View Javadoc

1   package com.atlassian.plugin.osgi.factory;
2   
3   import com.atlassian.plugin.PluginState;
4   import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
5   import com.atlassian.plugin.descriptors.RequiresRestart;
6   import com.atlassian.plugin.event.PluginEventManager;
7   import com.atlassian.plugin.event.events.PluginContainerRefreshedEvent;
8   import com.atlassian.plugin.module.ModuleFactory;
9   import com.atlassian.plugin.osgi.container.OsgiContainerException;
10  import com.atlassian.plugin.osgi.util.OsgiSystemBundleUtil;
11  import junit.framework.TestCase;
12  import org.mockito.invocation.InvocationOnMock;
13  import org.mockito.stubbing.Answer;
14  import org.osgi.framework.Bundle;
15  import org.osgi.framework.BundleContext;
16  import org.osgi.framework.BundleException;
17  import org.osgi.framework.Constants;
18  
19  import java.util.Dictionary;
20  import java.util.Hashtable;
21  
22  import static org.mockito.Mockito.*;
23  
24  public class TestOsgiPlugin extends TestCase
25  {
26      private Bundle bundle;
27      private OsgiPlugin plugin;
28      private BundleContext bundleContext;
29      private Bundle systemBundle;
30      private BundleContext systemBundleContext;
31      private Dictionary<String, String> dict;
32      private OsgiPluginHelper helper;
33  
34      @Override
35      public void setUp()
36      {
37          bundle = mock(Bundle.class);
38          dict = new Hashtable<String, String>();
39          dict.put(Constants.BUNDLE_DESCRIPTION, "desc");
40          dict.put(Constants.BUNDLE_VERSION, "1.0");
41          when(bundle.getHeaders()).thenReturn(dict);
42          bundleContext = mock(BundleContext.class);
43          when(bundle.getBundleContext()).thenReturn(bundleContext);
44  
45          systemBundle = mock(Bundle.class);
46          systemBundleContext = mock(BundleContext.class);
47          when(bundleContext.getBundle(OsgiSystemBundleUtil.SYSTEM_BUNDLE_ID)).thenReturn(systemBundle);
48          when(systemBundle.getBundleContext()).thenReturn(systemBundleContext);
49  
50          helper = mock(OsgiPluginHelper.class);
51          when(helper.getBundle()).thenReturn(bundle);
52  
53          plugin = new OsgiPlugin(mock(PluginEventManager.class), helper);
54      }
55  
56      @Override
57      public void tearDown()
58      {
59          bundle = null;
60          plugin = null;
61          bundleContext = null;
62      }
63  
64      public void testEnabled() throws BundleException
65      {
66          _enablePlugin();
67          verify(bundle).start();
68      }
69  
70      private void _enablePlugin() {
71          when(bundle.getState()).thenReturn(Bundle.RESOLVED);
72          plugin.enable();
73      }
74  
75      public void testDisabled() throws BundleException
76      {
77          when(bundle.getState()).thenReturn(Bundle.ACTIVE);
78          plugin.disable();
79          verify(bundle).stop();
80      }
81  
82      public void testDisabledOnNonDynamicPlugin() throws BundleException
83      {
84          plugin.addModuleDescriptor(new StaticModuleDescriptor());
85          plugin.onPluginFrameworkStartedEvent(null);
86          when(bundle.getState()).thenReturn(Bundle.ACTIVE);
87          plugin.disable();
88          verify(bundle, never()).stop();
89      }
90  
91      public void testUninstall() throws BundleException
92      {
93          _enablePlugin();
94          when(bundle.getState()).thenReturn(Bundle.ACTIVE);
95          _assertPluginUninstalled();
96      }
97  
98      public void testUninstallingUninstalledBundle() throws BundleException
99      {
100         _enablePlugin();
101         when(bundle.getState()).thenReturn(Bundle.ACTIVE).thenReturn(Bundle.UNINSTALLED);
102         _assertPluginUninstalled();
103         _assertPluginUninstalled();
104     }
105 
106     private void _assertPluginUninstalled() {
107         plugin.uninstallInternal();
108         assertEquals(plugin.getPluginState(), PluginState.UNINSTALLED);
109     }
110 
111     public void testOnPluginContainerRefresh()
112     {
113         plugin.setKey("plugin-key");
114         _enablePlugin();
115         PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
116         plugin.onPluginContainerRefresh(event);
117         assertEquals(PluginState.ENABLED, plugin.getPluginState());
118     }
119 
120     public void testQuickOnPluginContainerRefresh() throws BundleException, InterruptedException
121     {
122         plugin.setKey("plugin-key");
123         when(bundle.getState()).thenReturn(Bundle.RESOLVED);
124 
125         final ConcurrentStateEngine states = new ConcurrentStateEngine("bundle-starting", "container-created", "bundle-started", "mid-start", "end");
126         when(bundle.getBundleContext()).thenAnswer(new Answer<Object>()
127         {
128             public Object answer(InvocationOnMock invocation) throws Throwable
129             {
130                 states.tryNextState("bundle-started", "mid-start");
131                 final BundleContext context = mock(BundleContext.class);
132                 when(context.getBundle(OsgiSystemBundleUtil.SYSTEM_BUNDLE_ID)).thenReturn(systemBundle);
133 
134                 return context;
135             }
136         });
137 
138         doAnswer(new Answer<Object>()
139         {
140             public Object answer(InvocationOnMock invocation) throws Throwable
141             {
142                 states.state("bundle-starting");
143                 Thread t = new Thread()
144                 {
145                     public void run()
146                     {
147                         PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
148                         states.tryNextState("bundle-starting", "container-created");
149                         plugin.onPluginContainerRefresh(event);
150                     }
151                 };
152                 t.start();
153                 states.tryNextState("container-created", "bundle-started");
154                 return null;
155             }
156         }).when(bundle).start();
157 
158         plugin.enable();
159 
160 
161         states.tryNextState("mid-start", "end");
162 
163         assertEquals(PluginState.ENABLED, plugin.getPluginState());
164     }
165 
166     public void testOnPluginContainerRefreshNotEnabling()
167     {
168         plugin.setKey("plugin-key");
169         PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
170         when(bundle.getState()).thenReturn(Bundle.ACTIVE);
171         plugin.disable();
172         plugin.onPluginContainerRefresh(event);
173         assertEquals(PluginState.DISABLED, plugin.getPluginState());
174     }
175 
176     public void testUninstallRetryLogic() throws BundleException
177     {
178         try {
179             when(bundle.getState()).thenReturn(Bundle.ACTIVE);
180             plugin.enable();
181             when(bundle.getSymbolicName()).thenReturn("Mock Bundle");
182             doThrow(new BundleException("Mock Bundle Exception")).when(bundle).uninstall();
183             plugin.uninstallInternal();
184         } catch (Exception e) {
185             assertTrue("Should throw an OsgiContainerException", e instanceof OsgiContainerException);
186         } finally {
187             assertEquals(PluginState.ENABLED, plugin.getPluginState());
188             verify(bundle, times(3)).uninstall();
189         }
190     }
191 
192     @RequiresRestart
193     public static class StaticModuleDescriptor extends AbstractModuleDescriptor<Object>
194     {
195         public StaticModuleDescriptor()
196         {
197             super(ModuleFactory.LEGACY_MODULE_FACTORY);
198         }
199 
200         public Object getModule()
201         {
202             return null;
203         }
204     }
205 }