1 package com.atlassian.plugin.manager;
2
3 import java.util.Arrays;
4 import java.util.HashSet;
5 import java.util.Set;
6
7 import com.atlassian.plugin.MockPluginAccessor;
8 import com.atlassian.plugin.Plugin;
9 import com.atlassian.plugin.PluginAccessor;
10 import com.atlassian.plugin.PluginController;
11 import com.atlassian.plugin.PluginException;
12 import com.atlassian.plugin.PluginState;
13 import com.atlassian.plugin.exception.PluginExceptionInterception;
14 import com.atlassian.plugin.impl.StaticPlugin;
15
16 import org.junit.Before;
17 import org.junit.Rule;
18 import org.junit.Test;
19 import org.junit.contrib.java.lang.system.RestoreSystemProperties;
20 import org.junit.runner.RunWith;
21 import org.mockito.Mock;
22 import org.mockito.runners.MockitoJUnitRunner;
23
24 import static com.atlassian.plugin.util.PluginUtils.ATLASSIAN_PLUGINS_ENABLE_WAIT;
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.hamcrest.Matchers.is;
27 import static org.hamcrest.Matchers.lessThan;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.withSettings;
31
32 @RunWith (MockitoJUnitRunner.class)
33 public class TestPluginEnabler
34 {
35 @Rule public RestoreSystemProperties restoreSystemProperties =
36 new RestoreSystemProperties(ATLASSIAN_PLUGINS_ENABLE_WAIT);
37
38 @Mock private PluginAccessor pluginAccessor;
39 @Mock private PluginController pluginController;
40 @Mock private PluginExceptionInterception pluginExceptionInterception;
41
42 private PluginEnabler pluginEnabler;
43
44 @Before
45 public void setUp()
46 {
47 pluginEnabler = new PluginEnabler(pluginAccessor, pluginController, pluginExceptionInterception);
48 }
49
50 @Test
51 public void enablePlugin()
52 {
53 final Plugin plugin = new MyPlugin("foo");
54
55 pluginEnabler.enable(Arrays.asList(plugin));
56 assertThat(plugin.getPluginState(), is(PluginState.ENABLED));
57 }
58
59 @Test
60 public void enableResolvesResolvablePlugins()
61 {
62 final Plugin resolvablePlugin = mock(Plugin.class, withSettings().extraInterfaces(Plugin.Resolvable.class));
63 pluginEnabler.enable(Arrays.asList(resolvablePlugin));
64 verify((Plugin.Resolvable) resolvablePlugin).resolve();
65 verify(resolvablePlugin).enable();
66 }
67
68 @Test
69 public void customTimeoutTimesOut()
70 {
71 final Plugin plugin = new MyPlugin("foo")
72 {
73 @Override
74 protected PluginState enableInternal() throws PluginException
75 {
76 return PluginState.ENABLING;
77 }
78 };
79
80 System.setProperty(ATLASSIAN_PLUGINS_ENABLE_WAIT, "1");
81 final long start = System.currentTimeMillis();
82 pluginEnabler = new PluginEnabler(mock(PluginAccessor.class), mock(PluginController.class), pluginExceptionInterception);
83 pluginEnabler.enable(Arrays.asList(plugin));
84 final long end = System.currentTimeMillis();
85 assertThat(end - start, lessThan(5000L));
86 assertThat(plugin.getPluginState(), is(PluginState.ENABLING));
87 }
88
89 @Test
90 public void enableMultiplePluginsWithDependencies()
91 {
92 final Plugin plugin = new MyPlugin("foo", "foo2");
93 final Plugin plugin2 = new MyPlugin("foo2", "foo3");
94 final Plugin plugin3 = new MyPlugin("foo3");
95
96 pluginEnabler.enable(Arrays.asList(plugin, plugin2, plugin3));
97 assertThat(plugin.getPluginState(), is(PluginState.ENABLED));
98 assertThat(plugin2.getPluginState(), is(PluginState.ENABLED));
99 assertThat(plugin3.getPluginState(), is(PluginState.ENABLED));
100 }
101
102 @Test
103 public void enablingPluginAlsoEnablesRequiredPluginsTransitively()
104 {
105 final Plugin plugin = new MyPlugin("foo", "foo2");
106 final Plugin plugin2 = new MyPlugin("foo2", "foo3");
107 final Plugin plugin3 = new MyPlugin("foo3");
108 final MockPluginAccessor accessor = new MockPluginAccessor();
109 accessor.addPlugin(plugin);
110 accessor.addPlugin(plugin2);
111 accessor.addPlugin(plugin3);
112
113 pluginEnabler = new PluginEnabler(accessor, mock(PluginController.class), pluginExceptionInterception);
114
115
116 pluginEnabler.enableAllRecursively(Arrays.asList(plugin));
117 assertThat(plugin.getPluginState(), is(PluginState.ENABLED));
118 assertThat(plugin2.getPluginState(), is(PluginState.ENABLED));
119 assertThat(plugin3.getPluginState(), is(PluginState.ENABLED));
120 }
121
122 @Test
123 public void canEnableCircularlyDependentPlugins()
124 {
125 final Plugin plugin = new MyPlugin("foo", "foo2");
126 final Plugin plugin2 = new MyPlugin("foo2", "foo3");
127 final Plugin plugin3 = new MyPlugin("foo3", "foo");
128
129 pluginEnabler.enable(Arrays.asList(plugin, plugin2, plugin3));
130 assertThat(plugin.getPluginState(), is(PluginState.ENABLED));
131 assertThat(plugin2.getPluginState(), is(PluginState.ENABLED));
132 assertThat(plugin3.getPluginState(), is(PluginState.ENABLED));
133 }
134
135 @Test
136 public void failedEnableIsPassedToPluginInterception()
137 {
138 final RuntimeException runtimeException = new RuntimeException();
139 final Plugin plugin = new MyPlugin("foo")
140 {
141 @Override
142 protected PluginState enableInternal() throws PluginException
143 {
144 throw runtimeException;
145 }
146 };
147
148 pluginEnabler.enable(Arrays.asList(plugin));
149 verify(pluginExceptionInterception).onEnableException(plugin, runtimeException);
150 }
151
152 public static class MyPlugin extends StaticPlugin
153 {
154 private final Set<String> deps;
155
156 public MyPlugin(final String key, final String... deps)
157 {
158 setKey(key);
159 this.deps = new HashSet<String>(Arrays.asList(deps));
160 setPluginState(PluginState.DISABLED);
161 }
162
163 @Override
164 public Set<String> getRequiredPlugins()
165 {
166 return deps;
167 }
168 }
169 }