| /******************************************************************************* |
| * 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 org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EOperation; |
| import org.eclipse.emf.ecore.EParameter; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.ocl.ParserException; |
| import org.eclipse.ocl.SemanticException; |
| import org.eclipse.ocl.ecore.LoopExp; |
| import org.eclipse.ocl.ecore.OCL; |
| import org.eclipse.ocl.ecore.OCL.Helper; |
| import org.eclipse.ocl.ecore.OCLExpression; |
| import org.eclipse.ocl.examples.testutils.BaseTest; |
| import org.eclipse.ocl.util.Bag; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import company.CompanyFactory; |
| import company.CompanyPackage; |
| 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 QuickOclParseAndEvalTest extends BaseTest |
| { |
| private SapClass class1; |
| private SapClass class2; |
| private Parameter param; |
| private ClassTypeDefinition ctd; |
| private MethodSignature signature; |
| private OCL ocl; |
| private Helper oclHelper; |
| |
| private void assertInvalid(Object object) { |
| assertEquals(ocl.getEnvironment().getOCLStandardLibrary().getInvalid(), object); |
| } |
| |
| @Override |
| @Before |
| public void setUp() |
| { |
| class1 = ClassesFactory.eINSTANCE.createSapClass(); |
| class1.setName("class1"); |
| class2 = ClassesFactory.eINSTANCE.createSapClass(); |
| class2.setName("class2"); |
| signature = ClassesFactory.eINSTANCE.createMethodSignature(); |
| signature.setName("context"); |
| param = ClassesFactory.eINSTANCE.createParameter(); |
| param.setName("p"); |
| ctd = ClassesFactory.eINSTANCE.createClassTypeDefinition(); |
| ctd.setClazz(class1); |
| param.setOwnedTypeDefinition(ctd); |
| signature.setOwner(class2); |
| ocl = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance(); |
| oclHelper = ocl.createOCLHelper(); |
| oclHelper.setContext(ClassesPackage.eINSTANCE.getParameter()); |
| } |
| |
| /** |
| * Check if it is possible to create an expression in context Boolean |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionInContextBoolean() throws ParserException { |
| oclHelper.setContext(EcorePackage.eINSTANCE.getEBoolean()); |
| { |
| OCLExpression expression4 = oclHelper.createQuery("self"); |
| Object result4 = ocl.evaluate(true, expression4); |
| assertTrue((Boolean) result4); |
| Object result5 = ocl.evaluate(false, expression4); |
| assertFalse((Boolean) result5); |
| } |
| { |
| OCLExpression expression4 = oclHelper.createQuery("not self"); |
| Object result4 = ocl.evaluate(true, expression4); |
| assertFalse((Boolean) result4); |
| Object result5 = ocl.evaluate(false, expression4); |
| assertTrue((Boolean) result5); |
| } |
| } |
| |
| /** |
| * Check if a type name parses as a type literal |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithTypeLiteral() throws ParserException { |
| oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment()); |
| OCLExpression expression4 = oclHelper.createQuery("company::Division"); |
| Object result4 = ocl.evaluate(null, expression4); |
| assertTrue(result4 instanceof EClass); |
| assertEquals(CompanyPackage.eINSTANCE.getDivision(), result4); |
| OCLExpression expression5 = oclHelper.createQuery("Division"); |
| Object result5 = ocl.evaluate(null, expression5); |
| assertTrue(result5 instanceof EClass); |
| assertEquals(CompanyPackage.eINSTANCE.getDivision(), result5); |
| } |
| |
| /** |
| * Check what happens when ->at(...) argument is out of bounds |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithOutOfBoundsAtArgument() throws ParserException { |
| oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment()); |
| OCLExpression expression4 = oclHelper.createQuery("Sequence{1..2}->at(3)"); |
| Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4); |
| assertInvalid(result4); |
| } |
| |
| |
| /** |
| * Check what happens when last value of a range is invalid instead of an Integer. Interestingly, this aborts the whole |
| * evaluation and even "bypasses" a trailing oclIsInvalid(). |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithInvalidAsLastPartOfRange() throws ParserException { |
| oclHelper.setContext(CompanyPackage.eINSTANCE.getDepartment()); |
| OCLExpression expression4 = oclHelper.createQuery("(Sequence{1..(self.parentDepartment.subDepartment->size())}->select(i | i>0)).oclIsInvalid()"); |
| Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4); |
| assertInvalid(result4); |
| } |
| |
| /** |
| * Check if invalid can be passed into an operation as argument |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithMixOfPrimitiveAndObjectTypesInCollectionLiteral() throws ParserException { |
| OCLExpression expression4 = oclHelper.createQuery("Set{1, 2, self}->select(i | i.oclIsKindOf(Integer))"); |
| Object result4 = ocl.evaluate(CompanyFactory.eINSTANCE.createDepartment(), expression4); |
| assertTrue(result4 instanceof Collection); |
| assertTrue(((Collection<?>) result4).contains(1)); |
| assertTrue(((Collection<?>) result4).contains(2)); |
| } |
| |
| /** |
| * Check if invalid can be passed into an operation as argument |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithInvalidInOperationArgument() throws ParserException { |
| EClass cl = CompanyPackage.eINSTANCE.getDepartment(); |
| EOperation op = EcoreFactory.eINSTANCE.createEOperation(); |
| try { |
| op.setName("myOp"); |
| op.setEType(EcorePackage.eINSTANCE.getEBoolean()); |
| EParameter param = EcoreFactory.eINSTANCE.createEParameter(); |
| param.setName("humba"); |
| param.setEType(org.eclipse.emf.ecore.EcorePackage.eINSTANCE |
| .getEClassifier()); |
| op.getEParameters().add(param); |
| cl.getEOperations().add(op); |
| oclHelper.setOperationContext(cl, op); |
| oclHelper.createBodyCondition("humba.oclIsInvalid()"); |
| oclHelper.setContext(cl); |
| OCLExpression expression4 = oclHelper |
| .createQuery("self.myOp(invalid)"); |
| Object result4 = ocl.evaluate( |
| CompanyFactory.eINSTANCE.createDepartment(), expression4); |
| assertEquals(true, result4); |
| } finally { |
| cl.getEOperations().remove(op); |
| } |
| } |
| |
| /** |
| * Ensure that "or" and "and" do shortcut evaluation for invalid arguments |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithInvalidInBooleanShortcutEval() throws ParserException { |
| OCLExpression expression4 = oclHelper.createQuery("false and invalid"); |
| Object result4 = ocl.evaluate(null, expression4); |
| assertEquals(false, result4); |
| OCLExpression expression5 = oclHelper.createQuery("true or invalid"); |
| Object result5 = ocl.evaluate(null, expression5); |
| assertEquals(true, result5); |
| OCLExpression expression6 = oclHelper.createQuery("(invalid or true).oclIsInvalid()"); |
| Object result6 = ocl.evaluate(null, expression6); |
| assertEquals(false, result6); |
| OCLExpression expression7 = oclHelper.createQuery("(invalid and false).oclIsInvalid()"); |
| Object result7 = ocl.evaluate(null, expression7); |
| assertEquals(false, result7); |
| OCLExpression expression8 = oclHelper.createQuery("(invalid or true)"); |
| Object result8 = ocl.evaluate(null, expression8); |
| assertEquals(true, result8); |
| OCLExpression expression9 = oclHelper.createQuery("(invalid and false)"); |
| Object result9 = ocl.evaluate(null, expression9); |
| assertEquals(false, result9); |
| } |
| |
| /** |
| * Testing if a let-expression evaluates to OclInvalid if the initExpression evaluates to OclInvalid although |
| * the variable is not used in the "in" expression. |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithInvalidLetInitExpression() throws ParserException { |
| OCLExpression expression4 = oclHelper |
| .createQuery("let x:Integer=self.name.size() in 1+2"); |
| Object result4 = ocl.evaluate(null, expression4); |
| assertEquals(3, result4); |
| } |
| |
| /** |
| * Testing if two iterator variables appear as such |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionForAllWithTwoIterators() throws ParserException { |
| OCLExpression expression4 = oclHelper |
| .createQuery("Set{1, 2, 3}->forAll(i, j | i+j <> 7)"); |
| assertEquals(2, ((LoopExp) expression4).getIterator().size()); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertEquals(true, result4); |
| } |
| |
| /** |
| * Testing if an iterate's accumulator expression is really evaluated even when the iterate is applied to an empty collection |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionAccumulatorForIterateOnEmptyCollection() throws ParserException { |
| OCLExpression expression4 = oclHelper |
| .createQuery("let s:Set(Integer)=Set{} in s->iterate(i:Integer; acc:Integer=1 | acc+1)"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertEquals(1, result4); |
| } |
| |
| /** |
| * Testing if shadowing a variable by an iterator leads to incorrect results because the shadowed |
| * variable is overwritten by the iterator values |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionIteratorShadowingLetVariable() throws ParserException |
| { |
| param.setOwnedTypeDefinition(ctd); |
| ctd.setClazz(null); |
| try { |
| OCLExpression expression4 = oclHelper.createQuery("let i:Integer=1 in if self.ownedTypeDefinition->select(i|i.oclAsType(ClassTypeDefinition).clazz->notEmpty())->isEmpty() then i else 0 endif"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertEquals(1, result4); |
| } catch (SemanticException e) { |
| // it's ok if the OCL implementation doesn't accept shadowing: |
| assertEquals("Variable name already used: (i)", e.getMessage()); |
| } |
| } |
| |
| /** |
| * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator |
| * returns a valid result |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithTupleWithNull() throws ParserException |
| { |
| param.setName(null); |
| OCLExpression expression5 = oclHelper.createQuery("Tuple{c:Tuple(d:String)=Tuple{d=self.name}}.c.d"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertNull(result5); |
| } |
| |
| /** |
| * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator |
| * returns a valid result |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithCollectOfNullValue() throws ParserException |
| { |
| OCLExpression expression5 = oclHelper.createQuery("Set{1, 2}->collect(null)"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertEquals(2, ((Collection<?>) result5).size()); |
| assertTrue(((Collection<?>) result5).contains(null)); |
| } |
| |
| /** |
| * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator |
| * returns a valid result |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithIncludingNullInSequence() throws ParserException |
| { |
| OCLExpression expression5 = oclHelper.createQuery("Sequence{1}->including(null)"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertEquals(2, ((Collection<?>) result5).size()); |
| assertTrue(((Collection<?>) result5).contains(null)); |
| } |
| |
| /** |
| * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator |
| * returns a valid result |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithSizeOverSequenceContainingNull() throws ParserException |
| { |
| OCLExpression expression5 = oclHelper.createQuery("Sequence{1}->including(null)->size()"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertEquals(2, result5); |
| } |
| |
| /** |
| * Ensures that an OclInvalid value does not pass a select filter, yet the select iterator |
| * returns a valid result |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithCollectOverOclInvalid() throws ParserException |
| { |
| OCLExpression expression5 = oclHelper.createQuery("Set{self, invalid}->collect(i | i)"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertInvalid(result5); |
| } |
| |
| /** |
| * Ensures that an OclInvalid value propagates from a collection literal to the overall expression |
| */ |
| @Test |
| public void testParseAndEvaluateOclExpressionWithSelectOverOclInvalid() throws ParserException |
| { |
| OCLExpression expression5 = oclHelper.createQuery("Set{self, invalid}->select(i | i.name = 'p')"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertInvalid(result5); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpression() throws ParserException |
| { |
| OCLExpression expression = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz"); |
| Object result = ocl.evaluate(param, expression); |
| assertEquals(class1, result); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithOperationCallOnNullValue() throws ParserException |
| { |
| param.setOwnedTypeDefinition(null); |
| OCLExpression expression2 = oclHelper.createQuery("self.ownedTypeDefinition.getInnermost()"); |
| Object result = ocl.evaluate(param, expression2); |
| assertEquals(ocl.getEnvironment().getOCLStandardLibrary().getInvalid(), result); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithPropertyCallOnNullValue() throws ParserException |
| { |
| param.setOwnedTypeDefinition(null); |
| OCLExpression expression2 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.oclIsInvalid()"); |
| Object result2 = ocl.evaluate(param, expression2); |
| assertTrue((Boolean)result2); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithCollectOverNullValue() throws ParserException |
| { |
| param.setOwnedTypeDefinition(null); |
| OCLExpression expression3 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition)->collect(clazz)"); |
| Object result3 = ocl.evaluate(param, expression3); |
| assertEquals(0, ((Collection< ? >)result3).size()); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionCollectWithBodyEvaluatingToNull() throws ParserException |
| { |
| param.setOwnedTypeDefinition(ctd); |
| ctd.setClazz(null); |
| OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition)->collect(clazz)"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertTrue(((Bag< ? >)result4).contains(null)); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithImplicitCollectOverOperationCallResult() throws ParserException |
| { |
| OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.getAssociationEnds().otherEnd()"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertTrue(((Collection<?>) result4).isEmpty()); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithDelegatesToSimulation() throws ParserException |
| { |
| OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition.oclAsType(data::classes::ClassTypeDefinition).clazz.getAssociationEnds().otherEnd()->select(delegation->notEmpty()).type.clazz->reject(c|c=self)->asSet()"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertTrue(((Collection<?>) result4).isEmpty()); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithImplicitSetLiteral() throws ParserException |
| { |
| OCLExpression expression4 = oclHelper.createQuery("self.ownedTypeDefinition->isEmpty()"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertFalse((Boolean) result4); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithImplicitSetLiteralCheckingForIsEmpty() throws ParserException |
| { |
| param.setOwnedTypeDefinition(null); |
| OCLExpression expression5 = oclHelper.createQuery("self.ownedTypeDefinition->isEmpty()"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertTrue((Boolean) result5); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithNullInSetLiteral() throws ParserException |
| { |
| param.setOwnedTypeDefinition(null); |
| OCLExpression expression5 = oclHelper.createQuery("Set{null}->isEmpty()"); |
| Object result5 = ocl.evaluate(param, expression5); |
| assertFalse((Boolean) result5); |
| OCLExpression expression6 = oclHelper.createQuery("null->isEmpty()"); |
| Object result6 = ocl.evaluate(param, expression6); |
| assertTrue((Boolean) result6); |
| } |
| |
| @Test |
| public void testParseAndEvaluateOclExpressionWithEmptySetLiteralIncludingNull() throws ParserException |
| { |
| OCLExpression expression4 = oclHelper.createQuery("Set{}->including(null)->isEmpty()"); |
| Object result4 = ocl.evaluate(param, expression4); |
| assertFalse((Boolean) result4); |
| } |
| |
| } |