blob: 72ac37140cec51ed15d4934a44554b4ae58e6192 [file] [log] [blame]
/*
* Copyright (c) 2013 CEA and others.
* 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:
* Christian W. Damus (CEA) - initial API and implementation
*/
package org.eclipse.uml2.uml.validation.tests;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.validation.service.ITraversalStrategy;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.tests.util.StandaloneSupport;
import org.eclipse.uml2.uml.util.UMLUtil;
import org.eclipse.uml2.uml.validation.UMLTraversalStrategy;
/**
* Test suite for the {@link UMLTraversalStrategy} class and attendant classes.
*/
public class UMLTraversalStrategyTest
extends TestCase {
private ITraversalStrategy fixture;
private Package model;
private Class utils;
/**
* Initializes me with my name.
*
* @param name
* my name
*/
public UMLTraversalStrategyTest(String name) {
super(name);
}
public static Test suite() {
return new TestSuite(UMLTraversalStrategyTest.class,
"UML traversal strategy tests"); //$NON-NLS-1$
}
public void testTraversalCoversStereotypesFromRootPackage() {
assertTraversal(model, new Element[]{model, utils});
}
public void testTraversalCoversStereotypesFromNestedElement() {
assertTraversal(utils, new Element[]{utils}, new Element[]{model});
}
public void testTraversalCoversStereotypesFromRootNonPackage() {
// make the Utils class a root
EcoreUtil.remove(utils);
model.eResource().getContents().add(utils);
assertTraversal(utils, new Element[]{utils}, new Element[]{model});
}
//
// Test framework
//
@Override
protected void setUp()
throws Exception {
super.setUp();
fixture = new UMLTraversalStrategy();
ResourceSet rset = new ResourceSetImpl();
if (StandaloneSupport.isStandalone()) {
StandaloneSupport.init(rset);
}
Resource res = rset.createResource(URI.createURI("bogus:///model.uml"));
model = UMLFactory.eINSTANCE.createPackage();
model.setName("model");
res.getContents().add(model);
Profile profile = (Profile) UMLUtil.load(rset,
URI.createURI(UMLResource.STANDARD_L2_PROFILE_URI),
UMLPackage.Literals.PROFILE);
model.applyProfile(profile);
model.applyStereotype(profile.getOwnedStereotype("ModelLibrary"));
utils = model.createOwnedClass("Utils", false);
utils.applyStereotype(profile.getOwnedStereotype("Utility"));
utils
.applyStereotype(profile.getOwnedStereotype("ImplementationClass"));
}
@Override
protected void tearDown()
throws Exception {
ResourceSet rset = model.eResource().getResourceSet();
for (Resource next : rset.getResources()) {
next.unload();
}
rset.getResources().clear();
rset.eAdapters().clear();
model = null;
fixture = null;
super.tearDown();
}
EObject requireApplication(Element element, Stereotype stereotype) {
EObject result = element.getStereotypeApplication(stereotype);
assertNotNull("Stereotype not applied", result);
return result;
}
void assertTraversal(Element root, Element[] required) {
assertTraversal(root, required, new Element[0]);
}
void assertTraversal(Element root, Element[] required, Element[] forbidden) {
List<Element> expectedTraversal = Arrays.asList(required);
Set<EObject> unexpected = new java.util.HashSet<EObject>(
Arrays.asList(forbidden));
for (Element next : forbidden) {
unexpected.addAll(next.getStereotypeApplications());
}
PushBackIterator<Element> expected = new PushBackIterator<Element>(
expectedTraversal.iterator());
fixture.startTraversal(Collections.singleton(root),
new NullProgressMonitor());
while (expected.hasNext()) {
assertTrue("Traversal has too few elements", fixture.hasNext());
Element next = expected.next();
EObject actual = fixture.next();
assertFalse("Traversal includes a forbidden element",
unexpected.contains(actual));
if (next != actual) {
// compare it with the next one, then
expected.pushBack(next);
} else {
// now grab its stereotype applications, which are in
// non-deterministic order
Set<EObject> stereotypeApplications = new java.util.HashSet<EObject>(
next.getStereotypeApplications());
while (!stereotypeApplications.isEmpty()) {
assertTrue("Traversal has too few elements",
fixture.hasNext());
assertTrue(
"Traversal did not provide a stereotype application",
stereotypeApplications.remove(fixture.next()));
}
}
}
}
static final class PushBackIterator<E>
implements Iterator<E> {
private final Iterator<E> delegate;
private E pushedBack;
PushBackIterator(Iterator<E> delegate) {
this.delegate = delegate;
}
public boolean hasNext() {
return (pushedBack != null) || delegate.hasNext();
}
public E next() {
E result = pushedBack;
if (result == null) {
result = delegate.next();
} else {
pushedBack = null;
}
return result;
}
public void pushBack(E element) {
if (pushedBack != null) {
throw new IllegalStateException(
"already pushed an element back");
} else if (element == null) {
throw new IllegalArgumentException("cannot push null back");
}
}
public void remove() {
throw new UnsupportedOperationException("remove");
}
}
}