blob: 5705e630fce15e8f2a08a66fea275934b4b11a10 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* SAP AG - initial API and implementation
******************************************************************************/
package org.eclipse.ocl.examples.impactanalyzer.tests.instanceScope;
import java.util.Collection;
import modelmanagement.ModelmanagementFactory;
import modelmanagement.ModelmanagementPackage;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.ocl.common.OCLConstants;
import org.eclipse.ocl.common.internal.options.CommonOptions;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzer;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzerFactory;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.notifications.NotificationHelper;
import org.eclipse.ocl.examples.impactanalyzer.configuration.OptimizationActivation;
import org.eclipse.ocl.examples.impactanalyzer.testutils.BaseDepartmentTestWithOCL;
import org.eclipse.ocl.examples.impactanalyzer.util.OCLFactory;
import org.junit.Test;
import behavioral.actions.ActionsFactory;
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;
import data.classes.SignatureImplementation;
import data.classes.TypeAdapter;
import dataaccess.expressions.ExpressionsFactory;
import dataaccess.expressions.ExpressionsPackage;
import dataaccess.expressions.MethodCallExpression;
import dataaccess.expressions.ObjectCreationExpression;
import dataaccess.expressions.VariableExpression;
import dataaccess.expressions.literals.LiteralsFactory;
import dataaccess.expressions.literals.LiteralsPackage;
import dataaccess.expressions.literals.ObjectLiteral;
import dataaccess.expressions.literals.StringLiteral;
public class OclIaTest extends BaseDepartmentTestWithOCL {
private static final String testAnalysisOfRecursiveOperationWithSelf = "context dataaccess::expressions::MethodCallExpression \n"
+ "inv testAnalysisOfRecursiveOperationWithSelf: \n"
+ "self.object.getType().getInnermost().oclAsType(data::classes::ClassTypeDefinition).clazz.allSignatures() \n"
+ "->select(s | s.name = 'testMethod')";
private static final String testAllInstancesSelectClassName = "context data::classes::ClassTypeDefinition \n"
+ "inv testAllInstancesSelectClassName:\n" + "data::classes::SapClass.allInstances()->select(c | c.name = 'Bob')";
private static final String testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis = "context data::classes::SapClass \n"
+ "inv testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis: \n"
+ "self.oclAsType(data::classes::SapClass).name";
private static final String testLongRunningNavigationPathExpression = "context data::classes::AssociationEnd inv LongRunningNavigationPath: \n "
+ "'.'.concat(self.oclAsType(data::classes::AssociationEnd).name)";
private static final String testLowerMultiplicityPropagationForMethodCall = "context data::classes::ClassTypeDefinition \n"
+ "inv testLowerMultiplicityPropagationForMethodCallOnParameterUsage: \n"
+ "self.ownerTypedElement.oclAsType(dataaccess::expressions::MethodCallExpression).methodSignature.output.lowerMultiplicity * \n"
+ "self.ownerTypedElement.oclAsType(dataaccess::expressions::MethodCallExpression).object.getType().lowerMultiplicity";
private static final String testInstanceScopeAnalysisForRecursiveOperation = "context data::classes::SapClass \n"
+ "inv testInstanceScopeAnalysisForRecursiveOperation: \n" + "self.adapters->forAll(a | self.conformsTo(a.to))";
private static final String testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf = "context data::classes::SapClass \n"
+ "inv testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf: \n" + "Tuple{cls=self}.cls.name";
private static final String testVerySimpleInstanceScopeAnalysisWithTuple = "context data::classes::SapClass \n"
+ "inv testVerySimpleInstanceScopeAnalysisWithTuple: \n" + "Tuple{name=self.name}.name";
private static final String testForIA2 = "context dataaccess::expressions::literals::ObjectLiteral \n" + "inv testForIA2: \n"
+ "self.oclAsType(dataaccess::expressions::literals::ObjectLiteral).valueClass.getAssociationEnds().otherEnd()"
+ "->select(ae|ae.name='Assoc_to_Bob_changed')";
private EPackage cp;
private ResourceSetImpl rs;
@Override
public void setUp() {
CommonOptions.DEFAULT_DELEGATION_MODE.setDefaultValue(OCLConstants.OCL_DELEGATE_URI_LPG);
this.cp = ClassesPackage.eINSTANCE;
this.rs = new ResourceSetImpl();
this.rs.eAdapters().add(new ECrossReferenceAdapter());
this.rs.getResources().add(this.cp.eResource());
}
@Override
public void tearDown() {
this.rs = null;
this.cp = null;
}
@Test
public void testSelectByType() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testSelectByType:\n" +
"self.ownedSignatures.implementation->selectByType(data::classes::LinkSetting).implements_.output"+
".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
ms1.setName("ms1");
c1.getOwnedSignatures().add(ms1);
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
ms2.setName("ms2");
c2.getOwnedSignatures().add(ms2);
SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
ms1.setImplementation(ms1Impl);
SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
ms2.setImplementation(ms2Impl);
SapClass output = ClassesFactory.eINSTANCE.createSapClass();
output.setName("Output");
ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
outputCtdForMs1.setClazz(output);
outputCtdForMs2.setClazz(output);
ms1.setOutput(outputCtdForMs1);
ms2.setOutput(outputCtdForMs2);
Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(resultOnC1.isEmpty());
Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, resultOnC2.size());
assertTrue(resultOnC2.contains("Output"));
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
output.eAdapters().add(adapter);
output.setName("NewOutput");
Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(newResultOnC1.isEmpty());
Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, newResultOnC2.size());
assertTrue(newResultOnC2.contains("NewOutput"));
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(1, impact.size()); // expecting only c2 to be impacted because c1's ms1 implementation has the wrong type
assertFalse(impact.contains(c1));
assertTrue(impact.contains(c2));
}
@Test
public void testSelectByTypeForSubclass() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testSelectByTypeForSubclass:\n" +
"self.ownedSignatures.implementation->selectByType(data::classes::SignatureImplementation).implements_.output"+
".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
ms1.setName("ms1");
c1.getOwnedSignatures().add(ms1);
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
ms2.setName("ms2");
c2.getOwnedSignatures().add(ms2);
SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
ms1.setImplementation(ms1Impl);
SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
ms2.setImplementation(ms2Impl);
SapClass output = ClassesFactory.eINSTANCE.createSapClass();
output.setName("Output");
ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
outputCtdForMs1.setClazz(output);
outputCtdForMs2.setClazz(output);
ms1.setOutput(outputCtdForMs1);
ms2.setOutput(outputCtdForMs2);
Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(resultOnC1.isEmpty());
Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertTrue(resultOnC2.isEmpty());
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
output.eAdapters().add(adapter);
output.setName("NewOutput");
Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(newResultOnC1.isEmpty());
Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertTrue(newResultOnC2.isEmpty());
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertTrue(impact.isEmpty()); // expecting neither c1 nor c2 to be in
// the result because neither Block nor
// LinkSetting has exactly type
// SignatureImplementation
}
@Test
public void testSelectByKind() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testSelectByKind:\n" +
"self.ownedSignatures.implementation->selectByKind(data::classes::LinkSetting).implements_.output"+
".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
ms1.setName("ms1");
c1.getOwnedSignatures().add(ms1);
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
ms2.setName("ms2");
c2.getOwnedSignatures().add(ms2);
SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
ms1.setImplementation(ms1Impl);
SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
ms2.setImplementation(ms2Impl);
SapClass output = ClassesFactory.eINSTANCE.createSapClass();
output.setName("Output");
ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
outputCtdForMs1.setClazz(output);
outputCtdForMs2.setClazz(output);
ms1.setOutput(outputCtdForMs1);
ms2.setOutput(outputCtdForMs2);
Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(resultOnC1.isEmpty());
Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, resultOnC2.size());
assertTrue(resultOnC2.contains("Output"));
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
output.eAdapters().add(adapter);
output.setName("NewOutput");
Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(newResultOnC1.isEmpty());
Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, newResultOnC2.size());
assertTrue(newResultOnC2.contains("NewOutput"));
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(1, impact.size()); // expecting only c2 to be impacted because c1's ms1's implementation's type doesn't match
assertTrue(impact.contains(c2));
}
@Test
public void testSelectByKindForSubclass() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testSelectByKindForSubclass:\n" +
"self.ownedSignatures.implementation->selectByKind(data::classes::SignatureImplementation).implements_.output"+
".oclAsType(data::classes::ClassTypeDefinition).clazz.name",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
ms1.setName("ms1");
c1.getOwnedSignatures().add(ms1);
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
ms2.setName("ms2");
c2.getOwnedSignatures().add(ms2);
SignatureImplementation ms1Impl = ActionsFactory.eINSTANCE.createBlock();
ms1.setImplementation(ms1Impl);
SignatureImplementation ms2Impl = ClassesFactory.eINSTANCE.createLinkSetting();
ms2.setImplementation(ms2Impl);
SapClass output = ClassesFactory.eINSTANCE.createSapClass();
output.setName("Output");
ClassTypeDefinition outputCtdForMs1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ClassTypeDefinition outputCtdForMs2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
outputCtdForMs1.setClazz(output);
outputCtdForMs2.setClazz(output);
ms1.setOutput(outputCtdForMs1);
ms2.setOutput(outputCtdForMs2);
Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertEquals(1, resultOnC1.size());
assertTrue(resultOnC1.contains("Output"));
Collection<?> resultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, resultOnC2.size());
assertTrue(resultOnC2.contains("Output"));
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
output.eAdapters().add(adapter);
output.setName("NewOutput");
Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertEquals(1, newResultOnC1.size());
assertTrue(newResultOnC1.contains("NewOutput"));
Collection<?> newResultOnC2 = (Collection<?>) OCL.newInstance().evaluate(c2, expression);
assertEquals(1, newResultOnC2.size());
assertTrue(newResultOnC2.contains("NewOutput"));
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(2, impact.size()); // expecting both, c1 and c2, to be impacted
assertTrue(impact.contains(c1));
assertTrue(impact.contains(c2));
}
@Test
public void testSimpleClosure() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testSimpleClosure:\n" +
"self->closure(i | i.ownedSignatures.input.ownedTypeDefinition." +
"oclAsType(data::classes::ClassTypeDefinition).clazz)",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
MethodSignature ms1 = ClassesFactory.eINSTANCE.createMethodSignature();
ms1.setName("ms1");
c1.getOwnedSignatures().add(ms1);
Parameter p1 = ClassesFactory.eINSTANCE.createParameter();
p1.setName("p1");
ms1.getInput().add(p1);
ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
p1.setOwnedTypeDefinition(ctd1);
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
ctd1.setClazz(c2);
c2.setName("c2");
MethodSignature ms2 = ClassesFactory.eINSTANCE.createMethodSignature();
ms2.setName("ms2");
c2.getOwnedSignatures().add(ms2);
Parameter p2 = ClassesFactory.eINSTANCE.createParameter();
p2.setName("p2");
ms2.getInput().add(p2);
ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
p2.setOwnedTypeDefinition(ctd2);
SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
ctd2.setClazz(c3);
c3.setName("c3");
MethodSignature ms3 = ClassesFactory.eINSTANCE.createMethodSignature();
ms3.setName("ms3");
c3.getOwnedSignatures().add(ms3);
Parameter p3 = ClassesFactory.eINSTANCE.createParameter();
p3.setName("p3");
ms3.getInput().add(p3);
ClassTypeDefinition ctd3 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
p3.setOwnedTypeDefinition(ctd3);
SapClass c4 = ClassesFactory.eINSTANCE.createSapClass();
ctd3.setClazz(c4);
c4.setName("c4");
MethodSignature ms4 = ClassesFactory.eINSTANCE.createMethodSignature();
ms3.setName("ms4");
c4.getOwnedSignatures().add(ms4);
Collection<?> resultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(resultOnC1.contains(c2));
assertTrue(resultOnC1.contains(c3));
assertTrue(resultOnC1.contains(c4));
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
ms2.eAdapters().add(adapter);
// now add another parameter p22 with new type c5 to ms2; this should change expression
// for c2 and c1 whose ms1 argument p1 is using c2
SapClass c5 = ClassesFactory.eINSTANCE.createSapClass();
c5.setName("c5");
Parameter p22 = ClassesFactory.eINSTANCE.createParameter();
p22.setName("p22");
ClassTypeDefinition ctd22 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
p22.setOwnedTypeDefinition(ctd22);
ctd22.setClazz(c5);
ms2.getInput().add(p22);
Collection<?> newResultOnC1 = (Collection<?>) OCL.newInstance().evaluate(c1, expression);
assertTrue(newResultOnC1.contains(c2));
assertTrue(newResultOnC1.contains(c3));
assertTrue(newResultOnC1.contains(c4));
assertTrue(newResultOnC1.contains(c5));
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(2, impact.size()); // expecting c1 and c2 to be impacted
assertTrue(impact.contains(c1));
assertTrue(impact.contains(c2));
}
@Test
public void testResultUseInIterate() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testMoveWithoutImpact:\n" +
"Sequence{1, 2, 3}->iterate(i; result:Set(data::classes::SapClass)=Set{self} | result.ownedSignatures.output.oclAsType(data::classes::ClassTypeDefinition).clazz)",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
c3.setName("c3");
SapClass c4 = ClassesFactory.eINSTANCE.createSapClass();
c4.setName("c4");
SapClass c5 = ClassesFactory.eINSTANCE.createSapClass();
c5.setName("c5");
SapClass c6 = ClassesFactory.eINSTANCE.createSapClass();
c6.setName("c6");
connectWithMethodOutput(c1, c2);
connectWithMethodOutput(c2, c3);
connectWithMethodOutput(c3, c4);
connectWithMethodOutput(c4, c5);
this.cp.eResource().getContents().add(c1);
this.cp.eResource().getContents().add(c2);
this.cp.eResource().getContents().add(c3);
this.cp.eResource().getContents().add(c4);
this.cp.eResource().getContents().add(c5);
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
c5.eAdapters().add(adapter);
connectWithMethodOutput(c5, c6);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(5, impact.size()); // expecting all c1..c6 to be impacted
assertFalse(impact.contains(c6));
}
private void connectWithMethodOutput(SapClass c1, SapClass c2) {
MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
m1.setName("m1");
ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd1.setClazz(c2);
m1.setOutput(ctd1);
c1.getOwnedSignatures().add(m1);
}
@Test
public void testMoveWithoutImpact() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testMoveWithoutImpact:\n" + "self.ownedSignatures->at(3).name = 'm3'",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
m1.setName("m1");
c.getOwnedSignatures().add(m1);
MethodSignature m2 = ClassesFactory.eINSTANCE.createMethodSignature();
m2.setName("m2");
c.getOwnedSignatures().add(m2);
MethodSignature m3 = ClassesFactory.eINSTANCE.createMethodSignature();
m1.setName("m3");
c.getOwnedSignatures().add(m3);
this.cp.eResource().getContents().add(c);
c.setName("C");
final Notification[] noti = new Notification[1];
Adapter adapter = new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
noti[0] = msg;
}
};
c.eAdapters().add(adapter);
c.getOwnedSignatures().move(0, 1); // swap first two signatures
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti[0]);
assertEquals(0, impact.size());
c.getOwnedSignatures().move(1, 2); // not the name of the element at position 3 should have changed
Collection<EObject> impact2 = ia.getContextObjects(noti[0]);
assertEquals(1, impact2.size());
assertTrue(impact2.contains(c));
}
@Test
public void testTupleLiteralUsedTwice() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testTupleLiteralUsedTwice:\n"
+ "let t:Tuple(c:data::classes::SapClass, d:data::classes::SapClass) = Tuple{c=self, d=self.adapters.to->first()} in\n"
+ "Set{t.c.name, t.d.name}", this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
SapClass d = ClassesFactory.eINSTANCE.createSapClass();
d.setName("D");
this.cp.eResource().getContents().add(c);
c.setName("oldName");
TypeAdapter ta = ClassesFactory.eINSTANCE.createTypeAdapter();
ta.setAdapted(c);
ta.setTo(d);
EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(c));
Notification noti2 = NotificationHelper.createAttributeChangeNotification(d, att, "D", "newD");
Collection<EObject> impact2 = ia.getContextObjects(noti2);
assertTrue(impact2.size() == 2 && impact2.contains(c) && impact2.contains(d));
}
@Test
public void testTupleLiteralWithImmediatePropertyCall() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testTupleLiteralWithImmediatePropertyCall:\n" + "Tuple{c=self}.c.name",
this.cp).iterator().next().getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
this.cp.eResource().getContents().add(c);
c.setName("oldName");
EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(c));
}
@Test
public void testTupleLiteralPassedThroughLetVariable() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testTupleLiteralPassedThroughLetVariable:\n"
+ "let t:Tuple(c:data::classes::SapClass) = Tuple{c=self} in\n" + "t.c.name", this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
this.cp.eResource().getContents().add(c);
c.setName("oldName");
EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(c));
}
@Test
public void testTupleLiteralPassedThroughTwoLetVariables() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testTupleLiteralPassedThroughLetVariable:\n"
+ "let t1:Tuple(c:data::classes::SapClass) = Tuple{c=self} in\n"
+ "let t2:Tuple(c:data::classes::SapClass) = t1 in\n" + "t2.c.name", this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
this.cp.eResource().getContents().add(c);
c.setName("oldName");
EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(c));
}
@Test
public void testNestedTupleLiteral() {
OCLExpression expression = (OCLExpression) parse(
"context data::classes::SapClass inv testNestedTupleLiteral:\n"
+ "Tuple{c:Tuple(d:data::classes::SapClass)=Tuple{d=self}}.c.d.name", this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
SapClass c = ClassesFactory.eINSTANCE.createSapClass();
this.cp.eResource().getContents().add(c);
c.setName("oldName");
EAttribute att = (EAttribute) c.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(c, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(c));
}
@Test
public void testLongRunningNavigationPathConstruction() {
OCLExpression expression = (OCLExpression) parse(testLongRunningNavigationPathExpression, this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(expression);
AssociationEnd ae = ClassesFactory.eINSTANCE.createAssociationEnd();
this.cp.eResource().getContents().add(ae);
EAttribute att = (EAttribute) ae.eClass().getEStructuralFeature(ClassesPackage.ASSOCIATION_END__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(ae, att, "oldName", "newName");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expression, ClassesPackage.eINSTANCE
.getAssociationEnd(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 1 && impact.contains(ae));
}
/**
* self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity *
* self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity
*/
@Test
public void testLowerMultiplicityPropagationForMethodCallOnParameterUsage() {
OCLExpression exp = (OCLExpression) parse(testLowerMultiplicityPropagationForMethodCall, this.cp).iterator().next()
.getSpecification().getBodyExpression();
Resource r = this.cp.eResource();
r.eAdapters().add(new ECrossReferenceAdapter());
r.getContents().add(exp);
// construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1
MethodSignature length = ClassesFactory.eINSTANCE.createMethodSignature();
r.getContents().add(length);
length.setName("length");
SapClass numberClass = ClassesFactory.eINSTANCE.createSapClass();
r.getContents().add(numberClass);
numberClass.setName("Number");
ClassTypeDefinition msOutput = ClassesFactory.eINSTANCE.createClassTypeDefinition();
msOutput.setClazz(numberClass);
msOutput.setLowerMultiplicity(1);
msOutput.setUpperMultiplicity(1);
length.setOutput(msOutput);
ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd.setClazz(numberClass);
ctd.setLowerMultiplicity(1);
ctd.setUpperMultiplicity(1);
MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
r.getContents().add(mce);
mce.setOwnedTypeDefinition(ctd);
mce.setMethodSignature(length);
Parameter p = ClassesFactory.eINSTANCE.createParameter();
r.getContents().add(p);
p.setName("p");
SapClass stringClass = ClassesFactory.eINSTANCE.createSapClass();
r.getContents().add(stringClass);
stringClass.setName("String");
ClassTypeDefinition otDef = ClassesFactory.eINSTANCE.createClassTypeDefinition();
otDef.setClazz(stringClass);
otDef.setUpperMultiplicity(1);
otDef.setLowerMultiplicity(1);
p.setOwnedTypeDefinition(otDef);
VariableExpression ve = ExpressionsFactory.eINSTANCE.createVariableExpression();
ve.setVariable(p); // this should infer the variable expression's multiplicity to that of p
mce.setObject(ve);
assertEquals(1, ve.getType().getLowerMultiplicity());
OCL ocl = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance();
Object oldResult = ocl.evaluate(ctd, exp);
Notification noti = NotificationHelper.createChangeLowerMultiplicityNotification(p.getOwnedTypeDefinition(), 0);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE
.getClassTypeDefinition(), /* notifyOnNewContextElements */ false,
OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
Object newResult = ocl.evaluate(ctd, exp);
assertEquals(0, p.getOwnedTypeDefinition().getLowerMultiplicity());
assertFalse("expected " + oldResult + " and " + newResult + " to be different but were equal", oldResult
.equals(newResult));
assertEquals(1, impact.size());
assertTrue(impact.contains(ctd));
}
/**
* self.ownerTypedElement.oclAsType(MethodCallExpression).methodSignature.output.lowerMultiplicity *
* self.ownerTypedElement.oclAsType(MethodCallExpression).object.getType().lowerMultiplicity
*/
@Test
public void testLowerMultiplicityPropagationForMethodCall() {
OCLExpression exp = (OCLExpression) parse(testLowerMultiplicityPropagationForMethodCall, this.cp).iterator().next()
.getSpecification().getBodyExpression();
Resource r = this.cp.eResource();
r.getContents().add(exp);
// construct something like "abc".length(), then change multiplicity of "abc" from 1..1 to 0..1
MethodSignature length = ClassesFactory.eINSTANCE.createMethodSignature();
length.setName("length");
SapClass numberClass = ClassesFactory.eINSTANCE.createSapClass();
numberClass.setName("Number");
ClassTypeDefinition msOutput = ClassesFactory.eINSTANCE.createClassTypeDefinition();
msOutput.setClazz(numberClass);
msOutput.setLowerMultiplicity(1);
msOutput.setUpperMultiplicity(1);
length.setOutput(msOutput);
ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd1.setClazz(numberClass);
ctd1.setLowerMultiplicity(1);
ctd1.setUpperMultiplicity(1);
MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
mce.setOwnedTypeDefinition(ctd1);
mce.setMethodSignature(length);
StringLiteral sl = LiteralsFactory.eINSTANCE.createStringLiteral();
sl.setLiteral("abc");
SapClass stringClass = ClassesFactory.eINSTANCE.createSapClass();
ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd2.setClazz(stringClass);
ctd2.setLowerMultiplicity(1);
ctd2.setUpperMultiplicity(1);
sl.setOwnedTypeDefinition(ctd2);
mce.setObject(sl);
r.getContents().add(mce);
r.getContents().add(length);
r.getContents().add(numberClass);
r.getContents().add(stringClass);
assertEquals(1, sl.getOwnedTypeDefinition().getLowerMultiplicity());
Notification noti = NotificationHelper.createChangeLowerMultiplicityNotification(sl.getOwnedTypeDefinition(), 0);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE
.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(0, sl.getOwnedTypeDefinition().getLowerMultiplicity());
assertEquals(1, impact.size());
assertTrue(impact.contains(ctd1));
}
/**
* data::classes::SapClass.allInstances()->select(c | c.name = 'something'
*/
@Test
public void testAnalysisOfRecursiveOperationWithSelf() {
OCLExpression exp = (OCLExpression) parse(testAnalysisOfRecursiveOperationWithSelf, this.cp).iterator().next()
.getSpecification().getBodyExpression();
Resource r = this.cp.eResource();
r.eAdapters().add(new ECrossReferenceAdapter());
r.getContents().add(exp);
// construct something like "new HumbaClass1().m()"
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
MethodSignature ms = ClassesFactory.eINSTANCE.createMethodSignature();
ms.setName("testMethod");
cl1.getOwnedSignatures().add(ms);
final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd.setLowerMultiplicity(1);
ctd.setUpperMultiplicity(1);
ctd.setClazz(null);
final MethodCallExpression mce = ExpressionsFactory.eINSTANCE.createMethodCallExpression();
final ObjectCreationExpression oce = ExpressionsFactory.eINSTANCE.createObjectCreationExpression();
oce.setClassToInstantiate(cl1);
oce.setOwnedTypeDefinition(ctd);
mce.setObject(oce);
r.getContents().add(cl1);
r.getContents().add(mce);
Notification noti = NotificationHelper.createChangeClazzNotification(ctd, cl1);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ExpressionsPackage.eINSTANCE
.getMethodCallExpression(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(mce) && !impact.contains(ctd));
}
/**
* data::classes::SapClass.allInstances()->select(c | c.name = 'something'
*/
@Test
public void testAllInstancesSelectClassName() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
.getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd.setClazz(cl1);
r.getContents().add(ctd);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
// The expression has as its context ClassTypeDefinition. Therefore, the SapClass must not be returned
// as impacted object. However, the change affects the ->select clause after allInstances(), so
// all context objects of type ClassTypeDefinition are affected. That's what we want to assert now:
assertTrue(impact.size() > 0 && impact.contains(ctd) && !impact.contains(cl1));
}
/**
* The ->select lets only classes pass whose name is 'Bob'. Therefore, a class named 'Alice'
* should not be produced by any context.
*/
@Test
public void testFindContextElementsForResultForAllInstances() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
.getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd.setClazz(cl1);
r.getContents().add(ctd);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> contexts = ia.getContextObjects(cl1);
assertTrue(contexts.isEmpty());
}
/**
* The ->select lets only classes pass whose name is 'Bob'. Therefore, a class named 'Bob'
* should be produced by all possible contexts
*/
@Test
public void testFindAllContextElementsForResultForAllInstances() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
.getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Bob");
r.getContents().add(cl1);
final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
ctd.setClazz(cl1);
r.getContents().add(ctd);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> contexts = ia.getContextObjects(cl1);
assertTrue(!contexts.isEmpty());
assertTrue(contexts.contains(ctd));
}
/**
* data::classes::SapClass.allInstances()->select(c | c.name = 'something'
*/
@Test
public void testTriggeringAllInstancesByDirectResourceContainment() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testAllInstancesSelectClassName, this.cp).iterator().next().getSpecification()
.getBodyExpression();
r.getContents().add(exp);
final ClassTypeDefinition ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition();
r.getContents().add(ctd);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Bob");
final Notification[] notifications = new Notification[1];
Adapter a = new AdapterImpl() {
@Override
public void notifyChanged(Notification n) {
if (n.getEventType() != Notification.REMOVING_ADAPTER) {
if (notifications[0] != null) {
fail("didn't expect to receive two notifications");
}
notifications[0] = n;
}
}
};
r.eAdapters().add(a);
cl1.eAdapters().add(a);
r.getContents().add(cl1);
assertNotNull("Expected to receive one notification", notifications[0]);
r.eAdapters().remove(a);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getClassTypeDefinition(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(notifications[0]);
// The expression has as its context ClassTypeDefinition. Therefore, the SapClass must not be returned
// as impacted object. However, the change affects the ->select clause after allInstances(), so
// all context objects of type ClassTypeDefinition are affected. That's what we want to assert now:
assertTrue(impact.size() > 0 && impact.contains(ctd) && !impact.contains(cl1));
}
@Test
public void testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testVerySimpleTracerBasedInstanceScopeAnalysisWithNewClassScopeAnalysis,
this.cp).iterator().next().getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 1 && impact.contains(cl1));
}
@Test
public void testInstanceScopeAnalysisForRecursiveOperation() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testInstanceScopeAnalysisForRecursiveOperation, this.cp).iterator().next()
.getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
SapClass cl2 = ClassesFactory.eINSTANCE.createSapClass();
;
cl2.setName("Bob");
r.getContents().add(cl2);
TypeAdapter adapter = ClassesFactory.eINSTANCE.createTypeAdapter();
adapter.setName("Alice_to_Bob_Adapter");
adapter.setAdapted(cl1);
// the adapted reference already is a container
// r.getContents().add(adapter);
EReference ref1 = (EReference) adapter.eClass().getEStructuralFeature(ClassesPackage.TYPE_ADAPTER__TO);
Notification noti1 = NotificationHelper.createReferenceChangeNotification(adapter, ref1, null, cl2);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact1 = ia.getContextObjects(noti1);
assertTrue(impact1.size() == 1 && impact1.contains(cl1));
}
@Test
public void testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testVerySimpleInstanceScopeAnalysisWithTupleUsingSelf, this.cp).iterator()
.next().getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(cl1));
}
@Test
public void testVerySimpleInstanceScopeAnalysisWithTuple() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testVerySimpleInstanceScopeAnalysisWithTuple, this.cp).iterator().next()
.getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setName("Alice");
r.getContents().add(cl1);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, "Alice", "Bob");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 1 && impact.contains(cl1));
}
@Test
public void testGetFloorTokenNull() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse(testForIA2, this.cp).iterator().next().getSpecification().getBodyExpression();
SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
r.getContents().add(cl1);
cl1.setName("Alice");
cl1.setValueType(true);
ClassTypeDefinition ctd1 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
r.getContents().add(ctd1);
ctd1.setClazz(cl1);
ctd1.setLowerMultiplicity(1);
ctd1.setUpperMultiplicity(1);
ctd1.setOrdered(false);
ctd1.setUnique(false);
SapClass cl2 = ClassesFactory.eINSTANCE.createSapClass();
r.getContents().add(cl2);
cl2.setName("Bob");
ClassTypeDefinition ctd2 = ClassesFactory.eINSTANCE.createClassTypeDefinition();
r.getContents().add(ctd2);
ctd2.setClazz(cl2);
ctd2.setLowerMultiplicity(1);
ctd2.setUpperMultiplicity(1);
ctd2.setOrdered(false);
ctd2.setUnique(false);
ObjectLiteral ol1 = LiteralsFactory.eINSTANCE.createObjectLiteral();
r.getContents().add(ol1);
ol1.setValueClass(cl1);
AssociationEnd ae1 = ClassesFactory.eINSTANCE.createAssociationEnd();
r.getContents().add(ae1);
ae1.setName("Assoc_to_Alice");
ae1.setType(ctd1);
AssociationEnd ae2 = ClassesFactory.eINSTANCE.createAssociationEnd();
r.getContents().add(ae2);
ae2.setName("Assoc_to_Bob");
ae2.setType(ctd2);
Association a = ClassesFactory.eINSTANCE.createAssociation();
r.getContents().add(a);
a.setName("Assoc");
a.getEnds().add(ae1);
a.getEnds().add(ae2);
EAttribute att = (EAttribute) ae1.eClass().getEStructuralFeature(ClassesPackage.ASSOCIATION_END__NAME);
Notification noti = NotificationHelper.createAttributeChangeNotification(ae2, att, "Assoc_to_Bob",
"Assoc_to_Bob_changed");
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE
.createImpactAnalyzer(exp, LiteralsPackage.eINSTANCE.getObjectLiteral(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(1, impact.size());
assertTrue(impact.contains(ol1));
}
@Test
public void testPredicateEvaluation() {
OCLExpression exp = (OCLExpression) parse(
"context data::classes::SapClass inv testPredicateEvaluation:\n"
+ "self.ownedSignatures->select(s|s.sideEffectFree)->size() > 1", this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(exp);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("c1");
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("c2");
SapClass c3 = ClassesFactory.eINSTANCE.createSapClass();
c3.setName("c3");
MethodSignature m1 = ClassesFactory.eINSTANCE.createMethodSignature();
m1.setName("Signature 1");
m1.setSideEffectFree(true);
MethodSignature m2 = ClassesFactory.eINSTANCE.createMethodSignature();
m2.setName("Signature 2");
m2.setSideEffectFree(false);
MethodSignature m3 = ClassesFactory.eINSTANCE.createMethodSignature();
m3.setName("Signature 3");
m3.setSideEffectFree(true);
c1.getOwnedSignatures().add(m1);
c2.getOwnedSignatures().add(m2);
c3.getOwnedSignatures().add(m3);
EAttribute att = (EAttribute) m3.eClass().getEStructuralFeature(ClassesPackage.METHOD_SIGNATURE__SIDE_EFFECT_FREE);
Notification noti = NotificationHelper.createAttributeChangeNotification(m3, att, true, false);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 1 && impact.contains(c3));
noti = NotificationHelper.createAttributeChangeNotification(m3, att, false, true);
impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 1 && impact.contains(c3));
noti = NotificationHelper.createAttributeChangeNotification(m3, att, false, false);
impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 0);
noti = NotificationHelper.createAttributeChangeNotification(m3, att, true, true);
impact = ia.getContextObjects(noti);
assertTrue(impact.size() == 0);
}
@Test
public void testDeltaPropagationForAllInstances() {
OCLExpression exp = (OCLExpression) parse(
"context data::classes::SapClass inv testDeltaPropagationForAllInstances:\n"
+ "data::classes::SapClass.allInstances()->select(name='Humba')->size() = 0", this.cp).iterator().next()
.getSpecification().getBodyExpression();
this.cp.eResource().getContents().add(exp);
SapClass c1 = ClassesFactory.eINSTANCE.createSapClass();
c1.setName("Trala");
SapClass c2 = ClassesFactory.eINSTANCE.createSapClass();
c2.setName("Humba");
modelmanagement.Package pkg = ModelmanagementFactory.eINSTANCE.createPackage();
pkg.setName("Pkg");
this.cp.eResource().getContents().add(pkg);
Notification noti = NotificationHelper.createReferenceAddNotification(pkg, ModelmanagementPackage.eINSTANCE
.getPackage_Classes(), c1);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
assertEquals(0, impact.size());
noti = NotificationHelper.createReferenceAddNotification(pkg, ModelmanagementPackage.eINSTANCE.getPackage_Classes(), c2);
impact = ia.getContextObjects(noti);
assertTrue(impact.size() >= 2); // we don't know the exact size because of all the other test elements created for fixture
assertTrue(impact.contains(c1) && impact.contains(c2));
}
@Test
public void testSimpleUnusedCheckWithIfConditionAlwaysFalse() {
Resource r = this.cp.eResource();
OCLExpression exp = (OCLExpression) parse("context data::classes::SapClass inv testSimpleUnusedCheckWithIfClause:\n"+
"if false then self.valueType else true endif", this.cp).iterator().next()
.getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setValueType(false);
r.getContents().add(cl1);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__VALUE_TYPE);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, false, true);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
if (OptimizationActivation.getOption().isTracebackStepISAActive() && OptimizationActivation.getOption().isUnusedDetectionActive()) {
// expecting no impact because the then clause affected by the change is unused
assertEquals(0, impact.size());
} else {
assertEquals(1, impact.size());
assertEquals(cl1, impact.iterator().next());
}
}
@Test
public void testSimpleUnusedCheckWithIteratorSourceAlwaysEmpty() {
Resource r = this.cp.eResource();
// the idea: while self.valueType changes for cl1, self.adapters is always empty for the changed object
OCLExpression exp = (OCLExpression) parse("context data::classes::SapClass inv testSimpleUnusedCheckWithIfClause:\n"+
"self.adapters->select(a | a.to.valueType = self.valueType)", this.cp).iterator().next()
.getSpecification().getBodyExpression();
r.getContents().add(exp);
final SapClass cl1 = ClassesFactory.eINSTANCE.createSapClass();
cl1.setValueType(false);
r.getContents().add(cl1);
EAttribute att = (EAttribute) cl1.eClass().getEStructuralFeature(ClassesPackage.SAP_CLASS__VALUE_TYPE);
Notification noti = NotificationHelper.createAttributeChangeNotification(cl1, att, false, true);
ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
Collection<EObject> impact = ia.getContextObjects(noti);
if (OptimizationActivation.getOption().isUnusedDetectionActive()) {
// expecting no impact because the then clause affected by the change is unused
assertEquals(0, impact.size());
} else {
assertEquals(1, impact.size());
assertEquals(cl1, impact.iterator().next());
}
}
}