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
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
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
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
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 }