1 package com.atlassian.plugin.webresource;
2
3 import static com.google.common.collect.Iterables.isEmpty;
4 import static com.google.common.collect.Iterables.size;
5 import static org.mockito.Mockito.when;
6
7 import com.atlassian.plugin.ModuleDescriptor;
8 import com.atlassian.plugin.Plugin;
9 import com.atlassian.plugin.PluginAccessor;
10 import com.atlassian.plugin.elements.ResourceDescriptor;
11
12 import org.mockito.Mock;
13 import org.mockito.MockitoAnnotations;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21
22 import junit.framework.TestCase;
23
24 public class TestDefaultResourceDependencyResolver extends TestCase
25 {
26 @Mock
27 private WebResourceIntegration mockWebResourceIntegration;
28 @Mock
29 private PluginAccessor mockPluginAccessor;
30 @Mock
31 private ResourceBatchingConfiguration mockBatchingConfiguration;
32
33 private ResourceDependencyResolver dependencyResolver;
34
35 private Plugin testPlugin;
36 private final List<String> superBatchKeys = new ArrayList<String>();
37 private final List<WebResourceModuleDescriptor> moduleDescriptors = new ArrayList<WebResourceModuleDescriptor>();
38
39 @Override
40 protected void setUp() throws Exception
41 {
42 super.setUp();
43
44 testPlugin = TestUtils.createTestPlugin();
45
46 MockitoAnnotations.initMocks(this);
47 when(mockWebResourceIntegration.getPluginAccessor()).thenReturn(mockPluginAccessor);
48 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1");
49 when(mockPluginAccessor.getEnabledModuleDescriptorsByClass(WebResourceModuleDescriptor.class)).thenReturn(moduleDescriptors);
50 when(mockBatchingConfiguration.isSuperBatchingEnabled()).thenReturn(true);
51 when(mockBatchingConfiguration.getSuperBatchModuleCompleteKeys()).thenReturn(superBatchKeys);
52
53 dependencyResolver = new DefaultResourceDependencyResolver(mockWebResourceIntegration, mockBatchingConfiguration);
54 }
55
56 @Override
57 protected void tearDown() throws Exception
58 {
59 dependencyResolver = null;
60 mockWebResourceIntegration = null;
61 mockPluginAccessor = null;
62 mockBatchingConfiguration = null;
63
64 testPlugin = null;
65
66 super.tearDown();
67 }
68
69 public void testSuperBatchingNotEnabled()
70 {
71 when(mockBatchingConfiguration.isSuperBatchingEnabled()).thenReturn(true);
72 when(mockBatchingConfiguration.getSuperBatchModuleCompleteKeys()).thenReturn(superBatchKeys);
73
74 assertTrue(isEmpty(dependencyResolver.getSuperBatchDependencies()));
75 }
76
77 public void testGetSuperBatchDependenciesInOrder()
78 {
79 final String superBatchResource1 = "plugin.key:resource1";
80 final String superBatchResource2 = "plugin.key:resource2";
81 final String superBatchResource3 = "plugin.key:resource3";
82
83 superBatchKeys.add(superBatchResource1);
84 superBatchKeys.add(superBatchResource2);
85 superBatchKeys.add(superBatchResource3);
86
87 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1.0");
88
89 addModuleDescriptor(superBatchResource1);
90 addModuleDescriptor(superBatchResource2);
91 addModuleDescriptor(superBatchResource3);
92
93 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getSuperBatchDependencies();
94 assertNotNull(resources);
95 assertOrder(resources, superBatchResource1, superBatchResource2, superBatchResource3);
96 }
97
98 public void testGetSuperBatchDependenciesWithCylicDependency()
99 {
100 final String superBatchResource1 = "plugin.key:resource1";
101 final String superBatchResource2 = "plugin.key:resource2";
102
103 superBatchKeys.add(superBatchResource1);
104 superBatchKeys.add(superBatchResource2);
105
106 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1.0");
107
108 addModuleDescriptor(superBatchResource1, Arrays.asList(superBatchResource2));
109 addModuleDescriptor(superBatchResource2, Arrays.asList(superBatchResource1));
110
111 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getSuperBatchDependencies();
112 assertNotNull(resources);
113 assertOrder(resources, superBatchResource2, superBatchResource1);
114 }
115
116 public void testGetSuperBatchDependenciesWithDependencies()
117 {
118 final String superBatchResource1 = "test.atlassian:super1";
119 final String superBatchResource2 = "test.atlassian:super2";
120
121 superBatchKeys.add(superBatchResource1);
122 superBatchKeys.add(superBatchResource2);
123 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1.0");
124
125
126 final String resourceA = "test.atlassian:a";
127 final String resourceB = "test.atlassian:b";
128 final String resourceC = "test.atlassian:c";
129 final String resourceD = "test.atlassian:d";
130
131
132 addModuleDescriptor(resourceA);
133 addModuleDescriptor(resourceB);
134 addModuleDescriptor(superBatchResource1, Arrays.asList(resourceA, resourceB));
135
136
137 addModuleDescriptor(resourceD);
138 addModuleDescriptor(resourceC, Arrays.asList(resourceD));
139 addModuleDescriptor(superBatchResource2, Collections.singletonList(resourceC));
140
141 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getSuperBatchDependencies();
142 assertNotNull(resources);
143 assertOrder(resources, resourceA, resourceB, superBatchResource1, resourceD, resourceC, superBatchResource2);
144 }
145
146 public void testGetDependenciesExcludesSuperBatch()
147 {
148 final String superBatchResource1 = "test.atlassian:super1";
149 final String superBatchResource2 = "test.atlassian:super2";
150 final String moduleKey = "test.atlassian:foo";
151
152 superBatchKeys.add(superBatchResource1);
153 superBatchKeys.add(superBatchResource2);
154 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1.0");
155
156
157 addModuleDescriptor(moduleKey, Arrays.asList(superBatchResource1));
158 addModuleDescriptor(superBatchResource1);
159 addModuleDescriptor(superBatchResource2);
160
161 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependencies(moduleKey, true);
162 assertNotNull(resources);
163 assertOrder(resources, moduleKey);
164 }
165
166 public void testGetDependenciesIncludesSuperBatch()
167 {
168 final String superBatchResource1 = "test.atlassian:super1";
169 final String superBatchResource2 = "test.atlassian:super2";
170 final String moduleKey = "test.atlassian:foo";
171
172 superBatchKeys.add(superBatchResource1);
173 superBatchKeys.add(superBatchResource2);
174 when(mockWebResourceIntegration.getSuperBatchVersion()).thenReturn("1.0");
175
176
177 addModuleDescriptor(moduleKey, Arrays.asList(superBatchResource1));
178 addModuleDescriptor(superBatchResource1);
179 addModuleDescriptor(superBatchResource2);
180
181 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependencies(moduleKey, false);
182 assertNotNull(resources);
183 assertOrder(resources, superBatchResource1, moduleKey);
184 }
185
186 public void testGetDependenciesInContext()
187 {
188 final String moduleKey1 = "test.atlassian:foo";
189 final String moduleKey2 = "test.atlassian:bar";
190
191 final String context1 = "connie";
192 final Set<String> contexts1 = new HashSet<String>(Arrays.asList(context1));
193 final String context2 = "jira";
194 final Set<String> contexts2 = new HashSet<String>(Arrays.asList(context2));
195
196 addModuleDescriptor(moduleKey1, Collections.<String> emptyList(), contexts1);
197 addModuleDescriptor(moduleKey2, Collections.<String> emptyList(), contexts2);
198
199 Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context1);
200 assertOrder(resources, moduleKey1);
201
202 resources = dependencyResolver.getDependenciesInContext(context2);
203 assertOrder(resources, moduleKey2);
204 }
205
206 public void testGetDependenciesInContextWithMultipleEntries()
207 {
208 final String moduleKey1 = "test.atlassian:foo";
209 final String moduleKey2 = "test.atlassian:bar";
210
211 final String context = "connie";
212 final Set<String> contexts = new HashSet<String>(Arrays.asList(context));
213
214 addModuleDescriptor(moduleKey1, Collections.<String> emptyList(), contexts);
215 addModuleDescriptor(moduleKey2, Collections.<String> emptyList(), contexts);
216
217 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context);
218 assertOrder(resources, moduleKey1, moduleKey2);
219 }
220
221 public void testGetDependenciesInContextWithSharedDependenciesInDifferentContexts()
222 {
223 final String moduleKey1 = "test.atlassian:foo";
224 final String moduleKey2 = "test.atlassian:bar";
225 final String sharedModuleKey = "test.atlassian:shared";
226
227 final String context1 = "connie";
228 final Set<String> contexts1 = new HashSet<String>(Arrays.asList(context1));
229 final String context2 = "jira";
230 final Set<String> contexts2 = new HashSet<String>(Arrays.asList(context2));
231
232 addModuleDescriptor(moduleKey1, Arrays.asList(sharedModuleKey), contexts1);
233 addModuleDescriptor(moduleKey2, Arrays.asList(sharedModuleKey), contexts2);
234
235 addModuleDescriptor(sharedModuleKey);
236
237 Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context1);
238 assertOrder(resources, sharedModuleKey, moduleKey1);
239
240 resources = dependencyResolver.getDependenciesInContext(context2);
241 assertOrder(resources, sharedModuleKey, moduleKey2);
242 }
243
244 public void testGetDependenciesInContextWithSharedDependenciesInTheSameContext()
245 {
246 final String moduleKey1 = "test.atlassian:foo";
247 final String moduleKey2 = "test.atlassian:bar";
248 final String sharedModuleKey = "test.atlassian:shared";
249
250 final String context = "connie";
251 final Set<String> contexts = new HashSet<String>(Arrays.asList(context));
252
253 addModuleDescriptor(moduleKey1, Arrays.asList(sharedModuleKey), contexts);
254 addModuleDescriptor(moduleKey2, Arrays.asList(sharedModuleKey), contexts);
255
256 addModuleDescriptor(sharedModuleKey);
257
258 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context);
259 assertOrder(resources, sharedModuleKey, moduleKey1, moduleKey2);
260 }
261
262 public void testGetDependenciesInContextWithDuplicateResources()
263 {
264 final String moduleKey1 = "test.atlassian:foo";
265 final String parentModuleKey = "test.atlassian:parent";
266
267 final String context1 = "connie";
268 final Set<String> contexts1 = new HashSet<String>(Arrays.asList(context1));
269
270 addModuleDescriptor(parentModuleKey, Collections.<String> emptyList(), contexts1);
271 addModuleDescriptor(moduleKey1, Arrays.asList(parentModuleKey), contexts1);
272
273 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context1);
274 assertOrder(resources, parentModuleKey, moduleKey1);
275 }
276
277 public void testSkippedConditions() throws ClassNotFoundException
278 {
279 testPlugin = TestUtils.createTestPlugin("test.atlassian", "1", AlwaysTrueCondition.class, AlwaysFalseCondition.class);
280 final String moduleKey1 = "test.atlassian:foo";
281 final String parentModuleKey = "test.atlassian:parent";
282 final String skippedParentModuleKey = "test.atlassian:skipped-parent";
283 final String skippedModuleKey = "test.atlassian:skipped";
284
285 final String context1 = "connie";
286 final Set<String> contexts1 = new HashSet<String>(Arrays.asList(context1));
287
288 addModuleDescriptor(parentModuleKey, Collections.<String> emptyList(), contexts1);
289 addModuleDescriptor(moduleKey1, Arrays.asList(parentModuleKey), contexts1);
290 addModuleDescriptor(skippedParentModuleKey, Collections.<String> emptyList());
291
292 final WebResourceModuleDescriptor skippedModuleDescriptor = new WebResourceModuleDescriptorBuilder(testPlugin, "skipped").setCondition(
293 AlwaysTrueCondition.class).addDescriptor("skipped.js").addDependency(skippedParentModuleKey).addContext(context1).build();
294 addModuleDescriptor(skippedModuleDescriptor);
295
296 final Set<String> skippedResources = new HashSet<String>();
297 final Iterable<WebResourceModuleDescriptor> resources = dependencyResolver.getDependenciesInContext(context1, skippedResources);
298 assertOrder(resources, parentModuleKey, moduleKey1);
299
300
301 assertEquals(1, skippedResources.size());
302 assertEquals(skippedModuleKey, skippedResources.toArray()[0]);
303 }
304
305 private void addModuleDescriptor(final String moduleKey)
306 {
307 addModuleDescriptor(moduleKey, Collections.<String> emptyList());
308 }
309
310 private void addModuleDescriptor(final String moduleKey, final List<String> dependencies)
311 {
312 addModuleDescriptor(moduleKey, dependencies, Collections.<String> emptySet());
313 }
314
315 private void addModuleDescriptor(final String moduleKey, final List<String> dependencies, final Set<String> contexts)
316 {
317 final WebResourceModuleDescriptor webResourceModuleDescriptor = TestUtils.createWebResourceModuleDescriptor(moduleKey, testPlugin,
318 Collections.<ResourceDescriptor> emptyList(), dependencies, contexts);
319
320 addModuleDescriptor(webResourceModuleDescriptor);
321 }
322
323 private void addModuleDescriptor(final WebResourceModuleDescriptor webResourceModuleDescriptor)
324 {
325 moduleDescriptors.add(webResourceModuleDescriptor);
326
327 when(mockPluginAccessor.getEnabledPluginModule(webResourceModuleDescriptor.getCompleteKey())).thenReturn(
328 (ModuleDescriptor) webResourceModuleDescriptor);
329 }
330
331 private void assertOrder(final Iterable<WebResourceModuleDescriptor> resources, final String... expectedResources)
332 {
333 assertEquals(size(resources), expectedResources.length);
334
335 int i = 0;
336 for (final WebResourceModuleDescriptor resource : resources)
337 {
338 assertEquals(expectedResources[i], resource.getCompleteKey());
339 i++;
340 }
341 }
342 }