/* $Id: TestDependencyResolver.java 17994 2010-02-11 23:48:44Z euluis $ ***************************************************************************** * Copyright (c) 2010 Contributors - see below * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * euluis ***************************************************************************** */ package org.argouml.profile.internal; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; import junit.framework.TestCase; /** * Unit tests for {@link DependencyResolver}. * @author Luis Sergio Oliveira (euluis) */ public class TestDependencyResolver extends TestCase { private DependencyResolver<String> resolver; private DummyDependencyChecker checker; /** * @throws Exception * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); } /** * Test invoke of {@link DependencyResolver#resolve()} method without any * arguments. */ public void testResolveNoArgs() { DependencyChecker<String> checker2 = new DependencyChecker<String>() { public boolean check(String item) { return true; } }; resolver = new DependencyResolver<String>(checker2); resolver.resolve(); assertTrue("There should be no unresolved items.", resolver.unresolvedItems.isEmpty()); } /** * Test {@link DependentString#equals(Object)}. */ public void testDependentStringEquals() { // this is neat... assertEquals(new DependentString("A"), "A"); // but, lookout, it doesn't work both ways assertFalse("A".equals(new DependentString("A"))); } /** * Test the resolution of several items all without any dependencies. */ public void testResolveWithAllResolvableDependencies() { final Collection<DependentString> dependentItems = new ArrayList<DependentString>() { { add(new DependentString("A")); add(new DependentString("B")); add(new DependentString("C")); } }; checker = new DummyDependencyChecker(dependentItems); resolver = new DependencyResolver<String>(checker); final Collection<String> items = new ArrayList<String>() { { for (DependentString dependentItem : dependentItems) { add(dependentItem.theString); } } }; resolver.resolve(items); assertEquals(3, checker.calls); assertTrue("All the items should have been resolved.", checker.resolved.containsAll(items)); assertTrue("There should be no unresolved items.", resolver.unresolvedItems.isEmpty()); } /** * Test the resolution of items which are all resolvable, but, handed in * inverted order of their resolution: * A -> {B, C}, B -> {C} and C -> {} */ public void testResolveWithResolvableItemsButHandedInInvertedOrder() { final Collection<DependentString> dependentItems = new ArrayList<DependentString>() { { add(new DependentString("A", new HashSet<String>() { { add("B"); add("C"); } })); add(new DependentString("B", new HashSet<String>() { { add("C"); } })); add(new DependentString("C")); } }; checker = new DummyDependencyChecker(dependentItems); resolver = new DependencyResolver<String>(checker); Collection<String> items = new ArrayList<String>() { { for (DependentString dependentItem : dependentItems) { add(dependentItem.theString); } } }; resolver.resolve(items); assertTrue("All the items should have been resolved.", checker.resolved.containsAll(items)); assertTrue("There should be no unresolved items.", resolver.unresolvedItems.isEmpty()); } /** * Test the resolution of items which are all resolvable, but, handed first * partially and not resolvable, then a new call to resolve delivers the * solution. * First call: A -> {B, C}, B -> {C} and C -> {D} * Second call: D -> {} */ public void testResolveWithResolvableItemsButInTwoCalls() { final Collection<DependentString> dependentItems = new ArrayList<DependentString>() { { add(new DependentString("C", new HashSet<String>() { { add("D"); } })); add(new DependentString("D")); } }; checker = new DummyDependencyChecker(dependentItems); resolver = new DependencyResolver<String>(checker); Collection<String> items1 = new ArrayList<String>() { { add("C"); } }; resolver.resolve(items1); assertEquals("No item should have been resolved.", 0, checker.resolved.size()); Collection<String> items2 = new ArrayList<String>() { { add("D"); } }; resolver.resolve(items2); assertTrue("All the items should have been resolved.", checker.resolved.containsAll(items1) && checker.resolved.containsAll(items2)); assertTrue("There should be no unresolved items.", resolver.unresolvedItems.isEmpty()); } /** * Test the resolution of items which are not resolvable at first, but, * which after injecting the dependency, will afterwards be resolved with * the non-arguments resolve being invoked. * <ol> * <li>resolve(X -> {Z, Y}, Z -> {Y}) → nothing resolved</li> * <li>{@link DependencyResolver#resolve()} call → nothing * resolved</li> * <li>inject Y as resolved</li> * <li>{@link DependencyResolver#resolve()} call → X and Z * resolved</li> * </ol> */ public void testResolveWithSolutionInjectedByThirdParty() { final Collection<DependentString> dependentItems = new ArrayList<DependentString>() { { add(new DependentString("X", new HashSet<String>() { { add("Z"); add("Y"); } })); add(new DependentString("Z", new HashSet<String>() { { add("Y"); } })); } }; checker = new DummyDependencyChecker(dependentItems); resolver = new DependencyResolver<String>(checker); Collection<String> items = new ArrayList<String>() { { add("X"); add("Z"); } }; resolver.resolve(items); assertEquals("No item should have been resolved.", 0, checker.resolved.size()); resolver.resolve(); assertEquals("No item should have been resolved.", 0, checker.resolved.size()); checker.resolved.add("Y"); resolver.resolve(); assertTrue("All the items should have been resolved.", checker.resolved.containsAll(items)); assertTrue("There should be no unresolved items.", resolver.unresolvedItems.isEmpty()); } } class DependentString { String theString; Set<String> dependencies; DependentString(String s, Set<String> dependencies) { theString = s; this.dependencies = dependencies; if (dependencies == null) { this.dependencies = new HashSet<String>(); } } DependentString(String s) { this(s, new HashSet<String>()); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { return theString.equals(obj); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return theString.hashCode(); } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); for (String dependency : dependencies) { sb.append(dependency); sb.append(", "); } return theString + " -> {" + sb.toString() + "}"; } } class DummyDependencyChecker implements DependencyChecker<String> { Collection<String> items; Collection<DependentString> dependentItems; Collection<String> resolved = new HashSet<String>(); int calls = 0; DummyDependencyChecker(final Collection<DependentString> items) { this.items = new ArrayList<String>() { { for (DependentString item : items) { add(item.theString); } } }; this.dependentItems = items; } /** * @see org.argouml.profile.internal.DependencyChecker#check(java.lang.Object) */ public boolean check(String item) { calls++; if (items.contains(item)) { DependentString item2Check = null; for (DependentString theItem : dependentItems) { if (theItem.equals(item)) { item2Check = theItem; break; } } if (resolved.containsAll(item2Check.dependencies)) { resolved.add(item2Check.theString); return true; } } return false; } }