View Javadoc
1   package com.atlassian.sal.core.lifecycle;
2   
3   import io.atlassian.fugue.Pair;
4   import com.atlassian.plugin.Plugin;
5   import com.atlassian.plugin.PluginAccessor;
6   import com.atlassian.plugin.PluginController;
7   import com.atlassian.plugin.event.PluginEventManager;
8   import com.atlassian.plugin.event.events.PluginEnabledEvent;
9   import com.atlassian.plugin.osgi.factory.OsgiPlugin;
10  import com.atlassian.sal.api.lifecycle.LifecycleAware;
11  import com.google.common.collect.ImmutableMap;
12  import org.junit.Before;
13  import org.mockito.Mock;
14  import org.mockito.invocation.InvocationOnMock;
15  import org.mockito.stubbing.Answer;
16  import org.osgi.framework.Bundle;
17  import org.osgi.framework.BundleContext;
18  import org.osgi.framework.ServiceEvent;
19  import org.osgi.framework.ServiceListener;
20  import org.osgi.framework.ServiceReference;
21  
22  import java.util.Hashtable;
23  
24  import static org.mockito.ArgumentMatchers.any;
25  import static org.mockito.ArgumentMatchers.anyString;
26  import static org.mockito.Mockito.doAnswer;
27  import static org.mockito.Mockito.mock;
28  import static org.mockito.Mockito.when;
29  
30  public class TestDefaultLifecycleManagerBase {
31      protected final String pluginKey = "pluginKey";
32  
33      @Mock
34      protected PluginEventManager pluginEventManager;
35      @Mock
36      protected PluginAccessor pluginAccessor;
37      @Mock
38      protected BundleContext bundleContext;
39  
40      @Mock
41      protected Bundle pluginBundle;
42      @Mock
43      protected PluginController pluginController;
44      protected ServiceListener serviceListener;
45  
46      protected boolean isApplicationSetup;
47      protected int notifyOnStartCalled;
48      protected DefaultLifecycleManager defaultLifecycleManager;
49  
50      @Before
51      public void setUp() throws Exception {
52          // Setup object under test
53  
54          isApplicationSetup = false;
55          defaultLifecycleManager = new DefaultLifecycleManager(pluginEventManager, pluginAccessor, bundleContext) {
56              @Override
57              public boolean isApplicationSetUp() {
58                  return isApplicationSetup;
59              }
60  
61              @Override
62              protected void notifyOnStart() {
63                  super.notifyOnStart();
64                  ++notifyOnStartCalled;
65              }
66          };
67  
68          // Setup recurrent fixtures
69  
70          pluginBundle = mockBundle(pluginKey);
71          // We need to use an answer here so we get serviceListener set during the call to facilitate race condition tests, and for
72          // the same reason we can't use a vanilla ArgumentCaptor here (with polluting every serviceListener usage site).
73          final Answer answer = new Answer() {
74              @Override
75              public Object answer(final InvocationOnMock invocation) throws Throwable {
76                  serviceListener = (ServiceListener) invocation.getArguments()[0];
77                  return null;
78              }
79          };
80          doAnswer(answer).when(bundleContext).addServiceListener(any(ServiceListener.class), anyString());
81      }
82  
83      protected void enablePlugin(final String pluginKey) {
84          // Mark plugin enabled in accessor ...
85          when(pluginAccessor.isPluginEnabled(pluginKey)).thenReturn(true);
86          // ... and fire the event
87          defaultLifecycleManager.onPluginEnabled(new PluginEnabledEvent(mock(Plugin.class)));
88      }
89  
90      protected Bundle mockBundle(final String pluginKey) {
91          final Bundle bundle = mock(Bundle.class);
92          final ImmutableMap<String, String> headers = ImmutableMap.<String, String>builder()
93                  .put(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, pluginKey)
94                  .build();
95          when(bundle.getHeaders()).thenReturn(new Hashtable<String, String>(headers));
96          return bundle;
97      }
98  
99      protected Pair<LifecycleAware, ServiceReference<LifecycleAware>> mockLifecycleAwareAndRegisterService(final Bundle bundle, Class<LifecycleAware> classToMock) {
100         final LifecycleAware lifecycleAware = mock(classToMock);
101         ServiceReference<LifecycleAware> service = registerService(bundle, lifecycleAware);
102         return new Pair(lifecycleAware, service);
103     }
104 
105     protected ServiceReference<LifecycleAware> registerService(final Bundle bundle, final LifecycleAware lifecycleAware) {
106         @SuppressWarnings("unchecked")
107         // Mocking generics requires the unchecked cast
108         final ServiceReference<LifecycleAware> serviceReference = mock(ServiceReference.class);
109         when(serviceReference.getBundle()).thenReturn(bundle);
110         when(bundleContext.getService(serviceReference)).thenReturn(lifecycleAware);
111         // Only send the ServiceEvent if we've been initialized, which is mean serviceListener has been set
112         if (null != serviceListener) {
113             serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, serviceReference));
114         }
115         return serviceReference;
116     }
117 
118     protected void unregisterService(final ServiceReference serviceReference) {
119         // Only send the ServiceEvent if we've been initialized, which is mean serviceListener has been set
120         if (null != serviceListener) {
121             serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, serviceReference));
122         }
123         when(serviceReference.getBundle()).thenReturn(null);
124     }
125 }