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.osgi.util.OsgiSystemBundleUtil;
9 import junit.framework.TestCase;
10 import org.mockito.invocation.InvocationOnMock;
11 import org.mockito.stubbing.Answer;
12 import org.osgi.framework.Bundle;
13 import org.osgi.framework.BundleContext;
14 import org.osgi.framework.BundleException;
15 import org.osgi.framework.Constants;
16
17 import java.util.Dictionary;
18 import java.util.Hashtable;
19
20 import static org.mockito.Mockito.*;
21
22 public class TestOsgiPlugin extends TestCase
23 {
24 private Bundle bundle;
25 private OsgiPlugin plugin;
26 private BundleContext bundleContext;
27 private Bundle systemBundle;
28 private BundleContext systemBundleContext;
29 private Dictionary<String, String> dict;
30 private OsgiPluginHelper helper;
31
32 @Override
33 public void setUp()
34 {
35 bundle = mock(Bundle.class);
36 dict = new Hashtable<String, String>();
37 dict.put(Constants.BUNDLE_DESCRIPTION, "desc");
38 dict.put(Constants.BUNDLE_VERSION, "1.0");
39 when(bundle.getHeaders()).thenReturn(dict);
40 bundleContext = mock(BundleContext.class);
41 when(bundle.getBundleContext()).thenReturn(bundleContext);
42
43 systemBundle = mock(Bundle.class);
44 systemBundleContext = mock(BundleContext.class);
45 when(bundleContext.getBundle(OsgiSystemBundleUtil.SYSTEM_BUNDLE_ID)).thenReturn(systemBundle);
46 when(systemBundle.getBundleContext()).thenReturn(systemBundleContext);
47
48 helper = mock(OsgiPluginHelper.class);
49 when(helper.getBundle()).thenReturn(bundle);
50
51 plugin = new OsgiPlugin(mock(PluginEventManager.class), helper);
52 }
53
54 @Override
55 public void tearDown()
56 {
57 bundle = null;
58 plugin = null;
59 bundleContext = null;
60 }
61
62 public void testEnabled() throws BundleException
63 {
64 when(bundle.getState()).thenReturn(Bundle.RESOLVED);
65 plugin.enable();
66 verify(bundle).start();
67 }
68
69 public void testDisabled() throws BundleException
70 {
71 when(bundle.getState()).thenReturn(Bundle.ACTIVE);
72 plugin.disable();
73 verify(bundle).stop();
74 }
75
76 public void testDisabledOnNonDynamicPlugin() throws BundleException
77 {
78 plugin.addModuleDescriptor(new StaticModuleDescriptor());
79 plugin.onPluginFrameworkStartedEvent(null);
80 when(bundle.getState()).thenReturn(Bundle.ACTIVE);
81 plugin.disable();
82 verify(bundle, never()).stop();
83 }
84
85 public void testUninstall() throws BundleException
86 {
87 when(bundle.getState()).thenReturn(Bundle.ACTIVE);
88 plugin.uninstall();
89 assertEquals(plugin.getPluginState(), PluginState.UNINSTALLED);
90 }
91
92 public void testOnPluginContainerRefresh()
93 {
94 plugin.setKey("plugin-key");
95 when(bundle.getState()).thenReturn(Bundle.RESOLVED);
96 plugin.enable();
97 PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
98 plugin.onPluginContainerRefresh(event);
99 assertEquals(PluginState.ENABLED, plugin.getPluginState());
100 }
101
102 public void testQuickOnPluginContainerRefresh() throws BundleException, InterruptedException
103 {
104 plugin.setKey("plugin-key");
105 when(bundle.getState()).thenReturn(Bundle.RESOLVED);
106
107 final ConcurrentStateEngine states = new ConcurrentStateEngine("bundle-starting", "container-created", "bundle-started", "mid-start", "end");
108 when(bundle.getBundleContext()).thenAnswer(new Answer<Object>()
109 {
110 public Object answer(InvocationOnMock invocation) throws Throwable
111 {
112 states.tryNextState("bundle-started", "mid-start");
113 final BundleContext context = mock(BundleContext.class);
114 when(context.getBundle(OsgiSystemBundleUtil.SYSTEM_BUNDLE_ID)).thenReturn(systemBundle);
115
116 return context;
117 }
118 });
119
120 doAnswer(new Answer<Object>()
121 {
122 public Object answer(InvocationOnMock invocation) throws Throwable
123 {
124 states.state("bundle-starting");
125 Thread t = new Thread()
126 {
127 public void run()
128 {
129 PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
130 states.tryNextState("bundle-starting", "container-created");
131 plugin.onPluginContainerRefresh(event);
132 }
133 };
134 t.start();
135 states.tryNextState("container-created", "bundle-started");
136 return null;
137 }
138 }).when(bundle).start();
139
140 plugin.enable();
141
142
143 states.tryNextState("mid-start", "end");
144
145 assertEquals(PluginState.ENABLED, plugin.getPluginState());
146 }
147
148 public void testOnPluginContainerRefreshNotEnabling()
149 {
150 plugin.setKey("plugin-key");
151 PluginContainerRefreshedEvent event = new PluginContainerRefreshedEvent(new Object(), "plugin-key");
152 when(bundle.getState()).thenReturn(Bundle.ACTIVE);
153 plugin.disable();
154 plugin.onPluginContainerRefresh(event);
155 assertEquals(PluginState.DISABLED, plugin.getPluginState());
156 }
157
158 @RequiresRestart
159 public static class StaticModuleDescriptor extends AbstractModuleDescriptor<Object>
160 {
161 public Object getModule()
162 {
163 return null;
164 }
165 }
166 }