2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.odlparent.bundlestest;
10 import static java.util.concurrent.TimeUnit.MILLISECONDS;
11 import static java.util.concurrent.TimeUnit.SECONDS;
12 import static org.junit.Assert.fail;
14 import java.util.concurrent.TimeUnit;
15 import org.apache.karaf.bundle.core.BundleService;
16 import org.awaitility.Awaitility;
17 import org.awaitility.core.ConditionTimeoutException;
18 import org.osgi.framework.Bundle;
19 import org.osgi.framework.BundleContext;
20 import org.osgi.framework.InvalidSyntaxException;
21 import org.osgi.framework.ServiceReference;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Utility to verify bundle diagnostic state from OSGi integration tests.
28 * @author Michael Vorburger.ch
30 public class TestBundleDiag {
32 private static final Logger LOG = LoggerFactory.getLogger(TestBundleDiag.class);
34 private final BundleContext bundleContext;
35 private final BundleService bundleService;
37 public TestBundleDiag(BundleContext bundleContext, BundleService bundleService) {
38 this.bundleContext = bundleContext;
39 this.bundleService = bundleService;
43 * Does the equivalent of the "diag" CLI command, and fails the test if anything incl. bundle wiring is NOK.
45 * <p>The implementation is based on Karaf's BundleService, and not the BundleStateService,
46 * because each Karaf supported DI system (such as Blueprint and Declarative Services, see String constants
47 * in BundleStateService), will have a separate BundleStateService. The BundleService however will
48 * contain the combined status of all BundleStateServices.
50 * @author Michael Vorburger, based on guidance from Christian Schneider
52 public void checkBundleDiagInfos(long timeout, TimeUnit timeoutUnit) {
54 Awaitility.await("checkBundleDiagInfos")
55 .pollDelay(0, MILLISECONDS)
56 .pollInterval(1, SECONDS)
57 .atMost(timeout, timeoutUnit)
58 .conditionEvaluationListener(
59 condition -> LOG.info("checkBundleDiagInfos: Elapsed time {}s, remaining time {}s, {}",
60 condition.getElapsedTimeInMS() / 1000, condition.getRemainingTimeInMS() / 1000,
61 ((BundleDiagInfos) condition.getValue()).getFullDiagnosticText()))
62 .until(() -> getBundleDiagInfos(), new BundleServiceSummaryMatcher());
64 // If we're here then either BundleServiceSummaryMatcher quit because of Active, Failure or Stopping..
65 BundleDiagInfos bundleInfos = getBundleDiagInfos();
66 SystemState systemState = bundleInfos.getSystemState();
67 if (systemState.equals(SystemState.Failure) || systemState.equals(SystemState.Stopping)) {
68 LOG.error("diag failure; BundleService reports bundle(s) which failed or are already stopping"
69 + " (details in following INFO and ERROR log messages...)");
70 logBundleDiagInfos(bundleInfos);
71 fail(bundleInfos.getFullDiagnosticText());
74 // Inform the developer of the green SystemState.Active
75 LOG.info(bundleInfos.getFullDiagnosticText());
78 } catch (ConditionTimeoutException e) {
79 // If this happens then it got stuck waiting in SystemState.Booting,
80 // typically due to bundles still in BundleState GracePeriod or Waiting
81 LOG.error("diag failure; BundleService reports bundle(s) which are still not active"
82 + " (details in following INFO and ERROR log messages...)");
83 BundleDiagInfos bundleInfos = getBundleDiagInfos();
84 logBundleDiagInfos(bundleInfos);
85 throw e; // fail the test!
89 private void logBundleDiagInfos(BundleDiagInfos bundleInfos) {
92 } catch (IllegalStateException e) {
93 LOG.warn("logOSGiServices() failed (never mind); too late during shutdown already?", e);
95 for (String okBundleStateInfo : bundleInfos.getOkBundleStateInfoTexts()) {
96 LOG.info(okBundleStateInfo);
98 for (String whitelistedBundleStateInfo : bundleInfos.getWhitelistedBundleStateInfoTexts()) {
99 LOG.warn(whitelistedBundleStateInfo);
101 for (String nokBundleStateInfo : bundleInfos.getNokBundleStateInfoTexts()) {
102 LOG.error(nokBundleStateInfo);
106 private BundleDiagInfos getBundleDiagInfos() {
107 return BundleDiagInfos.forContext(bundleContext, bundleService);
110 private void logOSGiServices() {
111 ServiceReferenceUtil util = new ServiceReferenceUtil();
112 LOG.info("Now going to log all known services, to help diagnose root cause of "
113 + "diag failure BundleService reported bundle(s) which are not active");
115 for (ServiceReference<?> serviceRef : bundleContext.getAllServiceReferences(null, null)) {
116 Bundle bundle = serviceRef.getBundle();
117 // serviceRef.getBundle() can return null if the bundle was destroyed
118 if (bundle != null) {
119 LOG.info("{} defines OSGi Service {} used by {}", bundle.getSymbolicName(),
120 util.getProperties(serviceRef), util.getUsingBundleSymbolicNames(serviceRef));
122 LOG.trace("skipping reporting service reference as the underlying bundle is null");
125 } catch (InvalidSyntaxException e) {
126 LOG.error("logOSGiServices() failed due to InvalidSyntaxException", e);