/*
* Copyright (C) 2011 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.gatein.portal.controller.resource.script;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import org.exoplatform.commons.utils.I18N;
import org.exoplatform.component.test.BaseGateInTest;
import org.exoplatform.portal.resource.InvalidResourceException;
import org.exoplatform.web.application.javascript.DependencyDescriptor;
import org.exoplatform.web.application.javascript.DuplicateResourceKeyException;
import org.exoplatform.web.application.javascript.ScriptResourceDescriptor;
import org.exoplatform.web.controller.QualifiedName;
import org.gatein.common.util.Tools;
import org.gatein.portal.controller.resource.ResourceId;
import org.gatein.portal.controller.resource.ResourceRequestHandler;
import org.gatein.portal.controller.resource.ResourceScope;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
*/
public class TestScriptGraph extends BaseGateInTest {
private static final String CONTEXT_PATH_1 = "/my-app-1";
private static final String CONTEXT_PATH_2 = "/my-app-2";
private static final String CONTEXT_PATH_3 = "/my-app-3";
private static final String CONTEXT_PATH_4 = "/my-app-4";
private static final String CONTEXT_PATH_5 = "/my-app-5";
private static final String CONTEXT_PATH_6 = "/my-app-6";
private static final String CONTEXT_PATH_7 = "/my-app-7";
/** . */
private static final ResourceId A = new ResourceId(ResourceScope.SHARED, "A");
/** . */
private static final ResourceId B = new ResourceId(ResourceScope.SHARED, "B");
/** . */
private static final ResourceId C = new ResourceId(ResourceScope.SHARED, "C");
/** . */
private static final ResourceId D = new ResourceId(ResourceScope.PORTAL, "D");
private static final ResourceId E = new ResourceId(ResourceScope.SHARED, "E");
private static final ResourceId F = new ResourceId(ResourceScope.SHARED, "F");
private static final ResourceId G = new ResourceId(ResourceScope.SHARED, "G");
private static final String GROUP_1 = "group1";
private static final String GROUP_2 = "group2";
private static ResourceId id(ResourceScope scope) {
return new ResourceId(scope, "test_"+ scope.name());
}
private static ScriptResourceDescriptor immediate(ResourceId rid) {
return new ScriptResourceDescriptor(rid, FetchMode.IMMEDIATE);
}
private static ScriptResourceDescriptor onLoad(ResourceId rid) {
return new ScriptResourceDescriptor(rid, FetchMode.ON_LOAD);
}
private static ScriptResourceDescriptor addDep(ScriptResourceDescriptor desc, ResourceId depId) {
DependencyDescriptor dependency = new DependencyDescriptor(depId, null, null);
desc.getDependencies().add(dependency);
return desc;
}
public void testAddRemoveEmpty() throws InvalidResourceException {
ScriptGraph initial = ScriptGraph.empty().validate();
for (ResourceScope scope : ResourceScope.values()) {
Collection<ScriptResource> scopeValues = initial.getResources(scope);
assertEquals(0, scopeValues.size());
}
for (ResourceScope scope : ResourceScope.values()) {
ResourceId id = id(scope);
ScriptGraph afterAdd = initial.add(CONTEXT_PATH_1, Arrays.asList(immediate(id))).validate();
Collection<ScriptResource> scopeValues = afterAdd.getResources(scope);
assertEquals(1, scopeValues.size());
assertEquals(id, afterAdd.getResource(id).getId());
ScriptGraph afterRemoveNonExistent = afterAdd.remove(CONTEXT_PATH_2).validate();
scopeValues = afterRemoveNonExistent.getResources(scope);
assertEquals(1, scopeValues.size());
assertEquals(id, afterAdd.getResource(id).getId());
ScriptGraph afterRemove = afterAdd.remove(CONTEXT_PATH_1).validate();
scopeValues = afterRemove.getResources(scope);
assertEquals(0, scopeValues.size());
assertNull(afterRemove.getResource(id));
}
}
public void testSelfDependency() throws InvalidResourceException {
ScriptGraph initial = ScriptGraph.empty();
ScriptGraph afterAdd = initial.add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), A)
)).validate();
/* assert that self-dep has no effect */
assertEquals(0, afterAdd.getResource(A).getDependencies().size());
assertEquals(0, afterAdd.getResource(A).getClosure().size());
}
public void testDetectTwoNodeCycle() {
ScriptGraph initial = ScriptGraph.empty();
try {
initial.add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(B), A)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
expected.printStackTrace();
}
}
public void testDetectThreeNodeCycle() {
ScriptGraph initial = ScriptGraph.empty();
try {
initial.add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(B), C),
addDep(immediate(C), A)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
}
public void testUnavailableDependency() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(B), C),
immediate(C)
)).validate();
try {
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
addDep(immediate(D), A),
addDep(immediate(E), F)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
}
public void testClosureAndDependencies() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(B), C),
immediate(C)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
assertEquals(Tools.toSet(B), a.getDependencies());
assertEquals(Tools.toSet(C), b.getDependencies());
assertEquals(Collections.emptySet(), c.getDependencies());
assertEquals(Tools.toSet(B, C), a.getClosure());
assertEquals(Tools.toSet(C), b.getClosure());
assertEquals(Collections.emptySet(), c.getClosure());
ScriptGraph afterRemove = graph.remove(CONTEXT_PATH_1).validate();
/* C should be away from everywhere */
assertNull(afterRemove.getResource(A));
assertNull(afterRemove.getResource(B));
assertNull(afterRemove.getResource(C));
}
public void testCrossContextClosure() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
immediate(C)
)).validate();
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(B), C)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
assertEquals(Tools.toSet(B), a.getDependencies());
assertEquals(Tools.toSet(C), b.getDependencies());
assertEquals(Collections.emptySet(), c.getDependencies());
assertEquals(Tools.toSet(B, C), a.getClosure());
assertEquals(Tools.toSet(C), b.getClosure());
assertEquals(Collections.emptySet(), c.getClosure());
ScriptGraph afterRemove = graph.remove(CONTEXT_PATH_1).validate();
/* C should be still there as B's stale dependency */
assertEquals(Tools.toSet(C), afterRemove.getResource(B).getDependencies());
/* But C should be away from the graph and closures */
assertNull(afterRemove.getResource(C));
assertEquals(Tools.toSet(B), afterRemove.getResource(A).getClosure());
assertEquals(Collections.emptySet(), afterRemove.getResource(B).getClosure());
}
public void testCrossContextClosureWith3Contexts() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
immediate(C)
)).validate();
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
addDep(immediate(B), C)
)).validate();
graph = graph.add(CONTEXT_PATH_3, Arrays.asList(
addDep(immediate(A), B)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
assertEquals(Tools.toSet(B), a.getDependencies());
assertEquals(Tools.toSet(C), b.getDependencies());
assertEquals(Collections.emptySet(), c.getDependencies());
assertEquals(Tools.toSet(B, C), a.getClosure());
assertEquals(Tools.toSet(C), b.getClosure());
assertEquals(Collections.emptySet(), c.getClosure());
ScriptGraph afterRemove = graph.remove(CONTEXT_PATH_2).validate();
/* B should be still there as A's stale dependency */
assertEquals(Tools.toSet(B), afterRemove.getResource(A).getDependencies());
/* But B should be away from the graph and closures */
assertNull(afterRemove.getResource(B));
assertEquals(Collections.emptySet(), afterRemove.getResource(A).getClosure());
assertEquals(Collections.emptySet(), afterRemove.getResource(C).getClosure());
}
public void testCrossContextClosureWith3ContextsMultipathSemidirect() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
immediate(C)
)).validate();
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
addDep(immediate(B), C)
)).validate();
ScriptResourceDescriptor aDesc = immediate(A);
aDesc.getDependencies().add(new DependencyDescriptor(B, null, null));
aDesc.getDependencies().add(new DependencyDescriptor(C, null, null));
graph = graph.add(CONTEXT_PATH_3, Arrays.asList(
aDesc
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
assertEquals(Tools.toSet(B, C), a.getDependencies());
assertEquals(Tools.toSet(C), b.getDependencies());
assertEquals(Collections.emptySet(), c.getDependencies());
assertEquals(Tools.toSet(B, C), a.getClosure());
assertEquals(Tools.toSet(C), b.getClosure());
assertEquals(Collections.emptySet(), c.getClosure());
ScriptGraph afterRemove = graph.remove(CONTEXT_PATH_2).validate();
/* B should be still there as A's stale dependency */
assertEquals(Tools.toSet(B, C), afterRemove.getResource(A).getDependencies());
/* But B should be away from the graph and closures */
assertNull(afterRemove.getResource(B));
/* C should still be there as it is A's direct dependency */
assertEquals(Tools.toSet(C), afterRemove.getResource(A).getClosure());
assertEquals(Collections.emptySet(), afterRemove.getResource(C).getClosure());
}
/**
* Let's have a graph like this where each node comes from a separate application and remove C
* <pre><blockquote>
A -> B -> C -> D -> E
\ ^
`-----> F -----> G ----ยด
</blockquote></pre> *
* @throws InvalidResourceException
*/
public void testCrossContextClosureWith3ContextsMultipathIndirect() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
immediate(E)
)).validate();
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
addDep(immediate(D), E)
)).validate();
graph = graph.add(CONTEXT_PATH_3, Arrays.asList(
addDep(immediate(C), D)
)).validate();
graph = graph.add(CONTEXT_PATH_4, Arrays.asList(
addDep(immediate(B), C)
)).validate();
graph = graph.add(CONTEXT_PATH_7, Arrays.asList(
addDep(immediate(G), E)
)).validate();
graph = graph.add(CONTEXT_PATH_6, Arrays.asList(
addDep(immediate(F), G)
)).validate();
ScriptResourceDescriptor aDesc = immediate(A);
aDesc.getDependencies().add(new DependencyDescriptor(B, null, null));
aDesc.getDependencies().add(new DependencyDescriptor(F, null, null));
graph = graph.add(CONTEXT_PATH_5, Arrays.asList(
aDesc
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
ScriptResource d = graph.getResource(D);
ScriptResource e = graph.getResource(E);
ScriptResource f = graph.getResource(F);
ScriptResource g = graph.getResource(G);
assertEquals(Tools.toSet(B, F), a.getDependencies());
assertEquals(Tools.toSet(C), b.getDependencies());
assertEquals(Tools.toSet(D), c.getDependencies());
assertEquals(Tools.toSet(E), d.getDependencies());
assertEquals(Collections.emptySet(), e.getDependencies());
assertEquals(Tools.toSet(G), f.getDependencies());
assertEquals(Tools.toSet(E), g.getDependencies());
assertEquals(Tools.toSet(B, C, D, E, F, G), a.getClosure());
assertEquals(Tools.toSet(C, D, E), b.getClosure());
assertEquals(Tools.toSet(D, E), c.getClosure());
assertEquals(Tools.toSet(E), d.getClosure());
assertEquals(Collections.emptySet(), e.getClosure());
assertEquals(Tools.toSet(G, E), f.getClosure());
assertEquals(Tools.toSet(E), g.getClosure());
/* this is the operation we test */
graph = graph.remove(CONTEXT_PATH_3).validate();
assertEquals(Tools.toSet(B, F), graph.getResource(A).getDependencies());
/* C should be still there as B's stale dependency */
assertEquals(Tools.toSet(C), graph.getResource(B).getDependencies());
/* But C should be away from the graph and closures */
assertNull(graph.getResource(C));
assertEquals(Tools.toSet(E), graph.getResource(D).getDependencies());
assertEquals(Collections.emptySet(), graph.getResource(E).getDependencies());
assertEquals(Tools.toSet(G), graph.getResource(F).getDependencies());
assertEquals(Tools.toSet(E), graph.getResource(G).getDependencies());
/* Both C and D should disappear from A' closure */
assertEquals(Tools.toSet(B, E, F, G), graph.getResource(A).getClosure());
/* B has no non-stale deps, so it should have empty closure */
assertEquals(Collections.emptySet(), graph.getResource(B).getClosure());
assertEquals(Tools.toSet(E), graph.getResource(D).getClosure());
assertEquals(Collections.emptySet(), graph.getResource(E).getClosure());
assertEquals(Tools.toSet(G, E), graph.getResource(F).getClosure());
assertEquals(Tools.toSet(E), graph.getResource(G).getClosure());
}
/**
* Closure of any node depends on node relationships in graph but does not depend on the order of building graph nodes
* @throws InvalidResourceException
*/
public void testBuildingOrder() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
addDep(immediate(C), D),
addDep(immediate(B), C),
immediate(D)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
ScriptResource d = graph.getResource(D);
assertEquals(Tools.toSet(D), c.getClosure());
assertEquals(Tools.toSet(C, D), b.getClosure());
assertEquals(Tools.toSet(B, C, D), a.getClosure());
assertEquals(Collections.emptySet(), d.getClosure());
}
public void testFetchMode() throws InvalidResourceException {
try {
ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(onLoad(A), C),
immediate(B),
immediate(C)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
onLoad(A),
addDep(immediate(B), C),
immediate(C)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
ScriptResource c = graph.getResource(C);
Map<ScriptResource, FetchMode> resolution = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, null));
assertResultOrder(resolution.keySet());
assertEquals(1, resolution.size());
assertEquals(Tools.toSet(a), resolution.keySet());
//
resolution = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(B, null));
assertResultOrder(resolution.keySet());
assertEquals(2, resolution.size());
assertEquals(Tools.toSet(b, c), resolution.keySet());
assertEquals(FetchMode.IMMEDIATE, resolution.get(b));
assertEquals(FetchMode.IMMEDIATE, resolution.get(c));
//
LinkedHashMap<ResourceId, FetchMode> pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(A, null);
pairs.put(B, null);
resolution = graph.resolve(pairs);
assertResultOrder(resolution.keySet());
assertEquals(3, resolution.size());
assertEquals(Tools.toSet(a, b, c), resolution.keySet());
assertEquals(FetchMode.ON_LOAD, resolution.get(a));
assertEquals(FetchMode.IMMEDIATE, resolution.get(b));
assertEquals(FetchMode.IMMEDIATE, resolution.get(c));
}
// ********
public void testResolveDefaultOnLoadFetchMode() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(onLoad(A))).validate();
ScriptResource a = graph.getResource(A);
// Use default fetch mode
Map<ScriptResource, FetchMode> test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, null));
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(a));
// Get resource with with same fetch-mode
test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, FetchMode.ON_LOAD));
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(a));
// Don't get resource with other fetch-mode
test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, FetchMode.IMMEDIATE));
assertEquals(0, test.size());
}
public void testResolveDefaultImmediateFetchMode() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(immediate(A))).validate();
ScriptResource a = graph.getResource(A);
// Use default fetch mode
Map<ScriptResource, FetchMode> test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, null));
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a), test.keySet());
assertEquals(FetchMode.IMMEDIATE, test.get(a));
// Dont' get resource with other fetch-mode
test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, FetchMode.ON_LOAD));
assertEquals(0, test.keySet().size());
// Get resource with the same fetch-mode
test = graph.resolve(Collections.<ResourceId, FetchMode> singletonMap(A, FetchMode.IMMEDIATE));
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a), test.keySet());
assertEquals(FetchMode.IMMEDIATE, test.get(a));
}
public void testResolveDependency1() throws InvalidResourceException {
try {
ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
onLoad(B)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
immediate(A),
onLoad(B)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
//
LinkedHashMap<ResourceId, FetchMode> pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(A, null);
pairs.put(B, null);
Map<ScriptResource, FetchMode> test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a, b), test.keySet());
assertEquals(FetchMode.IMMEDIATE, test.get(a));
assertEquals(FetchMode.ON_LOAD, test.get(b));
//
pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(B, null);
pairs.put(A, null);
test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a, b), test.keySet());
assertEquals(FetchMode.IMMEDIATE, test.get(a));
assertEquals(FetchMode.ON_LOAD, test.get(b));
//
pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(B, null);
test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(b), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(b));
}
public void testResolveDependency2() throws InvalidResourceException {
try {
ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(onLoad(A), B),
immediate(B)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
onLoad(A),
immediate(B)
)).validate();
ScriptResource a = graph.getResource(A);
ScriptResource b = graph.getResource(B);
//
LinkedHashMap<ResourceId, FetchMode> pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(A, null);
Map<ScriptResource, FetchMode> test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(a));
//
pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(A, null);
pairs.put(B, null);
test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a, b), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(a));
assertEquals(FetchMode.IMMEDIATE, test.get(b));
//
pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(B, null);
pairs.put(A, null);
test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(a, b), test.keySet());
assertEquals(FetchMode.ON_LOAD, test.get(a));
assertEquals(FetchMode.IMMEDIATE, test.get(b));
//
pairs = new LinkedHashMap<ResourceId, FetchMode>();
pairs.put(B, null);
test = graph.resolve(pairs);
assertResultOrder(test.keySet());
assertEquals(Tools.toSet(b), test.keySet());
assertEquals(FetchMode.IMMEDIATE, test.get(b));
}
public void testResolveDisjointDependencies() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), C),
immediate(B),
immediate(C)
)).validate();
// Yes all permutations
ResourceId[][] samples = { { A }, { A, B }, { B, A }, { A, B, C }, { A, C, B }, { B, A, C }, { B, C, A }, { C, A, B },
{ C, B, A }, };
//
LinkedHashMap<ResourceId, FetchMode> pairs = new LinkedHashMap<ResourceId, FetchMode>();
for (ResourceId[] sample : samples) {
pairs.clear();
for (ResourceId id : sample) {
pairs.put(id, null);
}
Map<ScriptResource, FetchMode> test = graph.resolve(pairs);
assertResultOrder(test.keySet());
}
}
public void testCrossDependency() {
// Scripts and Module can't depend on each other
try {
ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(immediate(A), B),
onLoad(B)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
try {
ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
addDep(onLoad(A), B),
immediate(B)
)).validate();
fail("InvalidResourceException expected");
} catch (InvalidResourceException expected) {
}
}
public void testDuplicateResource() throws InvalidResourceException {
ScriptGraph graph = ScriptGraph.empty();
ResourceId shared = new ResourceId(ResourceScope.SHARED, "foo");
graph = graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(shared))).validate();
try {
graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(shared))).validate();
fail("DuplicateResourceKeyException expected");
} catch (DuplicateResourceKeyException expected) {
}
ResourceId portlet = new ResourceId(ResourceScope.PORTLET, "foo");
graph = graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(portlet))).validate();
try {
graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(portlet))).validate();
fail("DuplicateResourceKeyException expected");
} catch (DuplicateResourceKeyException expected) {
}
ResourceId portal = new ResourceId(ResourceScope.PORTAL, "foo");
graph = graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(portal))).validate();
try {
graph.add(CONTEXT_PATH_1, Arrays.asList(immediate(portal))).validate();
fail("DuplicateResourceKeyException expected");
} catch (DuplicateResourceKeyException expected) {
}
}
/**
* Similar to {@link #testDuplicateResource()}.
*/
public void testAddDuplicate() throws InvalidResourceException {
ScriptGraph initial = ScriptGraph.empty();
for (ResourceScope scope : ResourceScope.values()) {
ResourceId id = id(scope);
initial = initial.add(CONTEXT_PATH_1, Arrays.asList(immediate(id))).validate();
}
for (ResourceScope scope : ResourceScope.values()) {
ResourceId id = id(scope);
try {
initial.add(CONTEXT_PATH_1, Arrays.asList(immediate(id))).validate();
fail("DuplicateResourceKeyException expected");
} catch (DuplicateResourceKeyException expected) {
}
/* no change in initial */
Collection<ScriptResource> scopeValues = initial.getResources(scope);
assertEquals(1, scopeValues.size());
ScriptResource found = initial.getResource(id);
assertEquals(id, found.getId());
}
}
public void testAddRemoveGroup() throws InvalidResourceException {
ScriptResourceDescriptor aDecriptor = new ScriptResourceDescriptor(A, FetchMode.IMMEDIATE, null, GROUP_1, false);
aDecriptor.getSupportedLocales().add(Locale.GERMANY);
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
aDecriptor,
new ScriptResourceDescriptor(B, FetchMode.IMMEDIATE, null, GROUP_1, false),
new ScriptResourceDescriptor(C, FetchMode.IMMEDIATE)
)).validate();
graph = graph.add(CONTEXT_PATH_2, Arrays.asList(
new ScriptResourceDescriptor(D, FetchMode.IMMEDIATE, null, GROUP_2, false)
)).validate();
assertEquals(Tools.toSet(A, B), graph.getLoadGroup(GROUP_1).getDependencies());
ScriptResource a = graph.getResource(A);
assertEquals(GROUP_1, a.getGroup().getId().getName());
assertEquals(GROUP_1, graph.getResource(B).getGroup().getId().getName());
assertNull(graph.getResource(C).getGroup());
assertEquals(Tools.toSet(D), graph.getLoadGroup(GROUP_2).getDependencies());
assertEquals(GROUP_2, graph.getResource(D).getGroup().getId().getName());
graph = graph.remove(CONTEXT_PATH_1);
assertNull(graph.getLoadGroup(GROUP_1));
assertNull(graph.getResource(A));
assertNull(graph.getResource(B));
assertNull(graph.getResource(C));
assertEquals(Tools.toSet(D), graph.getLoadGroup(GROUP_2).getDependencies());
assertEquals(GROUP_2, graph.getResource(D).getGroup().getId().getName());
}
public void testLocale() throws InvalidResourceException {
ScriptResourceDescriptor aDecriptor = new ScriptResourceDescriptor(A, FetchMode.IMMEDIATE, null, GROUP_1, false);
aDecriptor.getSupportedLocales().add(Locale.GERMANY);
ScriptGraph graph = ScriptGraph.empty().add(CONTEXT_PATH_1, Arrays.asList(
aDecriptor,
new ScriptResourceDescriptor(B, FetchMode.IMMEDIATE, null, GROUP_1, false),
new ScriptResourceDescriptor(C, FetchMode.IMMEDIATE)
)).validate();
assertEquals(Tools.toSet(A, B), graph.getLoadGroup(GROUP_1).getDependencies());
ScriptResource a = graph.getResource(A);
Map<QualifiedName, String> expectedParams = BaseScriptResource.createBaseParameters(a.getId().getScope(), a.getId().getName());
assertEquals(expectedParams, a.getParameters(false, null));
expectedParams.put(ResourceRequestHandler.LANG_QN, I18N.toTagIdentifier(Locale.GERMANY));
assertEquals(expectedParams, a.getParameters(false, Locale.GERMANY));
expectedParams.put(ResourceRequestHandler.LANG_QN, "");
expectedParams.put(ResourceRequestHandler.COMPRESS_QN, "min");
assertEquals(expectedParams, a.getParameters(true, null));
expectedParams.put(ResourceRequestHandler.LANG_QN, I18N.toTagIdentifier(Locale.GERMANY));
assertEquals(expectedParams, a.getParameters(true, Locale.GERMANY));
assertEquals(GROUP_1, a.getGroup().getId().getName());
assertEquals(GROUP_1, graph.getResource(B).getGroup().getId().getName());
Map<QualifiedName, String> expectedGroupParams = BaseScriptResource.createBaseParameters(ResourceScope.GROUP, GROUP_1);
assertEquals(expectedGroupParams, a.getGroup().getParameters(false, null));
expectedGroupParams.put(ResourceRequestHandler.LANG_QN, I18N.toTagIdentifier(Locale.GERMANY));
assertEquals(expectedGroupParams, a.getGroup().getParameters(false, Locale.GERMANY));
expectedGroupParams.put(ResourceRequestHandler.COMPRESS_QN, "min");
assertEquals(expectedGroupParams, a.getGroup().getParameters(true, Locale.GERMANY));
expectedGroupParams.put(ResourceRequestHandler.LANG_QN, "");
assertEquals(expectedGroupParams, a.getGroup().getParameters(true, null));
}
/**
* Test that each script of the test collection has no following script that belongs to its closure.
*
* @param test the test
*/
private void assertResultOrder(Collection<ScriptResource> test) {
ScriptResource[] array = test.toArray(new ScriptResource[test.size()]);
for (int i = 0; i < array.length; i++) {
ScriptResource resource = array[i];
for (int j = i + 1; j < array.length; j++) {
if (resource.getClosure().contains(array[j].getId()) && resource.getFetchMode().equals(array[j].getFetchMode())) {
failure("Was not expecting result order " + test, new Exception());
}
}
}
}
}