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.BundleContext;
19 import org.osgi.framework.InvalidSyntaxException;
20 import org.osgi.framework.ServiceReference;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Utility to verify bundle diagnostic state from OSGi integration tests.
27 * @author Michael Vorburger.ch
29 public class TestBundleDiag {
31 private static final Logger LOG = LoggerFactory.getLogger(TestBundleDiag.class);
33 private final BundleContext bundleContext;
34 private final BundleService bundleService;
36 public TestBundleDiag(BundleContext bundleContext, BundleService bundleService) {
37 this.bundleContext = bundleContext;
38 this.bundleService = bundleService;
42 * Does the equivalent of the "diag" CLI command, and fails the test if anything incl. bundle wiring is NOK.
44 * <p>The implementation is based on Karaf's BundleService, and not the BundleStateService,
45 * because each Karaf supported DI system (such as Blueprint and Declarative Services, see String constants
46 * in BundleStateService), will have a separate BundleStateService. The BundleService however will
47 * contain the combined status of all BundleStateServices.
49 * @author Michael Vorburger, based on guidance from Christian Schneider
51 public void checkBundleDiagInfos(long timeout, TimeUnit timeoutUnit) {
53 Awaitility.await("checkBundleDiagInfos")
54 .pollDelay(0, MILLISECONDS)
55 .pollInterval(1, SECONDS)
56 .atMost(timeout, timeoutUnit)
57 .conditionEvaluationListener(
58 condition -> LOG.info("{} (elapsed time {}s, remaining time {}s)",
59 ((BundleDiagInfos) condition.getValue()).getSummaryText(),
60 condition.getElapsedTimeInMS() / 1000, condition.getRemainingTimeInMS() / 1000))
61 .until(() -> getBundleDiagInfos(), new BundleServiceSummaryMatcher());
63 // If we're here then either BundleServiceSummaryMatcher quit because of Active, Failure or Stopping..
64 BundleDiagInfos bundleInfos = getBundleDiagInfos();
65 SystemState systemState = bundleInfos.getSystemState();
66 if (systemState.equals(SystemState.Failure) || systemState.equals(SystemState.Stopping)) {
67 LOG.error("diag failure; BundleService reports bundle(s) which failed or are already stopping"
68 + " (details in following INFO and ERROR log messages...)");
69 logBundleDiagInfos(bundleInfos);
70 fail(bundleInfos.getFullDiagnosticText());
73 // Inform the developer of the green SystemState.Active
74 LOG.info(bundleInfos.getFullDiagnosticText());
77 } catch (ConditionTimeoutException e) {
78 // If this happens then it got stuck waiting in SystemState.Booting,
79 // typically due to bundles still in BundleState GracePeriod or Waiting
80 LOG.error("diag failure; BundleService reports bundle(s) which are still not active"
81 + " (details in following INFO and ERROR log messages...)");
82 BundleDiagInfos bundleInfos = getBundleDiagInfos();
83 logBundleDiagInfos(bundleInfos);
84 throw e; // fail the test!
88 private void logBundleDiagInfos(BundleDiagInfos bundleInfos) {
91 } catch (IllegalStateException e) {
92 LOG.warn("logOSGiServices() failed (never mind); too late during shutdown already?", e);
94 for (String okBundleStateInfo : bundleInfos.getOkBundleStateInfoTexts()) {
95 LOG.info(okBundleStateInfo);
97 for (String whitelistedBundleStateInfo : bundleInfos.getWhitelistedBundleStateInfoTexts()) {
98 LOG.warn(whitelistedBundleStateInfo);
100 for (String nokBundleStateInfo : bundleInfos.getNokBundleStateInfoTexts()) {
101 LOG.error(nokBundleStateInfo);
105 private BundleDiagInfos getBundleDiagInfos() {
106 return BundleDiagInfos.forContext(bundleContext, bundleService);
109 private void logOSGiServices() {
110 ServiceReferenceUtil util = new ServiceReferenceUtil();
111 LOG.info("Now going to log all known services, to help diagnose root cause of "
112 + "diag failure BundleService reported bundle(s) which are not active");
114 for (ServiceReference<?> serviceRef : bundleContext.getAllServiceReferences(null, null)) {
115 LOG.info("{} defines OSGi Service {} used by {}", serviceRef.getBundle().getSymbolicName(),
116 util.getProperties(serviceRef), util.getUsingBundleSymbolicNames(serviceRef));
118 } catch (InvalidSyntaxException e) {
119 LOG.error("logOSGiServices() failed due to InvalidSyntaxException", e);