/******************************************************************************* * Copyright (c) 2009, 2011 SAP AG 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: * SAP AG - initial API and implementation ******************************************************************************/ package org.eclipse.ocl.examples.impactanalyzer.tests.deltaPropagation; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import junit.framework.TestCase; import modelmanagement.ModelmanagementPackage; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EOperation; 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.xmi.impl.XMIResourceImpl; import org.eclipse.ocl.ParserException; import org.eclipse.ocl.ecore.CallExp; import org.eclipse.ocl.ecore.IfExp; import org.eclipse.ocl.ecore.IterateExp; import org.eclipse.ocl.ecore.IteratorExp; import org.eclipse.ocl.ecore.LetExp; import org.eclipse.ocl.ecore.OCLExpression; import org.eclipse.ocl.ecore.OperationCallExp; import org.eclipse.ocl.ecore.OppositePropertyCallExp; import org.eclipse.ocl.ecore.PropertyCallExp; import org.eclipse.ocl.ecore.delegate.InvocationBehavior; import org.eclipse.ocl.examples.impactanalyzer.ValueNotFoundException; import org.eclipse.ocl.examples.impactanalyzer.deltaPropagation.PartialEvaluatorImpl; import org.eclipse.ocl.examples.impactanalyzer.filterSynthesis.FilterSynthesisImpl; import org.eclipse.ocl.examples.impactanalyzer.util.OCLFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import company.CompanyFactory; import company.CompanyPackage; import company.Department; import company.Division; import data.classes.Association; import data.classes.AssociationEnd; import data.classes.ClassTypeDefinition; import data.classes.ClassesFactory; import data.classes.ClassesPackage; import data.classes.MethodSignature; import data.classes.Parameter; import data.classes.SapClass; public class PartialEvaluatorTest extends TestCase { private PartialEvaluatorImpl evaluator; private OCLFactory oclFactory; @Override @Before public void setUp() { oclFactory = OCLFactory.getInstance(); evaluator = new PartialEvaluatorImpl(oclFactory); } @Override @After public void tearDown() { } @Test public void testSimplePartialEvaluate() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = evaluator.getHelper().createQuery("self.name"); assertTrue(expression instanceof PropertyCallExp); PropertyCallExp pce = (PropertyCallExp) expression; SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.setName("Humba"); Object result = evaluator.evaluate(c, pce, c); assertEquals(c.getName(), result); } @Test public void testPartialEvaluateAccessingUndefinedVariable() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = evaluator.getHelper().createQuery("let x:Integer=1 in self.name.size() + x"); assertTrue(expression instanceof LetExp); LetExp letExp = (LetExp) expression; OperationCallExp oce = (OperationCallExp) letExp.getIn(); SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.setName("Humba"); try { evaluator.evaluate(c, oce, c.getName().length()); fail("Expected ValueNotFoundException"); } catch (ValueNotFoundException e) { // this is what we expected } } @Test public void testPartialEvaluateAccessingUndefinedSelfVariable() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = evaluator.getHelper().createQuery( "self.ownedSignatures->select(name='abc')->any(true).name.size() + self.name.size()"); assertTrue(expression instanceof OperationCallExp); OperationCallExp oce = (OperationCallExp) expression; try { evaluator.evaluate(null, oce, 3); fail("Expected ValueNotFoundException"); } catch (ValueNotFoundException e) { // this is what we expected } } @Test public void testNoEffectForTrivialExpression() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); ResourceSet rs = new ResourceSetImpl(); OCLExpression expression = evaluator.getHelper().createQuery("self.name.size()"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof OperationCallExp); OperationCallExp oce = (OperationCallExp) expression; FilterSynthesisImpl mapper = new FilterSynthesisImpl(expression, /* notifyNewContextElements */false, org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance()); assertTrue(evaluator.hasNoEffectOnOverallExpression((OCLExpression) oce.getSource(), "Humba", "Trala", mapper)); assertFalse(evaluator.hasNoEffectOnOverallExpression((OCLExpression) oce.getSource(), "Humba", "Humba Humba", mapper)); } @Test public void testNoEffectForFullValuesOfSelectSource() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); MethodSignature ms = ClassesFactory.eINSTANCE.createMethodSignature(); ms.setName("def"); ResourceSet rs = new ResourceSetImpl(); OCLExpression expression = evaluator.getHelper().createQuery("self.ownedSignatures->select(name='abc')"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp iteratorExp = (IteratorExp) expression; FilterSynthesisImpl mapper = new FilterSynthesisImpl(expression, /* notifyNewContextElements */false, org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance()); assertTrue(evaluator.hasNoEffectOnOverallExpression((OCLExpression) iteratorExp.getSource(), Collections.EMPTY_SET, Collections.singleton(ms), mapper)); ms.setName("abc"); assertFalse(evaluator.hasNoEffectOnOverallExpression((OCLExpression) iteratorExp.getSource(), Collections.EMPTY_SET, Collections.singleton(ms), mapper)); } @Test public void testNoEffectForDeltaOfSelectSource() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); Parameter p = ClassesFactory.eINSTANCE.createParameter(); p.setName("def"); ResourceSet rs = new ResourceSetImpl(); // the following expresssion becomes self.ownedSignatures->collect(s | s.input)->select(name='abc') OCLExpression expression = evaluator.getHelper().createQuery("self.ownedSignatures.input->select(name='abc')"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp selectExp = (IteratorExp) expression; // select IteratorExp collectExp = (IteratorExp) selectExp.getSource(); PropertyCallExp inputPropertyCallExp = (PropertyCallExp) collectExp.getBody(); // s.input->select(...) FilterSynthesisImpl mapper = new FilterSynthesisImpl(expression, /* notifyNewContextElements */false, org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance()); assertTrue(evaluator.hasNoEffectOnOverallExpression(inputPropertyCallExp, Collections.EMPTY_SET, Collections.singleton(p), mapper)); p.setName("abc"); assertFalse(evaluator.hasNoEffectOnOverallExpression(inputPropertyCallExp, Collections.EMPTY_SET, Collections.singleton(p), mapper)); } @Test public void testNoEffectForDeltaOfDelegatesToPart() throws ParserException { evaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); SapClass c1 = ClassesFactory.eINSTANCE.createSapClass(); c1.setName("c1"); SapClass c2 = ClassesFactory.eINSTANCE.createSapClass(); c2.setName("c2"); ClassTypeDefinition ctdc1 = ClassesFactory.eINSTANCE.createClassTypeDefinition(); ctdc1.setClazz(c1); ClassTypeDefinition ctdc2 = ClassesFactory.eINSTANCE.createClassTypeDefinition(); ctdc2.setClazz(c2); Association assoc = ClassesFactory.eINSTANCE.createAssociation(); assoc.setName("assoc"); AssociationEnd ae1 = ClassesFactory.eINSTANCE.createAssociationEnd(); ae1.setName("ae1"); ae1.setType(ctdc1); AssociationEnd ae2 = ClassesFactory.eINSTANCE.createAssociationEnd(); ae2.setName("ae2"); ae2.setType(ctdc2); assoc.getEnds().add(ae1); assoc.getEnds().add(ae2); ResourceSet rs = new ResourceSetImpl(); // the following expresssion becomes self.ownedSignatures->collect(s | s.input)->select(name='abc') OCLExpression expression = evaluator.getHelper().createQuery("self.getAssociationEnds().otherEnd()->select(delegation->notEmpty()).type.clazz->reject(c|c=self)->asSet()"); FilterSynthesisImpl mapper = new FilterSynthesisImpl(expression, /* notifyNewContextElements */false, org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance()); OperationCallExp getAssociationEnds = ((OperationCallExp) ((IteratorExp) ((IteratorExp) ((IteratorExp) ((IteratorExp) ((IteratorExp) ((CallExp) expression) /*asSet*/.getSource())/*reject*/.getSource())/*collect(clazz)*/.getSource())/*collect(type)*/.getSource())/*select(delegation->notEmpty())*/.getSource())/*collect(otherEnd())*/.getSource())/*self.getAssociationEnds()*/; // getAssociationEnds(): self.elementsOfType->collect(associationEnd->asSet())->asSet() OCLExpression getAssociationEndsBody = mapper.getBodyForCall(getAssociationEnds); PropertyCallExp selfElementsOfType = (PropertyCallExp) ((IteratorExp) ((OperationCallExp) getAssociationEndsBody).getSource())/*collect*/.getSource(); rs.getResources().add(expression.eResource()); assertTrue(evaluator.hasNoEffectOnOverallExpression(selfElementsOfType, Collections.EMPTY_SET, Collections.singleton(ctdc1), mapper)); ae2.setDelegation(ClassesFactory.eINSTANCE.createDelegation()); assertFalse(evaluator.hasNoEffectOnOverallExpression(selfElementsOfType, Collections.EMPTY_SET, Collections.singleton(ctdc1), mapper)); } @Test public void testSimpleAtPreEvaluation() throws ParserException { final MethodSignature signature = ClassesFactory.eINSTANCE.createMethodSignature(); signature.setName("oldM"); final boolean testResult[] = new boolean[1]; signature.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.ownedSignatures.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof CallExp); final CallExp pce = (CallExp) expression; Object result = myEvaluator.evaluate(null, pce, Collections.singleton(signature)); testResult[0] = result instanceof Collection<?> && ((Collection<?>) result).size() > 0 && "oldM".equals(((Collection<?>) result).iterator().next()); } catch (ParserException e) { throw new RuntimeException(e); } } }); signature.setName("newM"); assertTrue(testResult[0]); assertEquals("newM", signature.getName()); } @Test public void testAtPreEvaluationWithSingleAddToReference() throws ParserException { final MethodSignature signature1 = ClassesFactory.eINSTANCE.createMethodSignature(); signature1.setName("sig1"); final MethodSignature signature2 = ClassesFactory.eINSTANCE.createMethodSignature(); signature2.setName("sig2"); final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.getOwnedSignatures().add(signature1); final boolean testResult[] = new boolean[1]; c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.ownedSignatures.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp ie = (IteratorExp) expression; PropertyCallExp pce = (PropertyCallExp) ie.getSource(); // self.ownedSignatures Object result = myEvaluator.evaluate(null, pce, c); testResult[0] = ((Collection<?>) result).size() == 1 && "sig1".equals(((MethodSignature) ((Collection<?>) result).iterator().next()).getName()); } catch (ParserException e) { throw new RuntimeException(e); } } }); c.getOwnedSignatures().add(signature2); assertTrue(testResult[0]); assertTrue(c.getOwnedSignatures().contains(signature1)); assertTrue(c.getOwnedSignatures().contains(signature2)); assertEquals(2, c.getOwnedSignatures().size()); } @Test public void testAtPreEvaluationWithSingleRemoveFromReference() throws ParserException { final MethodSignature signature1 = ClassesFactory.eINSTANCE.createMethodSignature(); signature1.setName("sig1"); final MethodSignature signature2 = ClassesFactory.eINSTANCE.createMethodSignature(); signature2.setName("sig2"); final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.getOwnedSignatures().add(signature1); c.getOwnedSignatures().add(signature2); final boolean testResult[] = new boolean[1]; c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.ownedSignatures.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp ie = (IteratorExp) expression; PropertyCallExp pce = (PropertyCallExp) ie.getSource(); // self.ownedSignatures Object result = myEvaluator.evaluate(null, pce, c); boolean foundSig1 = false; boolean foundSig2 = false; for (Object o : (Collection<?>) result) { MethodSignature ms = (MethodSignature) o; foundSig1 = foundSig1 || "sig1".equals(ms.getName()); foundSig2 = foundSig2 || "sig2".equals(ms.getName()); } testResult[0] = result instanceof Collection<?> && ((Collection<?>) result).size() == 2 && foundSig1 && foundSig2; } catch (ParserException e) { throw new RuntimeException(e); } } }); c.getOwnedSignatures().remove(signature2); assertTrue(testResult[0]); assertEquals(1, c.getOwnedSignatures().size()); assertTrue(c.getOwnedSignatures().contains(signature1)); assertFalse(c.getOwnedSignatures().contains(signature2)); assertEquals("sig1", c.getOwnedSignatures().iterator().next().getName()); } @Test public void testAtPreEvaluationWithSingleRemoveFromReferenceWithOrdering() throws ParserException { final MethodSignature signature1 = ClassesFactory.eINSTANCE.createMethodSignature(); signature1.setName("sig1"); final MethodSignature signature2 = ClassesFactory.eINSTANCE.createMethodSignature(); signature2.setName("sig2"); final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.getOwnedSignatures().add(signature1); c.getOwnedSignatures().add(signature2); final boolean testResult[] = new boolean[1]; c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.ownedSignatures.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp ie = (IteratorExp) expression; PropertyCallExp pce = (PropertyCallExp) ie.getSource(); // self.ownedSignatures Object result = myEvaluator.evaluate(null, pce, c); Iterator<?> i = ((Collection<?>) result).iterator(); testResult[0] = result instanceof Collection<?> && ((Collection<?>) result).size() == 2 && "sig1".equals(((MethodSignature) i.next()).getName()) && "sig2".equals(((MethodSignature) i.next()).getName()); } catch (ParserException e) { throw new RuntimeException(e); } } }); c.getOwnedSignatures().remove(signature1); assertTrue(testResult[0]); assertEquals(1, c.getOwnedSignatures().size()); assertFalse(c.getOwnedSignatures().contains(signature1)); assertTrue(c.getOwnedSignatures().contains(signature2)); assertEquals("sig2", c.getOwnedSignatures().iterator().next().getName()); } @Test public void testAtPreEvaluationWithMove() throws ParserException { final MethodSignature signature1 = ClassesFactory.eINSTANCE.createMethodSignature(); signature1.setName("sig1"); final MethodSignature signature2 = ClassesFactory.eINSTANCE.createMethodSignature(); signature2.setName("sig2"); final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); c.getOwnedSignatures().add(signature1); c.getOwnedSignatures().add(signature2); final boolean testResult[] = new boolean[1]; c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.ownedSignatures.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof IteratorExp); IteratorExp ie = (IteratorExp) expression; PropertyCallExp pce = (PropertyCallExp) ie.getSource(); // self.ownedSignatures Object result = myEvaluator.evaluate(null, pce, c); Iterator<?> i = ((Collection<?>) result).iterator(); testResult[0] = result instanceof Collection<?> && ((Collection<?>) result).size() == 2 && "sig1".equals(((MethodSignature) i.next()).getName()) && "sig2".equals(((MethodSignature) i.next()).getName()); } catch (ParserException e) { throw new RuntimeException(e); } } }); c.getOwnedSignatures().move(1, signature1); assertTrue(testResult[0]); assertEquals(2, c.getOwnedSignatures().size()); assertEquals(0, c.getOwnedSignatures().indexOf(signature2)); assertEquals(1, c.getOwnedSignatures().indexOf(signature1)); } @Test public void testAtPreEvaluationWithSetName() throws ParserException { final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); final boolean testResult[] = new boolean[1]; c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof PropertyCallExp); PropertyCallExp pce = (PropertyCallExp) expression; Object result = myEvaluator.evaluate(null, pce, c); testResult[0] = result == null; } catch (ParserException e) { throw new RuntimeException(e); } } }); c.setName("MyClass"); assertTrue(testResult[0]); c.getName().equals("MyClass"); } @Test public void testAtPreEvaluationWithUnsetName() throws ParserException { final SapClass c = ClassesFactory.eINSTANCE.createSapClass(); final boolean testResult[] = new boolean[1]; c.setName("MyClass"); c.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { final ResourceSet rs = new ResourceSetImpl(); PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(ClassesPackage.eINSTANCE.getSapClass()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.name"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof PropertyCallExp); PropertyCallExp pce = (PropertyCallExp) expression; Object result = myEvaluator.evaluate(null, pce, c); testResult[0] = result instanceof String && ((String) result).equals("MyClass"); } catch (ParserException e) { throw new RuntimeException(e); } } }); c.eUnset(ModelmanagementPackage.eINSTANCE.getNamedElement_Name()); assertTrue(testResult[0]); assertNull(c.getName()); } @Test public void testPartialEvaluationWithOppositeProperty() throws ParserException { final ResourceSet rs = new ResourceSetImpl(); final Resource r = new XMIResourceImpl(URI.createURI("http://humba/trala")); rs.getResources().add(r); final Division division = CompanyFactory.eINSTANCE.createDivision(); r.getContents().add(division); final Department department = CompanyFactory.eINSTANCE.createDepartment(); division.getDepartment().add(department); evaluator.getHelper().setContext(CompanyPackage.eINSTANCE.getDepartment()); OCLExpression expression = evaluator.getHelper().createQuery("self.department2division"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof OppositePropertyCallExp); OppositePropertyCallExp pce = (OppositePropertyCallExp) expression; Object result = evaluator.evaluate(null, pce, department); assertTrue(result instanceof Collection<?>); assertTrue(((Collection<?>) result).contains(division)); } @Test public void testAtPreEvaluationWithSettingOppositeProperty() throws ParserException { final ResourceSet rs = new ResourceSetImpl(); final Resource r = new XMIResourceImpl(URI.createURI("http://humba/trala")); rs.getResources().add(r); final Division division = CompanyFactory.eINSTANCE.createDivision(); r.getContents().add(division); final Department department = CompanyFactory.eINSTANCE.createDepartment(); r.getContents().add(department); final boolean testResult[] = new boolean[1]; division.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(CompanyPackage.eINSTANCE.getDepartment()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.department2division"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof OppositePropertyCallExp); OppositePropertyCallExp pce = (OppositePropertyCallExp) expression; Object result = myEvaluator.evaluate(null, pce, department); testResult[0] = result == null || (result instanceof Collection<?> && ((Collection<?>) result).isEmpty()); } catch (ParserException e) { throw new RuntimeException(e); } } }); division.getDepartment().add(department); assertTrue(testResult[0]); assertTrue(division.getDepartment().contains(department)); } @Test public void testAtPreEvaluationWithUnsettingOppositeProperty() throws ParserException { final ResourceSet rs = new ResourceSetImpl(); final Resource r = new XMIResourceImpl(URI.createURI("http://humba/trala")); rs.getResources().add(r); final Division division = CompanyFactory.eINSTANCE.createDivision(); r.getContents().add(division); final Department department = CompanyFactory.eINSTANCE.createDepartment(); division.getDepartment().add(department); final boolean testResult[] = new boolean[1]; division.eAdapters().add(new AdapterImpl() { @Override public void notifyChanged(Notification n) { try { PartialEvaluatorImpl myEvaluator = new PartialEvaluatorImpl(n, oclFactory); myEvaluator.getHelper().setContext(CompanyPackage.eINSTANCE.getDepartment()); OCLExpression expression = myEvaluator.getHelper().createQuery("self.department2division"); rs.getResources().add(expression.eResource()); assertTrue(expression instanceof OppositePropertyCallExp); OppositePropertyCallExp pce = (OppositePropertyCallExp) expression; Object result = myEvaluator.evaluate(null, pce, department); testResult[0] = result instanceof Collection<?> && ((Collection<?>) result).contains(division); } catch (ParserException e) { throw new RuntimeException(e); } } }); r.getContents().add(department); assertTrue(testResult[0]); assertFalse(division.getDepartment().contains(department)); } /** * Partially evaluate a recursive operation such that during partial evaluation a recursive call happens. * The source expression for which the value is provided is an operation parameter on which the recursive call * will take place, but with a different parameter value. This way, during the recursive call evaluating the * source expression for which the value was provided for the first call needs to be computed normally. */ @Test public void testAtPreEvaluationForParameterInRecursiveOperation() throws ParserException { final ResourceSet rs = new ResourceSetImpl(); final Resource r = new XMIResourceImpl(URI.createURI("http://humba/trala")); rs.getResources().add(r); final Department department = CompanyFactory.eINSTANCE.createDepartment(); department.setBudget(100); r.getContents().add(department); Department sub = CompanyFactory.eINSTANCE.createDepartment(); sub.setBudget(200); department.getSubDepartment().add(sub); Department subsub = CompanyFactory.eINSTANCE.createDepartment(); subsub.setBudget(300); sub.getSubDepartment().add(subsub); evaluator.getHelper().setContext(CompanyPackage.eINSTANCE.getDepartment()); EOperation op = CompanyPackage.eINSTANCE.getDepartment().getEOperations().get(1); OCLExpression sumBudgetBody = InvocationBehavior.INSTANCE.getOperationBody(evaluator.getOcl(), op); /* expression expected: * if self.subDepartment->size() >= 1 then self.subDepartment->iterate(department; return : Integer = 0 | return + department.sumBudget()) + self.budget else self.budget endif */ assertTrue(sumBudgetBody instanceof IfExp); IfExp ifExp = (IfExp) sumBudgetBody; IterateExp selfSubDepartment_Iterate = (IterateExp) ((OperationCallExp) ifExp.getThenExpression()) // iterate+self.budget .getSource(); // self.subDepartment->iterate(...) Object result = evaluator.evaluate(null, selfSubDepartment_Iterate, Collections.singletonList(department)); assertEquals(600, result); } // TODO add a test case that computes delegatesTo() and pass old and new value for self.elementsOfType // (getAssociationEnds()) and for association.ends (otherEnd()) with a suitable test model that does // not use delegation on either association end }