Checkstyle: no space inside parentheses
[odlparent.git] / bundles4-test / src / main / java / org / opendaylight / odlparent / bundles4test / TestBundleDiag.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.odlparent.bundles4test;
9
10 import static java.util.concurrent.TimeUnit.MILLISECONDS;
11 import static java.util.concurrent.TimeUnit.SECONDS;
12 import static org.junit.Assert.fail;
13
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;
23
24 /**
25  * Utility to verify bundle diagnostic state from OSGi integration tests.
26  *
27  * @author Michael Vorburger.ch
28  */
29 public class TestBundleDiag {
30
31     private static final Logger LOG = LoggerFactory.getLogger(TestBundleDiag.class);
32
33     private final BundleContext bundleContext;
34     private final BundleService bundleService;
35
36     public TestBundleDiag(BundleContext bundleContext, BundleService bundleService) {
37         this.bundleContext = bundleContext;
38         this.bundleService = bundleService;
39     }
40
41     /**
42      * Does the equivalent of the "diag" CLI command, and fails the test if anything incl. bundle wiring is NOK.
43      *
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.
48      *
49      * @author Michael Vorburger, based on guidance from Christian Schneider
50      */
51     public void checkBundleDiagInfos(long timeout, TimeUnit timeoutUnit) {
52         try {
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());
62
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());
71
72             } else {
73                 // Inform the developer of the green SystemState.Active
74                 LOG.info(bundleInfos.getFullDiagnosticText());
75             }
76
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!
85         }
86     }
87
88     private void logBundleDiagInfos(BundleDiagInfos bundleInfos) {
89         try {
90             logOSGiServices();
91         } catch (IllegalStateException e) {
92             LOG.warn("logOSGiServices() failed (never mind); too late during shutdown already?", e);
93         }
94         for (String okBundleStateInfo : bundleInfos.getOkBundleStateInfoTexts()) {
95             LOG.info(okBundleStateInfo);
96         }
97         for (String whitelistedBundleStateInfo : bundleInfos.getWhitelistedBundleStateInfoTexts()) {
98             LOG.warn(whitelistedBundleStateInfo);
99         }
100         for (String nokBundleStateInfo : bundleInfos.getNokBundleStateInfoTexts()) {
101             LOG.error(nokBundleStateInfo);
102         }
103     }
104
105     private BundleDiagInfos getBundleDiagInfos() {
106         return BundleDiagInfos.forContext(bundleContext, bundleService);
107     }
108
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");
113         try {
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));
117             }
118         } catch (InvalidSyntaxException e) {
119             LOG.error("logOSGiServices() failed due to InvalidSyntaxException", e);
120         }
121     }
122
123 }