View Javadoc
1   package com.atlassian.plugin.loaders;
2   
3   import com.atlassian.plugin.ModuleDescriptor;
4   import com.atlassian.plugin.ModuleDescriptorFactory;
5   import com.atlassian.plugin.Permissions;
6   import com.atlassian.plugin.Plugin;
7   import com.atlassian.plugin.PluginArtifact;
8   import com.atlassian.plugin.PluginException;
9   import com.atlassian.plugin.PluginInformation;
10  import com.atlassian.plugin.PluginInternal;
11  import com.atlassian.plugin.impl.UnloadablePlugin;
12  import com.google.common.collect.ImmutableList;
13  import com.google.common.collect.ImmutableSet;
14  import com.google.common.collect.Iterables;
15  import org.junit.Before;
16  import org.junit.Test;
17  import org.junit.runner.RunWith;
18  import org.mockito.Mock;
19  import org.mockito.runners.MockitoJUnitRunner;
20  
21  import java.util.Set;
22  
23  import static org.hamcrest.Matchers.instanceOf;
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertSame;
26  import static org.junit.Assert.assertThat;
27  import static org.junit.Assert.assertTrue;
28  import static org.mockito.Matchers.any;
29  import static org.mockito.Mockito.doThrow;
30  import static org.mockito.Mockito.mock;
31  import static org.mockito.Mockito.times;
32  import static org.mockito.Mockito.verify;
33  import static org.mockito.Mockito.when;
34  
35  @RunWith(MockitoJUnitRunner.class)
36  public final class PermissionCheckingPluginLoaderTest {
37      private PermissionCheckingPluginLoader permissionCheckingPluginLoader;
38  
39      @Mock
40      private PluginLoader pluginLoader;
41  
42      @Mock
43      private ModuleDescriptorFactory moduleDescriptorFactory;
44  
45      @Before
46      public void setUp() {
47          permissionCheckingPluginLoader = new PermissionCheckingPluginLoader(pluginLoader);
48      }
49  
50      @Test
51      public void loadAllPluginsWithEmptyCollectionOfPlugins() {
52          when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of());
53          final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
54          assertTrue(Iterables.isEmpty(plugins));
55      }
56  
57      @Test
58      public void loadFoundPluginsWithEmptyCollectionOfPlugins() {
59          when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of());
60          final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
61          assertTrue(Iterables.isEmpty(plugins));
62      }
63  
64      @Test
65      public void loadFoundPluginsWithPluginWithoutExecuteJavaPermissionAndNoJava() {
66          final Plugin plugin = newPlugin(ImmutableSet.<String>of(), false, false);
67  
68          when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
69          final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
70  
71          assertEquals(1, Iterables.size(plugins));
72          assertSame(plugin, Iterables.get(plugins, 0));
73      }
74  
75      @Test
76      public void loadAllPluginsWithPluginWithoutExecuteJavaPermissionAndNoJava() {
77          final Plugin plugin = newPlugin(ImmutableSet.<String>of(), false, false);
78  
79          when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
80          final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
81  
82          assertEquals(1, Iterables.size(plugins));
83          assertSame(plugin, Iterables.get(plugins, 0));
84      }
85  
86      @Test
87      public void loadFoundPluginsWithPluginWithoutExecuteJavaPermissionAndSomeJava() {
88          final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, false);
89  
90          when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
91          final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
92  
93          assertEquals(1, Iterables.size(plugins));
94          assertTrue(Iterables.get(plugins, 0) instanceof UnloadablePlugin);
95      }
96  
97      @Test
98      public void loadAllPluginsWithPluginWithoutExecuteJavaPermissionAndSomeJava() {
99          final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, false);
100 
101         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
102         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
103 
104         assertEquals(1, Iterables.size(plugins));
105         assertTrue(Iterables.get(plugins, 0) instanceof UnloadablePlugin);
106     }
107 
108     @Test
109     public void loadAllPluginsWithUnloadablePluginThenRemoved() {
110         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, false);
111 
112         doThrow(new PluginException("cannot find plugin")).when(pluginLoader).removePlugin(any(Plugin.class));
113         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
114         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
115 
116         assertEquals(1, Iterables.size(plugins));
117         Plugin loadedPlugin = Iterables.get(plugins, 0);
118         assertTrue(loadedPlugin instanceof UnloadablePlugin);
119         permissionCheckingPluginLoader.removePlugin(loadedPlugin);
120     }
121 
122     @Test
123     public void loadAllPluginsWithGoodPluginThenDiscarded() throws Exception {
124         // We need to replace the object under test with a discardable loader. This could be structured better.
125         final DiscardablePluginLoader discardablePluginLoader = mock(DiscardablePluginLoader.class);
126         permissionCheckingPluginLoader = new PermissionCheckingPluginLoader(discardablePluginLoader);
127 
128         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, true);
129 
130         when(discardablePluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
131         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
132         permissionCheckingPluginLoader.discardPlugin(plugin);
133         verify(discardablePluginLoader).discardPlugin(plugin);
134     }
135 
136     @Test
137     public void loadAllPluginsWithUnloadablePluginThenDiscarded() {
138         // We need to replace the object under test with a discardable loader. This could be structured better.
139         final DiscardablePluginLoader discardablePluginLoader = mock(DiscardablePluginLoader.class);
140         permissionCheckingPluginLoader = new PermissionCheckingPluginLoader(discardablePluginLoader);
141 
142         final Plugin containsJavaButNoPermission = newPlugin(ImmutableSet.<String>of(), true, false);
143         final Plugin hasSystemButNoPermission = newPlugin(ImmutableSet.<String>of(), false, false);
144         addModuleDescriptor(hasSystemButNoPermission, true);
145 
146 
147         final Iterable<Plugin> pluginsToLoad = ImmutableList.<Plugin>of(containsJavaButNoPermission, hasSystemButNoPermission);
148         when(discardablePluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(pluginsToLoad);
149 
150         final Iterable<Plugin> loadedPlugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
151         // The actual plugin should be discarded when loadAllPlugins ignores it
152         for (final Plugin plugin : pluginsToLoad) {
153             verify(discardablePluginLoader).discardPlugin(plugin);
154         }
155 
156         assertEquals(Iterables.size(loadedPlugins), Iterables.size(pluginsToLoad));
157         for (final Plugin plugin : loadedPlugins) {
158             assertThat(plugin, instanceOf(UnloadablePlugin.class));
159             permissionCheckingPluginLoader.discardPlugin(plugin);
160         }
161         // I know .times() is frowned on, but i can't find another good way to do this in Mockito - i want to say
162         // the only discard calls were from the loadAllPlugins() above.
163         verify(discardablePluginLoader, times(Iterables.size(pluginsToLoad))).discardPlugin(any(Plugin.class));
164     }
165 
166     @Test
167     public void loadFoundPluginsWithGoodPluginThenDiscarded() throws Exception {
168         // We need to replace the object under test with a discardable loader. This could be structured better.
169         final DiscardablePluginLoader discardablePluginLoader = mock(DiscardablePluginLoader.class);
170         permissionCheckingPluginLoader = new PermissionCheckingPluginLoader(discardablePluginLoader);
171 
172         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, true);
173 
174         when(discardablePluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
175         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
176         permissionCheckingPluginLoader.discardPlugin(plugin);
177         verify(discardablePluginLoader).discardPlugin(plugin);
178     }
179 
180     @Test
181     public void loadFoundPluginsWithUnloadablePluginThenDiscarded() {
182         // We need to replace the object under test with a discardable loader. This could be structured better.
183         final DiscardablePluginLoader discardablePluginLoader = mock(DiscardablePluginLoader.class);
184         permissionCheckingPluginLoader = new PermissionCheckingPluginLoader(discardablePluginLoader);
185 
186         final Plugin containsJavaButNoPermission = newPlugin(ImmutableSet.<String>of(), true, false);
187         final Plugin hasSystemButNoPermission = newPlugin(ImmutableSet.<String>of(), false, false);
188         addModuleDescriptor(hasSystemButNoPermission, true);
189 
190 
191         final Iterable<Plugin> pluginsToLoad = ImmutableList.<Plugin>of(containsJavaButNoPermission, hasSystemButNoPermission);
192         when(discardablePluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(pluginsToLoad);
193 
194         final Iterable<Plugin> loadedPlugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
195         // The actual plugin should be discarded when loadFoundPlugins ignores it
196         for (final Plugin plugin : pluginsToLoad) {
197             verify(discardablePluginLoader).discardPlugin(plugin);
198         }
199 
200         assertEquals(Iterables.size(loadedPlugins), Iterables.size(pluginsToLoad));
201         for (final Plugin plugin : loadedPlugins) {
202             assertThat(plugin, instanceOf(UnloadablePlugin.class));
203             permissionCheckingPluginLoader.discardPlugin(plugin);
204         }
205         // I know .times() is frowned on, but i can't find another good way to do this in Mockito - i want to say
206         // the only discard calls were from the loadFoundPlugins() above.
207         verify(discardablePluginLoader, times(Iterables.size(pluginsToLoad))).discardPlugin(any(Plugin.class));
208     }
209 
210     @Test
211     public void loadAllPluginsWithPluginWithNoPermissionsAndSystemModules() throws Exception {
212         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), false, false);
213 
214         addModuleDescriptor(plugin, true);
215 
216         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
217         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
218 
219         assertEquals(1, Iterables.size(plugins));
220         assertTrue(Iterables.get(plugins, 0) instanceof UnloadablePlugin);
221     }
222 
223     @Test
224     public void loadAllPluginsWithPluginWithNoPermissionsAndNoSystemModules() throws Exception {
225         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), false, false);
226 
227         addModuleDescriptor(plugin, false);
228 
229         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
230         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
231 
232         assertEquals(1, Iterables.size(plugins));
233         assertSame(plugin, Iterables.get(plugins, 0));
234     }
235 
236     @Test
237     public void loadFoundPluginsWithPluginWithJavaPermissionAndSomeJava() throws Exception {
238         final Plugin plugin = newPlugin(ImmutableSet.<String>of(Permissions.EXECUTE_JAVA), true, false);
239 
240         when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
241         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
242 
243         assertEquals(1, Iterables.size(plugins));
244         assertSame(plugin, Iterables.get(plugins, 0));
245     }
246 
247     @Test
248     public void loadAllPluginsWithPluginWithCreateSystemModulePermissionsAndSystemModules() throws Exception {
249         final Plugin plugin = newPlugin(ImmutableSet.<String>of(Permissions.CREATE_SYSTEM_MODULES), false, false);
250 
251         addModuleDescriptor(plugin, true);
252 
253         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
254         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
255 
256         assertEquals(1, Iterables.size(plugins));
257         assertSame(plugin, Iterables.get(plugins, 0));
258     }
259 
260     @Test
261     public void loadAllPluginsWithPluginWithCreateSystemModulePermissionsAndNoSystemModules() throws Exception {
262         final Plugin plugin = newPlugin(ImmutableSet.<String>of(Permissions.CREATE_SYSTEM_MODULES), false, false);
263 
264         addModuleDescriptor(plugin, false);
265 
266         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
267         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
268 
269         assertEquals(1, Iterables.size(plugins));
270         assertSame(plugin, Iterables.get(plugins, 0));
271     }
272 
273     @Test
274     public void loadFoundPluginsWithPluginWithJavaPermissionAndNoJava() throws Exception {
275         final Plugin plugin = newPlugin(ImmutableSet.<String>of(Permissions.EXECUTE_JAVA), false, false);
276 
277         when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
278         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
279 
280         assertEquals(1, Iterables.size(plugins));
281         assertSame(plugin, Iterables.get(plugins, 0));
282     }
283 
284     @Test
285     public void loadAllPluginsWithPluginWithJavaPermissionAndNoJava() throws Exception {
286         final Plugin plugin = newPlugin(ImmutableSet.<String>of(Permissions.EXECUTE_JAVA), false, false);
287 
288         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
289         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
290 
291         assertEquals(1, Iterables.size(plugins));
292         assertSame(plugin, Iterables.get(plugins, 0));
293     }
294 
295     @Test
296     public void loadFoundPluginsWithPluginWithAllPermissionsAndSomeJava() throws Exception {
297         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, true);
298 
299         when(pluginLoader.loadFoundPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
300         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadFoundPlugins(moduleDescriptorFactory);
301 
302         assertEquals(1, Iterables.size(plugins));
303         assertSame(plugin, Iterables.get(plugins, 0));
304     }
305 
306     @Test
307     public void loadAllPluginsWithPluginWithAllPermissionsAndSomeJava() throws Exception {
308         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), true, true);
309 
310         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
311         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
312 
313         assertEquals(1, Iterables.size(plugins));
314         assertSame(plugin, Iterables.get(plugins, 0));
315     }
316 
317     @Test
318     public void loadAllPluginsWithPluginWithAllPermissionsAndSystemModules() throws Exception {
319         final Plugin plugin = newPlugin(ImmutableSet.<String>of(), false, true);
320         addModuleDescriptor(plugin, true);
321 
322         when(pluginLoader.loadAllPlugins(moduleDescriptorFactory)).thenReturn(ImmutableList.<Plugin>of(plugin));
323         final Iterable<Plugin> plugins = permissionCheckingPluginLoader.loadAllPlugins(moduleDescriptorFactory);
324 
325         assertEquals(1, Iterables.size(plugins));
326         assertSame(plugin, Iterables.get(plugins, 0));
327     }
328 
329     private void addModuleDescriptor(Plugin plugin, boolean system) {
330         ModuleDescriptor descriptor = mock(ModuleDescriptor.class);
331         when(descriptor.getKey()).thenReturn("foo");
332         when(descriptor.isSystemModule()).thenReturn(system);
333         when(plugin.getModuleDescriptors()).thenReturn(ImmutableList.<ModuleDescriptor<?>>of(descriptor));
334     }
335 
336     private Plugin newPlugin(Set<String> permissions, boolean hasJava, boolean hasAllPermissions) {
337         final PluginInternal plugin = mockPlugin(PluginInternal.class);
338         final PluginArtifact pluginArtifact = mock(PluginArtifact.class);
339         when(plugin.hasAllPermissions()).thenReturn(hasAllPermissions);
340         when(plugin.getActivePermissions()).thenReturn(permissions);
341         when(plugin.getPluginArtifact()).thenReturn(pluginArtifact);
342         when(pluginArtifact.containsJavaExecutableCode()).thenReturn(hasJava);
343         return plugin;
344     }
345 
346     private <P extends Plugin> P mockPlugin(Class<P> type) {
347         P mock = mock(type);
348         when(mock.getKey()).thenReturn("test-plugin-key");
349         when(mock.getName()).thenReturn("Test Plugin");
350         PluginInformation pluginInformation = mock(PluginInformation.class);
351         when(mock.getPluginInformation()).thenReturn(pluginInformation);
352         return mock;
353     }
354 }