1 package com.atlassian.plugin.manager;
2
3 import com.atlassian.plugin.MockPluginAccessor;
4 import com.atlassian.plugin.Plugin;
5 import com.atlassian.plugin.PluginAccessor;
6 import com.atlassian.plugin.PluginController;
7 import com.atlassian.plugin.PluginDependencies;
8 import com.atlassian.plugin.PluginState;
9 import com.atlassian.plugin.exception.PluginExceptionInterception;
10 import com.google.common.collect.ImmutableSet;
11 import org.junit.Before;
12 import org.junit.Rule;
13 import org.junit.Test;
14 import org.junit.contrib.java.lang.system.RestoreSystemProperties;
15 import org.mockito.Mock;
16 import org.mockito.junit.MockitoJUnit;
17 import org.mockito.junit.MockitoRule;
18
19 import java.util.Collections;
20
21 import static org.hamcrest.MatcherAssert.assertThat;
22 import static org.hamcrest.Matchers.is;
23 import static org.hamcrest.Matchers.notNullValue;
24 import static org.mockito.Mockito.mock;
25
26 public class TestPluginEnablerTransitiveDeps {
27
28 @Rule
29 public final MockitoRule mockito = MockitoJUnit.rule();
30 @Rule
31 public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
32
33 @Mock
34 private PluginController pluginController;
35 @Mock
36 private PluginExceptionInterception pluginExceptionInterception;
37 private PluginEnabler pluginEnabler;
38
39 @Before
40 public void setUp() throws Exception {
41 }
42
43 private PluginAccessor mockAccessor(Plugin... plugins) {
44 final MockPluginAccessor accessor = new MockPluginAccessor();
45
46 for (Plugin p : plugins) {
47 accessor.addPlugin(p);
48 }
49 return accessor;
50 }
51
52 private void assertPluginState(PluginState expected, PluginAccessor accessor, String... keys) {
53 for (String key : keys) {
54 Plugin p = accessor.getPlugin(key);
55 assertThat("Plugin " + key + " not found", p, is(notNullValue()));
56 assertThat(p + " not in " + expected + " state", p.getPluginState(), is(expected));
57 }
58 }
59
60 @Test
61 public void enablingPluginAlsoEnablesRequiredPluginsTransitively() {
62 final PluginAccessor accessor = mockAccessor(
63 new PluginWithDeps("foo", "foo2"),
64 new PluginWithDeps("foo2", "foo3"),
65 new PluginWithDeps("foo3"));
66
67 pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
68
69
70 pluginEnabler.enableAllRecursively(Collections.singletonList(accessor.getPlugin("foo")));
71
72 assertPluginState(PluginState.ENABLED, accessor, "foo", "foo2", "foo3");
73 }
74
75 @Test
76 public void enablingPluginAlsoEnablesRequiredPluginsTransitivelyWithCycles() {
77 final PluginAccessor accessor = mockAccessor(
78 new PluginWithDeps("foo", "foo2"),
79 new PluginWithDeps("foo2", "foo3", "foo"),
80 new PluginWithDeps("foo3", "foo2", "foo"));
81
82 pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
83
84
85 pluginEnabler.enableAllRecursively(Collections.singletonList(accessor.getPlugin("foo")));
86
87 assertPluginState(PluginState.ENABLED, accessor, "foo", "foo2", "foo3");
88 }
89
90 @Test
91 public void enablingPluginDoesNotEnableTransitivelyOptionalDepending() {
92 final PluginAccessor accessor = mockAccessor(
93 new PluginWithDeps("foo", "mandatory1"),
94 new PluginWithDeps("mandatory1", new PluginDependencies(
95 ImmutableSet.of("mandatory2"),
96 ImmutableSet.of("optional"),
97 ImmutableSet.of("dynamic"))),
98 new PluginWithDeps("mandatory2"),
99 new PluginWithDeps("optional", "mandatory_for_optional"),
100 new PluginWithDeps("dynamic", "mandatory_for_dynamic"),
101 new PluginWithDeps("mandatory_for_optional"),
102 new PluginWithDeps("mandatory_for_dynamic"));
103
104 pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
105
106
107 pluginEnabler.enableAllRecursively(Collections.singletonList(accessor.getPlugin("foo")));
108
109 assertPluginState(PluginState.ENABLED, accessor, "foo", "mandatory1", "mandatory2");
110 assertPluginState(PluginState.DISABLED, accessor, "optional", "mandatory_for_optional");
111 assertPluginState(PluginState.DISABLED, accessor, "dynamic", "mandatory_for_dynamic");
112 }
113 }