/******************************************************************************* * Copyright (c) 2005, 2015 IBM Corporation 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 * Zeligsoft - Bugs 243079, 244948, 244886, 245619 * E.D.Willink - Bug 191689, 254919, 296409, 298634 * Obeo - Bug 291310 *******************************************************************************/ package org.eclipse.ocl.tests; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; import org.eclipse.emf.common.EMFPlugin; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.ocl.Environment; import org.eclipse.ocl.EnvironmentFactory; import org.eclipse.ocl.OCL; import org.eclipse.ocl.OCLInput; import org.eclipse.ocl.ParserException; import org.eclipse.ocl.SemanticException; import org.eclipse.ocl.expressions.OCLExpression; import org.eclipse.ocl.expressions.Variable; import org.eclipse.ocl.helper.Choice; import org.eclipse.ocl.helper.ChoiceKind; import org.eclipse.ocl.helper.OCLHelper; import org.eclipse.ocl.internal.helper.PluginFinder; import org.eclipse.ocl.lpg.ProblemHandler; import org.eclipse.ocl.parser.OCLProblemHandler; import org.eclipse.ocl.types.OCLStandardLibrary; import org.eclipse.ocl.util.CollectionUtil; import org.eclipse.ocl.util.OCLUtil; import org.eclipse.ocl.utilities.Visitable; import org.eclipse.osgi.util.NLS; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Default test framework. * * @author Christian W. Damus (cdamus) */ @SuppressWarnings("nls") public abstract class GenericTestSuite<E extends EObject, PK extends E, T extends E, C extends T, CLS extends C, DT extends C, PT extends C, ET extends DT, O extends E, PM extends E, P extends E, PA extends P, PR extends P, EL, S, COA, SSA, CT> extends TestCase { // set this variable true when testing for memory leaks private static boolean DISPOSE_RESOURCE_SET = false; public static final class CheckedTestSuite extends TestSuite { public CheckedTestSuite(String name) { super(name); } public void createTestSuite(Class<? extends GenericTestSuite> testClass, String testName) { addTest(new TestSuite(testClass, testName)); } public void addTestSuite(CheckedTestSuite suite) { addTest(suite); } } protected static boolean noDebug = false; protected static ResourceSet resourceSet; private static ArrayList<Resource> standardResources; private static boolean initialized = false; public static <T> Collection<T> createBag(T... elements) { Collection<T> collection = CollectionUtil.createNewBag(); if (elements != null) { for (T element : elements) { collection.add(element); } } return collection; } public static <T> Set<T> createOrderedSet(T... elements) { Set<T> collection = CollectionUtil.createNewOrderedSet(); if (elements != null) { for (T element : elements) { collection.add(element); } } return collection; } public static <T> List<T> createSequence(T... elements) { List<T> collection = CollectionUtil.createNewSequence(); if (elements != null) { for (T element : elements) { collection.add(element); } } return collection; } public static <T> Set<T> createSet(T... elements) { Set<T> collection = CollectionUtil.createNewSet(); if (elements != null) { for (T element : elements) { collection.add(element); } } return collection; } public static void debugPrintln(String string) { if (!noDebug) { System.out.println(string); } } /** * @Deprecated Use EMFPlugin.IS_ECLIPSE_RUNNING */ @Deprecated public static boolean eclipseIsRunning() { return EMFPlugin.IS_ECLIPSE_RUNNING; } public static void initializeStandalone() { if (initialized) return; initialized = true; } protected TestReflection.Static<E, PK, T, C, CLS, DT, PT, ET, O, PM, P, PA, PR, EL, S, COA, SSA, CT> staticReflection; protected OCL<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> ocl; protected Environment<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> environment; protected TestReflection<E, PK, T, C, CLS, DT, PT, ET, O, PM, P, PA, PR, EL, S, COA, SSA, CT> reflection; protected OCLHelper<C, O, P, CT> helper; /** * Assert that an expression cannot be used as an invariant, because an exception is thrown * with a diagnostic of severity containing a message that is the result of messageTemplate * resolved by bindings. */ protected void assertBadInvariant(Class<?> exception, int severity, String expression, String messageTemplate, String... bindings) { String denormalized = denormalize(expression); try { helper.createInvariant(denormalized); fail("Should not have parsed \"" + denormalized + "\""); } catch (ParserException e) { assertEquals("Exception for \"" + denormalized + "\"", exception, e.getClass()); Diagnostic diagnostic = getDiagnostic(); assertNoException(diagnostic, ClassCastException.class); assertNoException(diagnostic, NullPointerException.class); assertEquals("Severity for \"" + denormalized + "\"", severity, diagnostic.getSeverity()); String expectedMessage = NLS.bind(messageTemplate, bindings); assertEquals("Message for \"" + denormalized + "\"", expectedMessage, diagnostic.getMessage()); } } /** * Assert that an expression cannot be used as a query, because an exception is thrown * with a diagnostic of severity containing a message that is the result of messageTemplate * resolved by bindings. */ protected void assertBadQuery(Class<?> exception, int severity, String expression, String messageTemplate, String... bindings) { String denormalized = denormalize(expression); try { helper.createQuery(denormalized); fail("Should not have parsed \"" + denormalized + "\""); } catch (ParserException e) { assertEquals("Exception for \"" + denormalized + "\"", exception, e.getClass()); Diagnostic diagnostic = getDiagnostic(); assertNoException(diagnostic, ClassCastException.class); assertNoException(diagnostic, NullPointerException.class); assertEquals("Severity for \"" + denormalized + "\"", severity, diagnostic.getSeverity()); String expectedMessage = NLS.bind(messageTemplate, bindings); assertEquals("Message for \"" + denormalized + "\"", expectedMessage, diagnostic.getMessage()); } } /** * Asserts that the specified choice is to be found in the collection of * <code>choices</code>. * * @param choices a collection of {@link Choice}s * @param kind the kind of choice to find * @param name the name of the choice to find */ protected void assertChoice(Collection<Choice> choices, ChoiceKind kind, String name) { assertNotNull("Choice not found: " + name + ", " + kind, //$NON-NLS-2$ findChoice(choices, kind, name)); } protected void assertInvalid(Object value) { assertTrue("Expected invalid", ocl.isInvalid(value)); } /** * Assert that an expression can be parsed as an invariant for a context and return the invariant. */ protected OCLExpression<C> assertInvariant(C context, String expression) { helper.setContext(context); String denormalized = denormalize(expression); try { OCLExpression<C> result = getBodyExpression(helper.createInvariant(denormalized)); return result; } catch (Exception e) { fail("Parse failed: " + e.getLocalizedMessage()); return null; } } /** * Assert that an expression evaluated as an invariant for a context returns false. */ protected Object assertInvariantFalse(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = check(helper, context, denormalized); assertEquals(denormalized, false, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that an expression evaluated as an invariant for a context returns true. */ protected Object assertInvariantTrue(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = check(helper, context, denormalized); assertEquals(denormalized, true, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Asserts that a exception of the specified kind is not signalled by * the a given diagnostic or (recursively) its children. * * @param diagnostic a diagnostic * @param excType an exception that must not be indicated by the diagnostic * * @since 1.2 */ protected void assertNoException(Diagnostic diagnostic, java.lang.Class<? extends Throwable> excType) { if (excType.isInstance(diagnostic.getException())) { fail("Diagnostic signals a(n) " + excType.getSimpleName()); } for (Diagnostic nested : diagnostic.getChildren()) { assertNoException(nested, excType); } } /** * Asserts that the specified choice is <em>not</em> to be found in the * collection of <code>choices</code>. * * @param choices a collection of {@link Choice}s * @param kind the kind of choice not to find * @param name the name of the choice not to find */ protected void assertNotChoice(Collection<Choice> choices, ChoiceKind kind, String name) { assertNull("Choice found: " + name + ", " + kind, //$NON-NLS-2$ findChoice(choices, kind, name)); } /** * Assert that an expression has a parser error with the exception message corresponding * to the messageTemplate and bindings. */ protected void assertParserError(String expression, String messageTemplate, Object... bindings) { String denormalized = denormalize(expression); try { helper.createQuery(denormalized); fail("Should not have parsed \"" + denormalized + "\""); } catch (ParserException e) { assertEquals("Exception for \"" + denormalized + "\"", ParserException.class, e.getClass()); String expectedMessage = NLS.bind(messageTemplate, bindings); assertEquals("Message for \"" + denormalized + "\"", expectedMessage, e.getMessage()); } } /** * Assert that an expression can be parsed as a query for a context and return the query. */ protected OCLExpression<C> assertQuery(C context, String expression) { helper.setContext(context); String denormalized = denormalize(expression); try { OCLExpression<C> result = helper.createQuery(denormalized); return result; } catch (Exception e) { // e.printStackTrace(); fail("Parse failed: " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is equal to expected. * @return the evaluation result */ protected Object assertQueryEquals(Object context, Object expected, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertEquals(denormalized, expected, value); if (expected instanceof LinkedHashSet) { assertTrue(denormalized, value instanceof LinkedHashSet); Iterator<?> es = ((LinkedHashSet<?>)expected).iterator(); Iterator<?> vs = ((LinkedHashSet<?>)value).iterator(); while (es.hasNext()) { Object e = es.next(); Object v = vs.next(); assertEquals(denormalized, e, v); } } return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is the same as expected. */ protected Object assertQueryEvaluate(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is false. * @return the evaluation result */ protected Object assertQueryFalse(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertEquals(denormalized, false, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is invalid. * @return the evaluation result */ protected Object assertQueryInvalid(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertInvalid(value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is not null. * @return the evaluation result */ protected Object assertQueryNotNull(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertNotNull(denormalized, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is null. * @return the evaluation result */ protected Object assertQueryNull(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertEquals(denormalized, null, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is not the same as expected. * @return the evaluation result */ protected Object assertQueryNotSame(Object context, Object expected, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertNotSame(denormalized, expected, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is the same as expected. * @return the evaluation result */ protected Object assertQuerySame(Object context, Object expected, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertSame(denormalized, expected, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that the result of evaluating an expression as a query is true. * @return the evaluation result */ protected Object assertQueryTrue(Object context, String expression) { String denormalized = denormalize(expression); try { Object value = evaluate(helper, context, denormalized); assertEquals(denormalized, true, value); return value; } catch (ParserException e) { fail("Failed to parse or evaluate \"" + denormalized + "\": " + e.getLocalizedMessage()); return null; } } /** * Assert that an expression cannot be used as a query, because semantic exception * error is thrown containing a message that is the result of messageTemplate * resolved by bindings. */ protected void assertSemanticError(String expression, String messageTemplate, String... bindings) { assertBadQuery(SemanticException.class, Diagnostic.ERROR, expression, messageTemplate, bindings); } /** * Asserts that the <code>toString</code> representation of an AST node as * generated by the toString visitor does not throw a run-time exception * and is not <code>null</code>. * * @param node a visitable AST node */ protected void assertValidToString(Visitable node) { try { String toString = node.toString(); assertNotNull("ToStringVisitorImpl returned null", toString); } catch (RuntimeException e) { e.printStackTrace(); fail("ToStringVisitorImpl threw an exception: " + e.getLocalizedMessage()); } } protected boolean check(String contextFreeExpression) { boolean result = false; try { String document = denormalize("package %uml context %String" + " inv: " + contextFreeExpression + " endpackage"); OCLExpression<C> expr = parse(document); result = check(expr, ""); } catch (Exception e) { fail("Check failed: " + e.getLocalizedMessage()); } return result; } protected boolean check(OCLHelper<C, O, P, CT> aHelper, Object context, String expression) throws ParserException { CT constraint = aHelper.createInvariant(expression); return ocl.check(context, constraint); } protected boolean check(OCLExpression<C> expr, Object self) { boolean result = false; try { result = ocl.check(self, expr); } catch (RuntimeException e) { fail("Check failed: " + e.getLocalizedMessage()); } return result; } /** * This can be called by subclasses to provide a meaningful error message * when the tests are run with an encoding distinct from UTF-8. */ protected void checkForUTF8Encoding() { String testCharacter = "ยด"; int length = testCharacter.length(); if ((length != 1) || (testCharacter.charAt(0) != 0xB4)) { StringBuilder s = new StringBuilder(); s.append("The Resource text file encoding should be set to UTF-8: test character was"); for (int i = 0; i < length; i++){ s.append(" "); s.append(Integer.toHexString(testCharacter.charAt(i))); } s.append(" rather than B4"); fail(s.toString()); } } protected OCLExpression<C> createBodyCondition(O context, String text) { OCLHelper<C, O, P, CT> helper = ocl.createOCLHelper(); helper.setOperationContext(reflection.getOwner(context), context); OCLExpression<C> result = null; try { result = getBodyExpression(helper.createBodyCondition(text)); } catch (Exception e) { e.printStackTrace(); fail("Parse failed: " + e.getLocalizedMessage()); } return result; } /** * Return an isOrdered,isUnique collection containing args. */ protected<Z> Collection<Z> createCollection(boolean isOrdered, boolean isUnique, Z... args) { if (isOrdered) return isUnique ? createOrderedSet(args) : createSequence(args); else return isUnique ? createSet(args) : createBag(args); } protected void createDocument(String text) { try { ocl .parse(new OCLInput( text)); } catch (Exception e) { fail("Failed to parse: " + e.getLocalizedMessage()); } } protected OCLHelper<C, O, P, CT> createHelper() { return ocl.createOCLHelper(); } protected OCLExpression<C> createInvariant(C context, String expression) { return assertInvariant(context, expression); } protected OCL<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> createOCL() { return staticReflection.createOCL(resourceSet); } protected OCLExpression<C> createPostcondition(O context, String text) { OCLHelper<C, O, P, CT> helper = ocl.createOCLHelper(); helper.setOperationContext(reflection.getOwner(context), context); OCLExpression<C> result = null; try { result = getBodyExpression(helper.createPostcondition(text)); } catch (Exception e) { e.printStackTrace(); fail("Parse failed: " + e.getLocalizedMessage()); } return result; } protected OCLExpression<C> createPrecondition(O context, String text) { OCLHelper<C, O, P, CT> helper = ocl.createOCLHelper(); helper.setOperationContext(reflection.getOwner(context), context); OCLExpression<C> result = null; try { result = getBodyExpression(helper.createPrecondition(text)); } catch (Exception e) { e.printStackTrace(); fail("Parse failed: " + e.getLocalizedMessage()); } return result; } protected OCLExpression<C> createQuery(CLS context, String expression) { return assertQuery(context, expression); } protected OCLExpression<C> createQuery( EnvironmentFactory<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> envFactory, C context, String text) { OCL<PK, C, O, P, EL, PM, S, COA, SSA, CT, CLS, E> localOcl = OCL.newInstance(envFactory); OCLHelper<C, O, P, CT> helper = localOcl.createOCLHelper(); helper.setContext(context); OCLExpression<C> result = null; try { result = helper.createQuery(text); } catch (Exception e) { e.printStackTrace(); fail("Parse failed: " + e.getLocalizedMessage()); } return result; } protected void createVariableInEnvironment(String name, C type) { Variable<C, PM> var = environment.getOCLFactory().createVariable(); var.setName(name); var.setType(type); environment.addElement(var.getName(), var, true); } /** * Replace every %xxx occurrence on expression by the binding-specific value of * denormalization of xxx if defined or xxx otherwise. */ public String denormalize(String expression) { StringBuilder s = new StringBuilder(); int iMax = expression.length(); for (int i = 0; i < iMax; i++) { char c = expression.charAt(i); if (c == '%') { int iStart = ++i; for (; i < iMax; i++){ c = expression.charAt(i); if (!Character.isLetterOrDigit(c)) { break; } } String key = expression.substring(iStart, i); String mapped = reflection.denormalize(key); s.append(mapped != null ? mapped : key); } if (i < iMax) s.append(c); } return s.toString(); } protected void disposeResourceSet() { for (Resource res : resourceSet.getResources()) { res.unload(); res.eAdapters().clear(); } resourceSet.getResources().clear(); resourceSet.eAdapters().clear(); resourceSet = null; standardResources = null; } protected Object evaluate(String contextFreeExpression) { Object result = null; try { String document = denormalize("package %uml context %String" + " inv: " + contextFreeExpression +" endpackage"); OCLExpression<C> expr = parse(document); result = evaluate(expr, ""); } catch (Exception e) { fail("Evaluation failed: " + e.getLocalizedMessage()); } return result; } protected Object evaluate(OCLHelper<C, O, P, CT> aHelper, Object context, String expression) throws ParserException { OCLExpression<C> query = aHelper.createQuery(expression); return ocl.evaluate(context, query); } protected Object evaluate(OCLExpression<C> expr) { Object result = null; try { result = ocl.evaluate(null, expr); } catch (RuntimeException e) { fail("Evaluation failed: " + e.getLocalizedMessage()); } return result; } protected Object evaluate(OCLExpression<C> expr, Object self) { Object result = null; try { result = ocl.evaluate(self, expr); } catch (RuntimeException e) { fail("Evaluation failed: " + e.getLocalizedMessage()); } return result; } protected Choice findChoice(Collection<Choice> choices, ChoiceKind kind, String name) { Choice result = null; for (Choice c : choices) { if (c.getKind() == kind && name.equals(c.getName())) { result = c; break; } } return result; } protected OCLExpression<C> getBodyExpression(CT constraint) { return reflection.getBodyExpression(constraint); } /** * Obtains the diagnostic describing the problem in the last failed parse, * asserting that it is not <code>null</code>. * * @return the diagnostic */ protected Diagnostic getDiagnostic() { OCLProblemHandler handler = (OCLProblemHandler) OCLUtil.getAdapter( ocl.getEnvironment(), ProblemHandler.class); Diagnostic result = handler.getDiagnostic(); if (result == null) { result = helper.getProblems(); } assertNotNull("No diagnostic", result); return result; } protected PT getEcoreBigDecimal() { return reflection.getEcoreBigDecimal(); } protected PT getEcoreBigInteger() { return reflection.getEcoreBigInteger(); } protected PT getEcoreLong() { return reflection.getEcoreLong(); } protected Object getInvalid() { return getOCLStandardLibrary().getInvalid(); } protected C getMetaclass(String name) { return reflection.getMetaclass(name); } protected C getMetametaclass(String name) { return reflection.getMetametaclass(name); } protected OCLStandardLibrary<C> getOCLStandardLibrary() { return ocl.getEnvironment().getOCLStandardLibrary(); } abstract protected TestReflection.Static<E, PK, T, C, CLS, DT, PT, ET, O, PM, P, PA, PR, EL, S, COA, SSA, CT> getStaticReflection(); public URI getTestModelURI(String localFileName) { String testPlugInId = staticReflection.getTestPlugInId(); try { java.lang.Class<?> platformClass = java.lang.Class.forName("org.eclipse.core.runtime.Platform"); Method getBundle = platformClass.getDeclaredMethod("getBundle", new java.lang.Class[] {String.class}); Object bundle = getBundle.invoke(null, new Object[] {testPlugInId}); if (bundle != null) { Method getEntry = bundle.getClass().getMethod("getEntry", new java.lang.Class[] {String.class}); URL url = (URL) getEntry.invoke(bundle, new Object[] {localFileName}); return URI.createURI(url.toString()); } } catch (Throwable e) { // not running in Eclipse } PluginFinder pluginFinder = new PluginFinder(testPlugInId); pluginFinder.resolve(); String urlString = pluginFinder.get(testPlugInId); if (urlString == null) { TestCase.fail("'" + testPlugInId + "' property not defined; use the launch configuration to define it"); //$NON-NLS-1$ //$NON-NLS-2$ } return URI.createFileURI(urlString + "/" + localFileName); } protected PT getUMLBoolean() { return reflection.getUMLBoolean(); } protected PT getUMLInteger() { return reflection.getUMLInteger(); } protected PK getUMLMetamodel() { return reflection.getUMLMetamodel(); } // protected PK getUMLModelMetamodel() { // return reflection.getUMLModelMetamodel(); // } protected PT getUMLString() { return reflection.getUMLString(); } protected PT getUMLUnlimitedNatural() { return reflection.getUMLUnlimitedNatural(); } protected void initializeResourceSet() { resourceSet = staticReflection.createResourceSet(); standardResources = new ArrayList<Resource>(resourceSet.getResources()); } /** * Parses the specified <code>text</code>. * * @param text the OCL text * @return the OCL expression */ protected OCLExpression<C> parse(String text) { OCLExpression<C> result = parseUnvalidated(text); validate(result); assertValidToString(result); return result; } /** * Parses the specified <code>text</code> as an OCL constraint. * * @param text the OCL text * @return the OCL constraint expression */ protected OCLExpression<C> parseConstraint(String text) { OCLExpression<C> result = parseConstraintUnvalidated(text); validate(result); assertValidToString(result); return result; } /** * Parses the specified <code>text</code> as an OCL constraint, without * validating it. * * @param text the OCL text * @return the OCL constraint expression, unvalidated */ protected OCLExpression<C> parseConstraintUnvalidated(String text) { List<CT> constraints; CT constraint = null; try { constraints = ocl.parse(new OCLInput(text)); constraint = constraints.get(0); } catch (ParserException e) { fail("Parse failed: " + e.getLocalizedMessage()); } catch (IllegalArgumentException e) { fail("Parse failed (illegal argument): " + e.getLocalizedMessage()); } OCLExpression<C> result = null; result = getBodyExpression(constraint); assertNotNull(result); assertValidToString(result); return result; } /** * Parses the specified <code>text</code> as a def expression. This differs * from the {@link #parse} method in not separating the expression from its * constraint, which is critically important to the structure of the defined * feature. * * @param env the environment in which the operation or property is to be defined * @param text the OCL text * @return the OCL def expression */ protected OCLExpression<C> parseDef(String text) { List<CT> constraints ; CT constraint = null; try { constraints = ocl.parse(new OCLInput(text)); constraint = constraints.get(0); } catch (ParserException e) { fail("Parse failed: " + e.getLocalizedMessage()); } catch (IllegalArgumentException e) { fail("Parse failed (illegal argument): " + e.getLocalizedMessage()); } OCLExpression<C> result = null; result = getBodyExpression(constraint); validate(result); assertNotNull(result); assertValidToString(result); return result; } /** * Parses the specified <code>text</code> without validating it. * * @param text the OCL text * * @return the OCL expression, unvalidated */ protected OCLExpression<C> parseUnvalidated(String text) { OCLExpression<C> result = parseConstraintUnvalidated(text); // forget the constraint because it interferes with validation EcoreUtil.remove(result); assertValidToString(result); return result; } /** * Create a Resource to register a binding-dependent pkg for access with a given nsPrefix and nsUri. */ protected PK registerPackage(PK pkg, String nsPrefix, String nsUri) { reflection.setNsPrefix(pkg, nsPrefix); reflection.setNsURI(pkg, nsUri); Resource resource = new ResourceImpl(URI.createURI(nsUri)); resource.getContents().add(pkg); resourceSet.getResources().add(resource); // FIXME UML needs this resourceSet.getPackageRegistry().put(nsUri, pkg); // whereas Ecore needs this return pkg; } @Override protected void setUp() { staticReflection = getStaticReflection(); if ((resourceSet != null) && DISPOSE_RESOURCE_SET) { disposeResourceSet(); } if (!initialized) { String property = System.getProperty(staticReflection.getTestPlugInId() + ".nodebug"); noDebug = !"false".equals(property); if (!EMFPlugin.IS_ECLIPSE_RUNNING) { initializeStandalone(); } } if (resourceSet == null) { initializeResourceSet(); } debugPrintln("==> Start " + getName()); ocl = createOCL(); environment = ocl.getEnvironment(); reflection = staticReflection.createReflection(environment); String repairs = System.getProperty(staticReflection.getTestPlugInId() + ".repairs"); if (repairs != null) ocl.setParserRepairCount(Integer.parseInt(repairs)); // ocl.setParseTracingEnabled(true); // ocl.setEvaluationTracingEnabled(true); helper = createHelper(); } @Override protected void tearDown() throws Exception { // // Unload any resources that a test may have loaded. // for (ListIterator<Resource> i = resourceSet.getResources().listIterator(); i.hasNext(); ) { Resource res = i.next(); if (!standardResources.contains(res)) { i.remove(); res.unload(); res.eAdapters().clear(); } } // // Null out any references that a test may have left behind, so that unwanted // objects are not locked into memory. // for (java.lang.Class<?> aClass = getClass(); GenericTestSuite.class.isAssignableFrom(aClass); aClass = aClass.getSuperclass()) { for (Field field : aClass.getDeclaredFields()) { int modifiers = field.getModifiers(); if (Modifier.isFinal(modifiers)) { } else if (!Modifier.isStatic(modifiers)) { java.lang.Class<?> fieldType = field.getType(); if (Object.class.isAssignableFrom(fieldType)) { String fieldName = field.getName(); try { String tearDownName = "tearDown_" + fieldName; Method method = aClass.getDeclaredMethod(tearDownName); try { tearDownUsing(method); } catch (Exception e) { // tearDown_xxx must be public fail("Failed to invoke " + getClass().getSimpleName() + "." + tearDownName + " : " + e); //$NON-NLS-2$//$NON-NLS-3$ } } catch (NoSuchMethodException e) { try { tearDownField(field); } catch (Exception e1) { // xxx without a tearDown_xxx must be public to ensure that leakage can be stopped fail("Failed to set " + getClass().getSimpleName() + "." + fieldName + " to null : " + e1); //$NON-NLS-2$ //$NON-NLS-3$ } } } } else { tearDownStatic(aClass, field); } } } debugPrintln("==> Finish " + getName()); } protected void tearDownField(Field field) throws IllegalAccessException { field.set(this, null); } protected void tearDownStatic(java.lang.Class<?> aClass, Field field) { if (aClass != GenericTestSuite.class) { // Tests may not have statics since they are prone to memory leakage fail("static test variable:" + field); } } protected void tearDownUsing(Method method) throws IllegalAccessException, InvocationTargetException { method.invoke(this); } protected void tearDown_ocl() { ocl.dispose(); ocl = null; } /** * Validates an OCL expression, asserting that it is valid. * * @param expr the OCL expression to validate * @param env an environment to use for validation */ protected void validate(CT constraint) { try { ocl.validate(constraint); } catch (SemanticException e) { fail("Validation failed: " + e.getLocalizedMessage()); } } /** * Validates an OCL expression, asserting that it is valid. * * @param expr the OCL expression to validate * @param env an environment to use for validation */ protected void validate(OCLExpression<C> expr) { try { EObject eContainer = expr.eContainer(); if ((eContainer != null) && reflection.getConstraintClass().isAssignableFrom(eContainer.eContainer().getClass())) { // start validation from the constraint, for good measure @SuppressWarnings("unchecked") CT eContainerContainer = (CT) eContainer.eContainer(); validate(eContainerContainer); } else { ocl.validate(expr); } } catch (SemanticException e) { fail("Validation failed: " + e.getLocalizedMessage()); } } }