/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation, Zeligsoft Inc., 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: * IBM - Initial API and implementation * Achim Demelt - Bug 245897 * Zeligsoft - Bug 245897 *******************************************************************************/ package org.eclipse.ocl.ecore.tests; import java.math.BigDecimal; import java.math.BigInteger; import java.util.LinkedHashSet; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.ETypedElement; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.impl.EObjectImpl; import org.eclipse.ocl.ParserException; import org.eclipse.ocl.expressions.CollectionKind; import org.eclipse.ocl.expressions.CollectionLiteralExp; import org.eclipse.ocl.expressions.OCLExpression; import org.eclipse.ocl.lpg.ProblemHandler; import org.eclipse.ocl.options.ParsingOptions; import org.eclipse.ocl.options.ProblemOption; import org.eclipse.ocl.types.CollectionType; /** * Tests for comparison (<, <=, >=, >) expressions. * * @author Christian W. Damus (cdamus) */ @SuppressWarnings("nls") public class ComparisonTest extends AbstractTestSuite { EPackage pkg; EClass thingType; EAttribute values; EAttribute bdValue; EAttribute biValue; EDataType valueType; EClass numeroType; EReference numeros; EClass comparable; EDataType myDataType; EObject thing; /** * Tests the < operator. */ public void test_lessThan() { helper.setContext(thingType); try { // primitives assertTrue(check(helper, thing, "1 < 2")); assertFalse(check(helper, thing, "21 < 2")); assertTrue(check(helper, thing, "1 < 2.0")); assertFalse(check(helper, thing, "21 < 2.0")); assertTrue(check(helper, thing, "1.0 < 2")); assertFalse(check(helper, thing, "21.0 < 2")); assertTrue(check(helper, thing, "1.0 < 2.0")); assertFalse(check(helper, thing, "21.0 < 2.0")); assertTrue(check(helper, thing, "'a' < 'b'")); assertFalse(check(helper, thing, "'ba' < 'b'")); // BigDecimal tests thing.eSet(bdValue, new BigDecimal("1")); assertTrue(check(helper, thing, "bdValue < 1.1")); assertTrue(check(helper, thing, "bdValue < 2")); assertTrue(check(helper, thing, "bdValue < 2.0")); thing.eSet(bdValue, new BigDecimal("1.0")); assertTrue(check(helper, thing, "bdValue < 1.1")); assertTrue(check(helper, thing, "bdValue < 2")); assertTrue(check(helper, thing, "bdValue < 2.0")); thing.eSet(bdValue, new BigDecimal("1.1")); assertTrue(check(helper, thing, "bdValue < 1.2")); assertTrue(check(helper, thing, "bdValue < 2")); assertTrue(check(helper, thing, "bdValue < 2.0")); // BigInteger tests thing.eSet(biValue, new BigInteger("1")); assertTrue(check(helper, thing, "biValue < 2")); assertTrue(check(helper, thing, "biValue < 2.1")); @SuppressWarnings("unchecked") List<Value> valuesList = (List<Value>) thing.eGet(values); valuesList.add(new Value("a")); valuesList.add(new Value("b")); ParsingOptions.setOption(helper.getOCL().getEnvironment(), ParsingOptions.USE_COMPARE_TO_OPERATION, true); assertTrue(check(helper, thing, "values->at(1) < values->at(2)")); assertFalse(check(helper, thing, "values->at(2) < values->at(1)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the <= operator. */ public void test_lessThanOrEqual() { helper.setContext(thingType); try { // primitives assertTrue(check(helper, thing, "1 <= 2")); assertTrue(check(helper, thing, "1 <= 1")); assertFalse(check(helper, thing, "21 <= 2")); assertTrue(check(helper, thing, "1 <= 2.0")); assertTrue(check(helper, thing, "1 <= 1.0")); assertFalse(check(helper, thing, "21 <= 2.0")); assertTrue(check(helper, thing, "1.0 <= 2")); assertTrue(check(helper, thing, "1.0 <= 1")); assertFalse(check(helper, thing, "21.0 <= 2")); assertTrue(check(helper, thing, "1.0 <= 2.0")); assertTrue(check(helper, thing, "1.0 <= 1.0")); assertFalse(check(helper, thing, "21.0 <= 2.0")); assertTrue(check(helper, thing, "'a' <= 'b'")); assertTrue(check(helper, thing, "'a' <= 'a'")); assertFalse(check(helper, thing, "'ba' <= 'b'")); // BigDecimal tests thing.eSet(bdValue, new BigDecimal("1")); assertTrue(check(helper, thing, "bdValue <= 1")); assertTrue(check(helper, thing, "bdValue <= 1.0")); assertTrue(check(helper, thing, "bdValue <= 1.1")); thing.eSet(bdValue, new BigDecimal("1.0")); assertTrue(check(helper, thing, "bdValue <= 1")); assertTrue(check(helper, thing, "bdValue <= 1.0")); assertTrue(check(helper, thing, "bdValue <= 1.1")); thing.eSet(bdValue, new BigDecimal("1.1")); assertTrue(check(helper, thing, "bdValue <= 1.1")); assertTrue(check(helper, thing, "bdValue <= 2.0")); assertTrue(check(helper, thing, "bdValue <= 2")); // BigInteger tests thing.eSet(biValue, new BigInteger("1")); assertTrue(check(helper, thing, "biValue <= 1")); assertTrue(check(helper, thing, "biValue <= 1.0")); assertTrue(check(helper, thing, "biValue <= 1.1")); @SuppressWarnings("unchecked") List<Value> valuesList = (List<Value>) thing.eGet(values); valuesList.add(new Value("a")); valuesList.add(new Value("b")); ParsingOptions.setOption(helper.getOCL().getEnvironment(), ParsingOptions.USE_COMPARE_TO_OPERATION, true); assertTrue(check(helper, thing, "values->at(1) <= values->at(2)")); assertTrue(check(helper, thing, "values->at(1) <= values->at(1)")); assertFalse(check(helper, thing, "values->at(2) <= values->at(1)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the > operator. */ public void test_greaterThan() { helper.setContext(thingType); try { // primitives assertTrue(check(helper, thing, "2 > 1")); assertFalse(check(helper, thing, "2 > 21")); assertTrue(check(helper, thing, "2 > 1.0")); assertFalse(check(helper, thing, "2 > 21.0")); assertTrue(check(helper, thing, "2.0 > 1")); assertFalse(check(helper, thing, "2.0 > 21")); assertTrue(check(helper, thing, "2.0 > 1.0")); assertFalse(check(helper, thing, "2.0 > 21.0")); assertTrue(check(helper, thing, "'b' > 'a'")); assertFalse(check(helper, thing, "'a' > 'b'")); // BigDecimal tests thing.eSet(bdValue, new BigDecimal("1")); assertTrue(check(helper, thing, "bdValue > 0")); assertTrue(check(helper, thing, "bdValue > 0.0")); assertTrue(check(helper, thing, "bdValue > 0.1")); thing.eSet(bdValue, new BigDecimal("1.0")); assertTrue(check(helper, thing, "bdValue > 0")); assertTrue(check(helper, thing, "bdValue > 0.0")); assertTrue(check(helper, thing, "bdValue > 0.1")); thing.eSet(bdValue, new BigDecimal("1.1")); assertTrue(check(helper, thing, "bdValue > 1")); assertTrue(check(helper, thing, "bdValue > 1.0")); assertTrue(check(helper, thing, "bdValue > 1.09")); // BigInteger tests thing.eSet(biValue, new BigInteger("1")); assertTrue(check(helper, thing, "biValue > 0")); assertTrue(check(helper, thing, "biValue > 0.1")); @SuppressWarnings("unchecked") List<Value> valuesList = (List<Value>) thing.eGet(values); valuesList.add(new Value("b")); valuesList.add(new Value("a")); ParsingOptions.setOption(helper.getOCL().getEnvironment(), ParsingOptions.USE_COMPARE_TO_OPERATION, true); assertTrue(check(helper, thing, "values->at(1) > values->at(2)")); assertFalse(check(helper, thing, "values->at(2) > values->at(1)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the >= operator. */ public void test_greaterThanOrEqual() { helper.setContext(thingType); try { // primitives assertTrue(check(helper, thing, "2 >= 1")); assertTrue(check(helper, thing, "2 >= 2")); assertFalse(check(helper, thing, "2 >= 21")); assertTrue(check(helper, thing, "2 >= 1.0")); assertTrue(check(helper, thing, "2 >= 2.0")); assertFalse(check(helper, thing, "2 >= 21.0")); assertTrue(check(helper, thing, "2.0 >= 1")); assertTrue(check(helper, thing, "2.0 >= 2")); assertFalse(check(helper, thing, "2.0 >= 21")); assertTrue(check(helper, thing, "2.0 >= 1.0")); assertTrue(check(helper, thing, "2.0 >= 2.0")); assertFalse(check(helper, thing, "2.0 >= 21.0")); assertTrue(check(helper, thing, "'b' >= 'a'")); assertTrue(check(helper, thing, "'b' >= 'b'")); assertFalse(check(helper, thing, "'a' >= 'b'")); // BigDecimal tests thing.eSet(bdValue, new BigDecimal("1")); assertTrue(check(helper, thing, "bdValue >= 1")); assertTrue(check(helper, thing, "bdValue >= 1.0")); assertTrue(check(helper, thing, "bdValue >= 0.9")); thing.eSet(bdValue, new BigDecimal("1.0")); assertTrue(check(helper, thing, "bdValue >= 1")); assertTrue(check(helper, thing, "bdValue >= 1.0")); assertTrue(check(helper, thing, "bdValue >= 0.9")); thing.eSet(bdValue, new BigDecimal("1.1")); assertTrue(check(helper, thing, "bdValue >= 1")); assertTrue(check(helper, thing, "bdValue >= 1.0")); assertTrue(check(helper, thing, "bdValue >= 1.1")); // BigInteger tests thing.eSet(biValue, new BigInteger("1")); assertTrue(check(helper, thing, "biValue >= 0.9")); assertTrue(check(helper, thing, "biValue >= 1")); assertTrue(check(helper, thing, "biValue >= 1.0")); @SuppressWarnings("unchecked") List<Value> valuesList = (List<Value>) thing.eGet(values); valuesList.add(new Value("b")); valuesList.add(new Value("a")); ParsingOptions.setOption(helper.getOCL().getEnvironment(), ParsingOptions.USE_COMPARE_TO_OPERATION, true); assertTrue(check(helper, thing, "values->at(1) >= values->at(2)")); assertTrue(check(helper, thing, "values->at(1) >= values->at(1)")); assertFalse(check(helper, thing, "values->at(2) >= values->at(1)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the sortedby iterator. */ public void test_sortedBy() { helper.setContext(thingType); try { @SuppressWarnings("unchecked") List<Value> valuesList = (List<Value>) thing.eGet(values); valuesList.add(new Value("b")); valuesList.add(new Value("c")); valuesList.add(new Value("a")); LinkedHashSet<Value> expected = new LinkedHashSet<Value>(); expected.add(valuesList.get(2)); expected.add(valuesList.get(0)); expected.add(valuesList.get(1)); assertEquals(expected, evaluate(helper, thing, "values->sortedBy(e | e)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the <code>=</code> and <code><></code> operators for the * Invalid type. */ public void test_invalid_equality() { helper.setContext(thingType); try { assertFalse(check(helper, thing, "OclInvalid = 'a'")); assertTrue(check(helper, thing, "OclInvalid <> 'a'")); assertTrue(check(helper, thing, "OclInvalid = OclInvalid")); assertFalse(check(helper, thing, "OclInvalid <> OclInvalid")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests the <code>=</code> and <code><></code> operators for the * OclVoid type. */ public void test_void_equality() { helper.setContext(thingType); try { assertFalse(check(helper, thing, "null = 'a'")); assertTrue(check(helper, thing, "null <> 'a'")); assertTrue(check(helper, thing, "null = null")); assertFalse(check(helper, thing, "null <> null")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests evaluation of the arithmetic operations on integers. */ public void test_integerArithmetic() { helper.setContext(thingType); try { assertEquals(new Integer(1), evaluate(helper, thing, "3 - 2")); assertEquals(new Integer(3), evaluate(helper, thing, "1 + 2")); assertEquals(new Double(2.0), evaluate(helper, thing, "6 / 3")); assertEquals(new Integer(6), evaluate(helper, thing, "2 * 3")); assertEquals(new Integer(-1), evaluate(helper, thing, "- 1")); assertEquals(new Integer(3), evaluate(helper, thing, "(2 - 5).abs()")); assertEquals(new Integer(3), evaluate(helper, thing, "3.max(2)")); assertEquals(new Integer(2), evaluate(helper, thing, "3.min(2)")); assertEquals(new Integer(3), evaluate(helper, thing, "7.div(2)")); assertEquals(new Integer(1), evaluate(helper, thing, "7.mod(2)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests evaluation of the arithmetic operations on reals. */ public void test_realArithmetic() { helper.setContext(thingType); try { assertEquals(new Double(1.0), evaluate(helper, thing, "3.0 - 2.0")); assertEquals(new Double(3.0), evaluate(helper, thing, "1.0 + 2.0")); assertEquals(new Double(2.0), evaluate(helper, thing, "6.0 / 3.0")); assertEquals(new Double(6.0), evaluate(helper, thing, "2.0 * 3.0")); assertEquals(new Double(-1.0), evaluate(helper, thing, "- 1.0")); assertEquals(new Double(3.0), evaluate(helper, thing, "(2.0 - 5.0).abs()")); assertEquals(new Double(3.0), evaluate(helper, thing, "3.0.max(2.0)")); assertEquals(new Double(2.0), evaluate(helper, thing, "3.0.min(2.0)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests evaluation of the arithmetic operations on integers, with real * arguments. */ public void test_mixedArithmetic() { helper.setContext(thingType); try { assertEquals(new Double(1.0), evaluate(helper, thing, "3 - 2.0")); assertEquals(new Double(3.0), evaluate(helper, thing, "1 + 2.0")); assertEquals(new Double(2.0), evaluate(helper, thing, "6 / 3.0")); assertEquals(new Double(6.0), evaluate(helper, thing, "2 * 3.0")); assertEquals(new Double(3.0), evaluate(helper, thing, "3.max(2.0)")); assertEquals(new Double(2.0), evaluate(helper, thing, "3.min(2.0)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } public void test_dotNotationForSymbolicOperationNames() { ParsingOptions.setOption(helper.getEnvironment(), ProblemOption.CONCEPTUAL_OPERATION_NAME, ProblemHandler.Severity.OK); helper.setContext(EcorePackage.Literals.EINT); Integer minusOne = new Integer(-1); Integer one = new Integer(1); Integer two = new Integer(2); Double doubleTwo = new Double(2.0); Integer three = new Integer(3); Integer six = new Integer(6); try { // new NUMERIC_OPERATION token assertEquals(one, evaluate(helper, one, "3.-(2)")); assertEquals(three, evaluate(helper, one, "1.+(2)")); assertEquals(doubleTwo, evaluate(helper, one, "6./(3)")); assertEquals(six, evaluate(helper, one, "2.*(3)")); assertTrue(check(helper, one, "1.<(2)")); assertTrue(check(helper, one, "1.<=(2)")); assertTrue(check(helper, one, "2.>=(1)")); assertTrue(check(helper, one, "2.>(1)")); // new operationCallExpCS rule assertEquals(one, evaluate(helper, three, "self.-(2)")); assertEquals(three, evaluate(helper, one, "self.+(2)")); assertEquals(doubleTwo, evaluate(helper, six, "self./(3)")); assertEquals(six, evaluate(helper, two, "self.*(3)")); assertTrue(check(helper, one, "self.<(2)")); assertTrue(check(helper, one, "self.<=(2)")); assertTrue(check(helper, two, "self.>=(1)")); assertTrue(check(helper, two, "self.>(1)")); // unary minus assertEquals(minusOne, evaluate(helper, one, "-1")); assertEquals(minusOne, evaluate(helper, one, "-self")); assertEquals(minusOne, evaluate(helper, one, "self.\"-\"()")); assertEquals(minusOne, evaluate(helper, one, "self.-()")); assertEquals(one, evaluate(helper, one, "- self.\"-\"()")); assertEquals(one, evaluate(helper, one, "- self.-()")); assertEquals(one, evaluate(helper, one, "- -1")); assertEquals(one, evaluate(helper, one, "- -self")); // unary not helper.setContext(EcorePackage.Literals.EBOOLEAN); assertEquals(Boolean.FALSE, evaluate(helper, Boolean.TRUE, "not self")); assertEquals(Boolean.FALSE, evaluate(helper, Boolean.TRUE, "self.\"not\"()")); assertEquals(Boolean.FALSE, evaluate(helper, Boolean.TRUE, "self.not()")); assertEquals(Boolean.TRUE, evaluate(helper, Boolean.TRUE, "not not self")); assertEquals(Boolean.TRUE, evaluate(helper, Boolean.TRUE, "not self._not()")); assertEquals(Boolean.TRUE, evaluate(helper, Boolean.TRUE, "not self.not()")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } ParsingOptions.setOption(helper.getEnvironment(), ProblemOption.CONCEPTUAL_OPERATION_NAME, ProblemHandler.Severity.ERROR); try { assertEquals(one, evaluate(helper, one, "3.-(2)")); fail("Missing exception"); } catch (Exception e) { } } public void test_javaImplementationsOfInfixOperators() { helper.setContext(thingType); Numero three = new Numero(3); Numero four = new Numero(4); Numero eight = new Numero(8); Numero twelve = new Numero(12); try { assertEquals(four, evaluate(helper, thing, "numeros->at(1) - numeros->at(2)")); assertEquals(eight, evaluate(helper, thing, "numeros->at(1) + numeros->at(2)")); assertEquals(three, evaluate(helper, thing, "numeros->at(1) / numeros->at(2)")); assertEquals(twelve, evaluate(helper, thing, "numeros->at(1) * numeros->at(2)")); assertTrue(check(helper, thing, "numeros->at(2) < numeros->at(1)")); assertTrue(check(helper, thing, "numeros->at(2) <= numeros->at(1)")); assertTrue(check(helper, thing, "numeros->at(1) > numeros->at(2)")); assertTrue(check(helper, thing, "numeros->at(1) >= numeros->at(2)")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } public void test_comparisonOfBooleanOperations_137487() { EClass ctx = EcorePackage.eINSTANCE.getEClass(); helper.setContext(ctx.eClass()); try { assertTrue(check(helper, ctx, "self.isSuperTypeOf(self)")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) and true")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) or false")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) xor false")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) implies true")); assertFalse(check(helper, ctx, "self.isSuperTypeOf(self) implies false")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) = true")); assertTrue(check(helper, ctx, "self.isSuperTypeOf(self) <> false")); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } public void test_enumerationLiteralEquality_137546() { // test all of the collection kinds for bug 176308 for (CollectionKind kind : CollectionKind.values()) { CollectionLiteralExp<EClassifier> ctx = oclFactory.createCollectionLiteralExp(); ctx.setKind(kind); helper.setInstanceContext(ctx); try { assertTrue(check(helper, ctx, "ocl::expressions::CollectionKind::\"" + kind.getLiteral() + "\" = self.kind")); assertTrue(check(helper, ctx, "self.kind = ocl::expressions::CollectionKind::\"" + kind.getLiteral() + '"')); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } } /** * Tests that unrecognized data types are represented by themselves, not * by OclAny. */ public void test_dataTypes_137158() { EPackage epackage = EcoreFactory.eINSTANCE.createEPackage(); epackage.setName("mypkg"); EClass eclass = EcoreFactory.eINSTANCE.createEClass(); eclass.setName("B"); epackage.getEClassifiers().add(eclass); EOperation eoperation = EcoreFactory.eINSTANCE.createEOperation(); eoperation.setName("f"); EDataType edatatype = EcoreFactory.eINSTANCE.createEDataType(); edatatype.setName("Thread"); edatatype.setInstanceClass(Thread.class); epackage.getEClassifiers().add(edatatype); eoperation.setEType(edatatype); eclass.getEOperations().add(eoperation); helper.setContext(eclass); try { OCLExpression<EClassifier> expr = helper.createQuery("self.f()"); EClassifier type = expr.getType(); assertSame(edatatype, type); eoperation.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); expr = helper.createQuery("self.f()"); type = expr.getType(); assertTrue(type instanceof CollectionType<?, ?>); type = ((org.eclipse.ocl.ecore.CollectionType) type).getElementType(); assertSame(edatatype, type); eoperation.setUpperBound(1); eoperation.setEType(EcorePackage.Literals.EJAVA_OBJECT); expr = helper.createQuery("self.f()"); type = expr.getType(); assertSame(getOCLStandardLibrary().getOclAny(), type); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests support for attributes of ELong type. */ public void test_supportForELongAttributes_198451() { helper.setContext(thingType); long maxInt = Integer.MAX_VALUE; long maxIntMinusOne = (long) Integer.MAX_VALUE - 1; long maxIntSquared = ((long) Integer.MAX_VALUE) * ((long) Integer.MAX_VALUE); double quotient = (double) maxIntSquared / (double) maxIntMinusOne; Numero maxIntN = new Numero(maxInt); Numero maxIntMinusOneN = new Numero(maxIntMinusOne); Numero maxIntSquaredN = new Numero(maxIntSquared); @SuppressWarnings("unchecked") EList<Numero> list = (EList<Numero>) thing.eGet(numeros); list.clear(); list.add(maxIntN); list.add(maxIntMinusOneN); list.add(maxIntSquaredN); list.add(new Numero(1)); try { // this should be OK because both values can be represented as integers assertEquals(1, evaluate(helper, thing, "numeros->at(1).asLong() - numeros->at(2).asLong()")); // same number represented in different precision assertTrue(check(helper, thing, "numeros->at(4).asLong() = 1")); // different numbers represented in different precision assertTrue(check(helper, thing, "numeros->at(4).asLong() <> 2")); // this is also OK, because we compute in high precision and coerce // the result to lower precision assertEquals(quotient, evaluate(helper, thing, "numeros->at(3).asLong() / numeros->at(2).asLong()")); // this is another case where the intermediate result is high-precision but // the result is low assertEquals((int) maxIntMinusOne, evaluate(helper, thing, String.format("(%d + %d).div(2) - 1", maxInt, maxInt))); // finally, a case where the result is in high precision (new capability) assertEquals(maxIntSquared, evaluate(helper, thing, String.format("%d * %d", maxInt, maxInt))); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests that the <tt>OclAny::=</tt> operation does not require the source * and argument types to be related. */ public void test_OclAny_equals_unrelatedArgumentTypes() { helper.setContext(fruit); try { // this should be OK anyways helper.createInvariant( "not Apple.allInstances()->exists(a | a = self)"); helper.createInvariant( "not ecore::EClass.allInstances()->exists(c | c = self)"); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * Tests that the <tt>OclAny::<></tt> operation does not require the * source and argument types to be related. */ public void test_OclAny_notEquals_unrelatedArgumentTypes() { helper.setContext(fruit); try { // this should be OK anyways helper.createInvariant( "Apple.allInstances()->forAll(a | a <> self)"); helper.createInvariant( "ecore::EClass.allInstances()->forAll(c | c <> self)"); } catch (Exception e) { fail("Failed to parse or evaluate: " + e.getLocalizedMessage()); } } /** * The compareTo() method is a Java-ism that should not be supported by * OCL as a definition of the relational comparison operations. */ public void test_compareToOnlyUsedByJavaImplementation_212804() { helper.setContext(comparable); try { // this should not parse because the >= operation is not defined helper.createInvariant( "Comparable.allInstances()->forAll(c | self >= c)"); fail("Should not have parsed"); } catch (ParserException e) { // success System.out.println("Got expected exception: " + e.getLocalizedMessage()); } catch (Exception e) { fail("Unexpected exception during parse: " + e.getLocalizedMessage()); } } /** * The compareTo() method is a Java-ism that should not be supported by * OCL as a definition of the relational comparison operations. */ public void test_comparableDataTypes_212804() { helper.setContext(myDataType); try { // this should not parse because the >= operation is not defined helper.createInvariant( "MyDataType.allInstances()->forAll(d | self >= d)"); fail("Should not have parsed"); } catch (ParserException e) { // success System.out.println("Got expected exception: " + e.getLocalizedMessage()); } catch (Exception e) { fail("Unexpected exception during parse: " + e.getLocalizedMessage()); } } // // Framework methods // @Override protected void setUp() { super.setUp(); pkg = EcoreFactory.eINSTANCE.createEPackage(); pkg.setName("pkg"); EFactory factory = EcoreFactory.eINSTANCE.createEFactory(); pkg.setEFactoryInstance(factory); valueType = EcoreFactory.eINSTANCE.createEDataType(); valueType.setName("Value"); valueType.setInstanceClass(Value.class); pkg.getEClassifiers().add(valueType); thingType = EcoreFactory.eINSTANCE.createEClass(); thingType.setName("Thing"); pkg.getEClassifiers().add(thingType); bdValue = EcoreFactory.eINSTANCE.createEAttribute(); bdValue.setName("bdValue"); bdValue.setEType(EcorePackage.Literals.EBIG_DECIMAL); bdValue.setUpperBound(1); thingType.getEStructuralFeatures().add(bdValue); biValue = EcoreFactory.eINSTANCE.createEAttribute(); biValue.setName("biValue"); biValue.setEType(EcorePackage.Literals.EBIG_INTEGER); biValue.setUpperBound(1); thingType.getEStructuralFeatures().add(biValue); values = EcoreFactory.eINSTANCE.createEAttribute(); values.setName("values"); values.setEType(valueType); values.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); thingType.getEStructuralFeatures().add(values); numeroType = EcoreFactory.eINSTANCE.createEClass(); numeroType.setName("Numero"); numeroType.setInstanceClass(Numero.class); pkg.getEClassifiers().add(numeroType); EOperation oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("+"); EParameter parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(numeroType); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("-"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(numeroType); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("*"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(numeroType); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("/"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(numeroType); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("-"); oper.setEType(numeroType); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("<"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(EcorePackage.Literals.EBOOLEAN); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("<="); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(EcorePackage.Literals.EBOOLEAN); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName(">"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(EcorePackage.Literals.EBOOLEAN); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName(">="); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("n"); parm.setEType(numeroType); oper.getEParameters().add(parm); oper.setEType(EcorePackage.Literals.EBOOLEAN); numeroType.getEOperations().add(oper); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("asLong"); oper.setEType(EcorePackage.Literals.ELONG); numeroType.getEOperations().add(oper); numeros = EcoreFactory.eINSTANCE.createEReference(); numeros.setName("numeros"); numeros.setEType(numeroType); numeros.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); numeros.setOrdered(true); thingType.getEStructuralFeatures().add(numeros); thing = factory.create(thingType); comparable = EcoreFactory.eINSTANCE.createEClass(); comparable.setName("Comparable"); comparable.setAbstract(true); pkg.getEClassifiers().add(comparable); oper = EcoreFactory.eINSTANCE.createEOperation(); oper.setName("compareTo"); parm = EcoreFactory.eINSTANCE.createEParameter(); parm.setName("c"); parm.setEType(comparable); oper.getEParameters().add(parm); oper.setEType(EcorePackage.Literals.EINT); comparable.getEOperations().add(oper); myDataType = EcoreFactory.eINSTANCE.createEDataType(); myDataType.setName("MyDataType"); myDataType.setInstanceClass(Thread.State.class); // enums are comparable pkg.getEClassifiers().add(myDataType); @SuppressWarnings("unchecked") EList<Numero> list = (EList<Numero>) thing.eGet(numeros); list.add(new Numero(6)); list.add(new Numero(2)); } private static class Value implements Comparable<Value> { private final String value; Value(String value) { this.value = value; } public int compareTo(Value arg0) { return value.compareTo((arg0).value); } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((value == null) ? 0 : value.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Value other = (Value) obj; if (value == null) { if (other.value != null) { return false; } } else if (!value.equals(other.value)) { return false; } return true; } } public static class Numero extends EObjectImpl { private long value; Numero() { super(); } Numero(long value) { this.value = value; } public Numero plus(Numero n) { return new Numero(value + n.value); } public Numero minus(Numero n) { return new Numero(value - n.value); } public Numero times(Numero n) { return new Numero(value * n.value); } public Numero divide(Numero n) { return new Numero(value / n.value); } public Numero minus() { return new Numero(-value); } public boolean lessThan(Numero n) { return value < n.value; } public boolean lessThanEqual(Numero n) { return value <= n.value; } public boolean greaterThan(Numero n) { return value > n.value; } public boolean greaterThanEqual(Numero n) { return value >= n.value; } public long asLong() { return value; } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + (int) (value & 0xFFFF); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Numero other = (Numero) obj; if (value != other.value) { return false; } return true; } @Override public String toString() { return "Numero(" + value + ")"; } } }