View Javadoc
1   package com.atlassian.plugin.manager;
2   
3   
4   import com.atlassian.plugin.MockPluginAccessor;
5   import com.atlassian.plugin.Plugin;
6   import com.atlassian.plugin.PluginAccessor;
7   import com.atlassian.plugin.PluginController;
8   import com.atlassian.plugin.PluginDependencies;
9   import com.atlassian.plugin.PluginState;
10  import com.atlassian.plugin.exception.PluginExceptionInterception;
11  import com.google.common.collect.ImmutableSet;
12  import org.junit.Before;
13  import org.junit.Rule;
14  import org.junit.Test;
15  import org.junit.contrib.java.lang.system.RestoreSystemProperties;
16  import org.junit.runner.RunWith;
17  import org.junit.runners.Parameterized;
18  import org.mockito.Mock;
19  import org.mockito.junit.MockitoJUnit;
20  import org.mockito.junit.MockitoRule;
21  
22  import java.util.Arrays;
23  import java.util.Collection;
24  
25  import static org.hamcrest.MatcherAssert.assertThat;
26  import static org.hamcrest.Matchers.is;
27  import static org.hamcrest.Matchers.notNullValue;
28  import static org.mockito.Mockito.mock;
29  
30  @RunWith(Parameterized.class)
31  public class TestPluginEnablerTransitiveDeps {
32      @Parameterized.Parameters(name = "{index}: enable optional: {0}")
33      public static Collection<Object[]> data() {
34          return Arrays.asList(new Object[][]{
35                  {null},
36                  {Boolean.FALSE},
37                  {Boolean.TRUE}
38          });
39      }
40  
41      @Parameterized.Parameter
42      public Boolean enableOptional;
43  
44      @Rule
45      public MockitoRule mockito = MockitoJUnit.rule();
46      @Rule
47      public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
48  
49      @Mock
50      private PluginController pluginController;
51      @Mock
52      private PluginExceptionInterception pluginExceptionInterception;
53  
54      private PluginEnabler pluginEnabler;
55  
56      @Before
57      public void setUp() throws Exception {
58          if (enableOptional != null) {
59              System.setProperty(PluginEnabler.ENABLE_OPTIONAL_REQUIREMENTS, enableOptional ? "true" : "false");
60          } else {
61              System.clearProperty(PluginEnabler.ENABLE_OPTIONAL_REQUIREMENTS);
62              // expected to behave like false
63              enableOptional = false;
64          }
65      }
66  
67      private PluginAccessor mockAccessor(Plugin... plugins) {
68          final MockPluginAccessor accessor = new MockPluginAccessor();
69  
70          for (Plugin p : plugins) {
71              accessor.addPlugin(p);
72          }
73          return accessor;
74      }
75  
76      private void assertPluginState(PluginState expected, PluginAccessor accessor, String... keys) {
77          for (String key : keys) {
78              Plugin p = accessor.getPlugin(key);
79              assertThat("Plugin " + key + " not found", p, is(notNullValue()));
80              assertThat(p + " not in " + expected + " state", p.getPluginState(), is(expected));
81          }
82      }
83  
84      @Test
85      public void enablingPluginAlsoEnablesRequiredPluginsTransitively() {
86          final PluginAccessor accessor = mockAccessor(
87                  new PluginWithDeps("foo", "foo2"),
88                  new PluginWithDeps("foo2", "foo3"),
89                  new PluginWithDeps("foo3"));
90  
91          pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
92  
93          // Enable a single plugin, which will recursively enable all deps
94          pluginEnabler.enableAllRecursively(Arrays.asList(accessor.getPlugin("foo")));
95  
96          assertPluginState(PluginState.ENABLED, accessor, "foo", "foo2", "foo3");
97      }
98  
99      @Test
100     public void enablingPluginAlsoEnablesRequiredPluginsTransitivelyWithCycles() {
101         final PluginAccessor accessor = mockAccessor(
102                 new PluginWithDeps("foo", "foo2"),
103                 new PluginWithDeps("foo2", "foo3", "foo"),
104                 new PluginWithDeps("foo3", "foo2", "foo"));
105 
106         pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
107 
108         // Enable a single plugin, which will recursively enable all deps
109         pluginEnabler.enableAllRecursively(Arrays.asList(accessor.getPlugin("foo")));
110 
111         assertPluginState(PluginState.ENABLED, accessor, "foo", "foo2", "foo3");
112     }
113 
114     @Test
115     public void enablingPluginEnablesTransitivelyOptionalDependingOnSystemProperty() {
116         final PluginAccessor accessor = mockAccessor(
117                 new PluginWithDeps("foo", "mandatory1"),
118                 new PluginWithDeps("mandatory1", new PluginDependencies(
119                         ImmutableSet.of("mandatory2"),
120                         ImmutableSet.of("optional"),
121                         ImmutableSet.of("dynamic"))),
122                 new PluginWithDeps("mandatory2"),
123                 new PluginWithDeps("optional", "mandatory_for_optional"),
124                 new PluginWithDeps("dynamic", "mandatory_for_dynamic"),
125                 new PluginWithDeps("mandatory_for_optional"),
126                 new PluginWithDeps("mandatory_for_dynamic"));
127 
128         pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
129 
130         // Enable a single plugin, which will recursively enable all deps
131         pluginEnabler.enableAllRecursively(Arrays.asList(accessor.getPlugin("foo")));
132 
133         assertPluginState(PluginState.ENABLED, accessor, "foo", "mandatory1", "mandatory2");
134         assertPluginState(enableOptional ? PluginState.ENABLED : PluginState.DISABLED, accessor, "optional", "mandatory_for_optional");
135         assertPluginState(PluginState.DISABLED, accessor, "dynamic", "mandatory_for_dynamic");
136     }
137 }