errors = Lists.newArrayList();
- int run = 0;
- int succeeded = 0;
- while (run < testRuns || (testRuns == 1 && succeeded == 0 && run < thisTestRetries + 1)) {
- try {
- run++;
- methodBlock(method).evaluate();
- succeeded++;
- } catch (AssumptionViolatedException e) {
- throw e;
- } catch (AssertionError exception) {
- failures.add(exception);
- problems.addProblem(exception);
- // CHECKSTYLE:CHECK-OFF IllegalCatch // we want to catch all possible errors
- } catch (Throwable throwable) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- errors.add(throwable);
- problems.addProblem(throwable);
- }
- }
- final String testCase = getTestClass().getJavaClass().getSimpleName() + '.' + method.getName();
- if (run > 1) {
- logRepeatedTestResult(testCase, run, succeeded, failures.size(), errors.size());
- }
- if (succeeded == 0) {
- problems.assertEmpty();
- }
- if (problems.hasProblems()) {
- if (unstableFail) {
- problems.assertEmpty();
- } else {
- final StringWriter stringWriter = new StringWriter();
- problems.printStackTrace(new PrintWriter(stringWriter));
- LOGGER.info(stringWriter.toString());
- }
- }
- } catch (AssumptionViolatedException e) { // NOPMD ExceptionAsFlowControl
- eachNotifier.addFailedAssumption(e);
- // CHECKSTYLE:CHECK-OFF IllegalCatch // we want to catch all possible errors
- } catch (Throwable e) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- eachNotifier.addFailure(e);
- } finally {
- eachNotifier.fireTestFinished();
- }
- }
-
- /**
- * Logs the repeated test result.
- *
- * @param testCase
- * the test case, must not be {@code null}
- * @param runs
- * the number of runs
- * @param succeeded
- * the number of succeeded runs
- * @param failures
- * the number of failed runs
- * @param errors
- * the number of errored runs
- */
- public void logRepeatedTestResult(final String testCase, final int runs, final int succeeded, final int failures, final int errors) {
- final StringBuilder testResult = new StringBuilder(testCase).append(" Repeated Test Result: "); //$NON-NLS-1$
- if (succeeded == runs) {
- testResult.append("SUCCESS"); //$NON-NLS-1$
- } else if (succeeded == 0) {
- testResult.append("FAILURE"); //$NON-NLS-1$
- } else {
- testResult.append("UNSTABLE"); //$NON-NLS-1$
- }
- testResult.append(" (").append(succeeded).append(" of ").append(runs).append(" succeeded"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- if (failures > 0) {
- testResult.append(", ").append(failures).append(" failed"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (errors > 0) {
- testResult.append(", ").append(errors).append(" errored"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- testResult.append(')');
- LOGGER.info(testResult.toString());
- }
-
- /**
- * Creates a notifier for each test.
- *
- * @param method
- * the {@link FrameworkMethod}, must not be {@code null}
- * @param notifier
- * the {@link RunNotifier}, must not be {@code null}
- * @return an instance of {@link EachTestNotifier}, never {@code null}
- */
- private EachTestNotifier createNotifier(final FrameworkMethod method, final RunNotifier notifier) {
- return new EachTestNotifier(notifier, describeChild(method));
- }
-
- /**
- * Adds any @BeforeAll methods to be run before the normal @Before annotated methods for the first test method only.
- *
- * {@inheritDoc}
- */
- @Override
- protected Statement withBefores(final FrameworkMethod method, final Object target, final Statement stmt) {
- ensureInitialized();
- Statement statement = super.withBefores(method, target, stmt); // NOPMD.CloseResource
- if (method.equals(expectedMethods.get(0))) {
- // reverse BeforeAll method order to get a 'runs top to bottom' order
- final List befores = Lists.reverse(getTestClass().getAnnotatedMethods(BeforeAll.class));
- statement = befores.isEmpty() ? statement : new RunBefores(statement, befores, target);
- }
- return statement;
- }
-
- /**
- * Adds any @AfterAll methods to be run after the normal @After annotated methods for the last test method only.
- *
- * {@inheritDoc}
- */
- @Override
- protected Statement withAfters(final FrameworkMethod method, final Object target, final Statement stmt) {
- ensureInitialized();
- Statement statement = super.withAfters(method, target, stmt); // NOPMD.CloseResource
- if (method.equals(Iterables.getLast(expectedMethods))) {
- final List afters = getTestClass().getAnnotatedMethods(AfterAll.class);
- statement = afters.isEmpty() ? statement : new RunAfters(statement, afters, target);
- }
- return statement;
- }
-
- @Override
- protected List computeTestMethods() {
- final Collection result = Sets.newHashSet();
- for (final Class extends Annotation> annotationClass : TEST_ANNOTATIONS) {
- result.addAll(getTestClass().getAnnotatedMethods(annotationClass));
- }
- return Lists.newArrayList(result);
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugClassFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugClassFilter.java
deleted file mode 100644
index 86bcb8505..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugClassFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.Debug;
-
-
-/**
- * A test class filter that makes sure only test classes annotated with @{@link Debug} are run.
- */
-public class DebugClassFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestClass(description);
- return description.getAnnotation(Debug.class) != null;
- }
-
- @Override
- public String describe() {
- return DebugClassFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugMethodFilter.java
deleted file mode 100644
index 5214a176e..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DebugMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.Debug;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link Debug} are run.
- */
-public class DebugMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(Debug.class) != null;
- }
-
- @Override
- public String describe() {
- return DebugMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DiscerningSuite.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DiscerningSuite.java
deleted file mode 100644
index ec91e7b7d..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DiscerningSuite.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import java.util.List;
-
-import org.junit.runner.Description;
-import org.junit.runner.Runner;
-import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.manipulation.Sorter;
-import org.junit.runners.Suite;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.RunnerBuilder;
-
-
-/**
- * Discerns tests using test filters.
- */
-public class DiscerningSuite extends Suite {
-
- private boolean descriptionOutdated = true;
- private Description description;
- private Filter testFilter;
-
- /**
- * Creates a new instance of {@link DiscerningSuite}.
- *
- * @param klass
- * root of the suite
- * @param runners
- * for each class in the suite, a {@link Runner}
- * @throws InitializationError
- * if an error occurred during the initialization
- */
- public DiscerningSuite(final Class> klass, final List runners) throws InitializationError {
- super(klass, runners);
- initialize();
- }
-
- /**
- * Creates a new instance of {@link DiscerningSwtBotNonSwtBotSuite}.
- *
- * @param klass
- * the root of the suite
- * @param suiteClasses
- * the classes in the suite
- * @throws InitializationError
- * if an error occurred during the initialization
- */
- public DiscerningSuite(final Class> klass, final Class>... suiteClasses) throws InitializationError {
- super(klass, suiteClasses);
- initialize();
- }
-
- /**
- * Creates a new instance of {@link DiscerningSwtBotNonSwtBotSuite}.
- *
- * @param klass
- * the root class
- * @param builder
- * builds runners for classes in the suite
- * @throws InitializationError
- * if an error occurred during the initialization
- */
- public DiscerningSuite(final Class> klass, final RunnerBuilder builder) throws InitializationError {
- super(klass, builder);
- initialize();
- }
-
- /**
- * Creates a new instance of {@link DiscerningSwtBotNonSwtBotSuite}.
- *
- * @param builder
- * builds runners for classes in the suite
- * @param klass
- * the root of the suite
- * @param suiteClasses
- * the classes in the suite
- * @throws InitializationError
- * if an error occurred during the initialization
- */
- public DiscerningSuite(final RunnerBuilder builder, final Class> klass, final Class>... suiteClasses) throws InitializationError {
- super(builder, klass, suiteClasses);
- initialize();
- }
-
- /**
- * Creates a new instance of {@link DiscerningSwtBotNonSwtBotSuite}.
- *
- * @param builder
- * builds runners for classes in the suite
- * @param classes
- * the classes in the suite
- * @throws InitializationError
- * if an error occurred during the initialization
- */
- public DiscerningSuite(final RunnerBuilder builder, final Class>... classes) throws InitializationError {
- super(builder, classes);
- initialize();
- }
-
- /**
- * Initializes the {@link DiscerningSuite}.
- */
- private void initialize() {
- SorterUtil.getInstance().initializeSorter(this);
- FilterRegistry.initializeFilter(this);
- }
-
- @Override
- public Description getDescription() {
- if (descriptionOutdated) {
- description = super.getDescription();
- descriptionOutdated = false;
- }
- return description;
- }
-
- @Override
- public void sort(final Sorter sorter) {
- super.sort(sorter);
- descriptionOutdated = true;
- }
-
- @Override
- public void filter(final Filter filter) throws NoTestsRemainException {
- if (testFilter == null || !testFilter.equals(filter)) {
- testFilter = filter;
- super.filter(filter);
- descriptionOutdated = true;
- }
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DynamicSuite.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DynamicSuite.java
deleted file mode 100644
index 540f7fcd8..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/DynamicSuite.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.runner.Runner;
-import org.junit.runners.Suite;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.RunnerBuilder;
-
-
-/**
- * Using {@link DynamicSuite} as a runner allows you to manually build a suite containing
- * tests from many classes, as with {@link Suite}. While {@link Suite} has static references
- * to the test classes, {@link DynamicSuite} resolves the class names at runtime.
- */
-public class DynamicSuite extends Suite {
-
- /**
- * Annotation allows to specify names of suite classes as separate strings.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target({java.lang.annotation.ElementType.TYPE})
- @Inherited
- public static @interface SuiteClasses {
- String[] value();
- }
-
- public DynamicSuite(final Class> clazz, final RunnerBuilder builder) throws InitializationError {
- this(clazz, builder.runners(clazz, getSuiteClasses(clazz)));
- }
-
- public DynamicSuite(final RunnerBuilder builder, final Class>... classes) throws InitializationError {
- super(builder, classes);
- }
-
- public DynamicSuite(final Class> clazz, final Class>... suiteClasses) throws InitializationError {
- super(clazz, suiteClasses);
- }
-
- public DynamicSuite(final Class> clazz, final List runners) throws InitializationError {
- super(clazz, runners);
- }
-
- public DynamicSuite(final RunnerBuilder builder, final Class> clazz, final Class>... suiteClasses) throws InitializationError {
- super(builder, clazz, suiteClasses);
- }
-
- /**
- * Collect suite classes from annotation.
- *
- * @param clazz
- * main suite to get suite classes annotation from
- * @return list of suite classes
- * @throws InitializationError
- * thrown when annotation is missing or class can not be found
- */
- @SuppressWarnings("nls")
- private static Class>[] getSuiteClasses(final Class> clazz) throws InitializationError {
- // get annotation
- SuiteClasses annotation = clazz.getAnnotation(SuiteClasses.class);
- if (annotation == null) {
- throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", clazz.getName()));
- }
-
- // get classes from class names
- List> suiteClasses = new ArrayList>();
- for (String className : annotation.value()) {
- try {
- suiteClasses.add(Class.forName(className, true, clazz.getClassLoader())); // use class loader of suite class in order to resolve specified classes
- } catch (ClassNotFoundException e) {
- throw new InitializationError(String.format("class '%s' not found", className)); // NOPMD: InitializationError has no parameter for Exception
- }
- }
-
- // return suite classes
- return suiteClasses.toArray(new Class>[suiteClasses.size()]);
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FilterRegistry.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FilterRegistry.java
deleted file mode 100644
index d0b4ae70a..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FilterRegistry.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.eclipse.osgi.util.NLS;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runners.ParentRunner;
-import org.junit.runners.Suite;
-
-import com.google.common.collect.Lists;
-
-
-/**
- * A delegating filter that allows registration of suite, test class and test method filters.
- *
- * Note: Filters can be registered using the system properties {@value #PROPERTY_SUITE_FILTERS}, {@value #PROPERTY_CLASS_FILTERS} and
- * {@value #PROPERTY_METHOD_FILTERS}.
- *
- */
-@SuppressWarnings("nls")
-public final class FilterRegistry extends Filter {
- private static final String NEGATOR = "!";
- private static final String FILTER_SEPARATOR = ",";
- private static final String EMPTY_STRING = "";
- /** The system property to register test suite filters. */
- private static final String PROPERTY_SUITE_FILTERS = "com.avaloq.test.suitefilters";
- /** The system property to register test class filters. */
- private static final String PROPERTY_CLASS_FILTERS = "com.avaloq.test.classfilters";
- /** The system property to register test method filters. */
- private static final String PROPERTY_METHOD_FILTERS = "com.avaloq.test.methodfilters";
- private static final String MESSAGE_INVALID_FILTER = "Invalid filter ''{0}'' registered in property ''{1}''.";
- /** The package prefix for default filters, including the last segment separator. */
- private static final String PACKAGE_PREFIX = FilterRegistry.class.getCanonicalName().substring(0, FilterRegistry.class.getCanonicalName().length()
- - FilterRegistry.class.getSimpleName().length());
- private static final FilterRegistry INSTANCE = new FilterRegistry();
- private static final Logger LOGGER = LogManager.getLogger(FilterRegistry.class);
- /** The list of test suite filters. */
- private final List suiteFilters;
- /** The list of test class filters. */
- private final List classFilters;
- /** The list of test method filters. */
- private final List methodFilters;
-
- /**
- * Initializes the test filter.
- *
- * @param parentRunner
- * the {@link ParentRunner} to initialize, must not be {@code null}
- */
- public static void initializeFilter(final ParentRunner> parentRunner) {
- try {
- parentRunner.filter(INSTANCE);
- } catch (NoTestsRemainException e) {
- // we ignore the case where no children are left
- }
- }
-
- /**
- * Creates a new instance of {@link FilterRegistry}.
- *
- * Note: This filter is initialized using the values of the system properties {@value #PROPERTY_SUITE_FILTERS}, {@value #PROPERTY_CLASS_FILTERS} and
- * {@value #PROPERTY_METHOD_FILTERS}.
- *
- *
- * The values are separated by {@value #FILTER_SEPARATOR}. A filter can be negated by prepending a {@value #NEGATOR}.
- *
- */
- private FilterRegistry() {
- suiteFilters = parseFilters(PROPERTY_SUITE_FILTERS);
- classFilters = parseFilters(PROPERTY_CLASS_FILTERS);
- methodFilters = parseFilters(PROPERTY_METHOD_FILTERS);
- }
-
- /**
- * Parses and instantiates filters registered with the given system property.
- *
- * @param property
- * the name of the system property to parse, must not be {@code null} or empty
- * @return the list of filters, never {@code null}
- */
- private List parseFilters(final String property) {
- final List result = Lists.newArrayList();
- final String filtersProperty = System.getProperty(property, EMPTY_STRING);
- if (filtersProperty.length() == 0) {
- return result;
- }
- final String[] filterNames = filtersProperty.split(FILTER_SEPARATOR);
- for (final String splitSegment : filterNames) {
- String splitSegmentTrimmed = splitSegment.trim();
- if (splitSegmentTrimmed.isEmpty()) {
- continue;
- }
-
- // Handle negation
- boolean negated = splitSegmentTrimmed.startsWith(NEGATOR);
- String filterClassOrLabel = splitSegmentTrimmed;
- if (negated) {
- filterClassOrLabel = splitSegmentTrimmed.substring(1);
- }
-
- // Try to find a Filter subclass with this name
- String qualifiedClassName = filterClassOrLabel;
- if (!filterClassOrLabel.contains(".")) {
- qualifiedClassName = PACKAGE_PREFIX + filterClassOrLabel;
- }
- try {
- Filter filter = null;
- try {
- Class> filterClass = Class.forName(qualifiedClassName);
- if (Filter.class.isAssignableFrom(filterClass)) {
- final Object filterInstance = filterClass.getConstructor().newInstance();
- filter = (Filter) filterInstance;
- }
- } catch (ClassNotFoundException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
- // If no class exists with this name, interpret the String as a label and create a label filter for it
- filter = new TestLabelFilter(filterClassOrLabel);
- }
-
- if (filter != null) {
- if (negated) {
- result.add(new NegatedFilter(filter));
- } else {
- result.add(filter);
- }
- }
- } catch (InstantiationException e) {
- LOGGER.error(NLS.bind(MESSAGE_INVALID_FILTER, qualifiedClassName, property), e);
- } catch (IllegalAccessException e) {
- LOGGER.error(NLS.bind(MESSAGE_INVALID_FILTER, qualifiedClassName, property), e);
- }
- }
- return result;
- }
-
- /**
- * Determines if the given {@link Description} is describing a {@link Suite}.
- *
- * @param description
- * the {@link Description} to check, must not be {@code null}
- * @return whether the description is describing a Suite
- */
- public static boolean isSuite(final Description description) {
- final RunWith runWithAnnotation = description.getAnnotation(RunWith.class);
- return runWithAnnotation != null && Suite.class.isAssignableFrom(runWithAnnotation.value());
- }
-
- /**
- * Determines if the given {@link Description} is describing a test class.
- *
- * @param description
- * the {@link Description} to check, must not be {@code null}
- * @return whether the description is describing a test class
- */
- public static boolean isTestClass(final Description description) {
- return !isSuite(description) && !isTestMethod(description);
- }
-
- /**
- * Determines if the given {@link Description} is describing a test method.
- *
- * @param description
- * the {@link Description} to check, must not be {@code null}
- * @return whether the description is describing a test method
- */
- public static boolean isTestMethod(final Description description) {
- return description.getMethodName() != null;
- }
-
- @Override
- public boolean shouldRun(final Description description) {
- if (isSuite(description)) {
- // check if the description passes all suite filters
- for (final Filter filter : suiteFilters) {
- if (!filter.shouldRun(description)) {
- return false;
- }
- }
- if (!hasRunnableChildren(description)) {
- return false;
- }
- } else if (isTestClass(description)) {
- if (!hasRunnableChildren(description)) {
- return false;
- }
- // check if the description passes all test class filters
- for (final Filter filter : classFilters) {
- if (!filter.shouldRun(description)) {
- return false;
- }
- }
- } else if (isTestMethod(description)) {
- // check if the description passes all test method filters
- for (final Filter filter : methodFilters) {
- if (!filter.shouldRun(description)) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Check recursively if at least one child description should be run.
- *
- * @param description
- * the parent {@link Description}, must not be {@code null}
- * @return whether there are runnable children
- */
- private boolean hasRunnableChildren(final Description description) {
- for (final Description child : description.getChildren()) {
- if (shouldRun(child)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String describe() {
- final StringBuilder description = new StringBuilder("FilterRegistry");
- description.append(describeFilters(suiteFilters, "suite"));
- description.append(describeFilters(classFilters, "class"));
- description.append(describeFilters(methodFilters, "method"));
- return description.toString();
- }
-
- /**
- * Describes the list of filters.
- *
- * @param filters
- * the filters to describe, must not be {@code null}
- * @param title
- * the title for the filters, may be {@code null}
- * @return
- * the description for the given filters, never {@code null}
- */
- private String describeFilters(final List filters, final String title) {
- assert filters != null;
- final StringBuilder description = new StringBuilder();
- if (!filters.isEmpty()) {
- description.append(" (").append(title).append(" filters:");
- for (final Filter filter : filters) {
- description.append(' ').append(filter.describe());
- }
- description.append(')');
- }
- return description.toString();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FixedIssueFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FixedIssueFilter.java
deleted file mode 100644
index 240004171..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FixedIssueFilter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.BugTest;
-import com.avaloq.tools.ddk.test.core.Issue;
-import com.avaloq.tools.ddk.test.core.Issues;
-
-
-/**
- * A test filter that makes sure only tests for fixed issues are run.
- *
- * The filter checks if all of the related issues are fixed . If there are no related issues specified, the test is not run.
- *
- */
-public class FixedIssueFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- if (FilterRegistry.isSuite(description)) {
- return true;
- }
- // else: test class or test method
- final Issues issuesAnnotation = description.getAnnotation(Issues.class);
- if (issuesAnnotation != null) {
- for (final Issue issueAnnotation : issuesAnnotation.value()) {
- if (issueAnnotation != null && !issueAnnotation.fixed()) {
- return false;
- }
- }
- }
- final Issue issueAnnotation = description.getAnnotation(Issue.class);
- if (issueAnnotation != null && !issueAnnotation.fixed()) {
- return false;
- }
- final BugTest bugTestAnnotation = description.getAnnotation(BugTest.class);
- if (bugTestAnnotation != null && bugTestAnnotation.unresolved()) {
- return false;
- }
- return FilterRegistry.isTestMethod(description); // if it is a test class we still want to check (and maybe run) its children
- }
-
- @Override
- public String describe() {
- return FixedIssueFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FlakyMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FlakyMethodFilter.java
deleted file mode 100644
index f45b2ec50..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/FlakyMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.Flaky;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link Flaky} are run.
- */
-public class FlakyMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(Flaky.class) != null;
- }
-
- @Override
- public String describe() {
- return FlakyMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/IntegrationTestMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/IntegrationTestMethodFilter.java
deleted file mode 100644
index 6ebd42a76..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/IntegrationTestMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.IntegrationTest;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link IntegrationTest} are run.
- */
-public class IntegrationTestMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(IntegrationTest.class) != null;
- }
-
- @Override
- public String describe() {
- return IntegrationTestMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/ModuleTestMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/ModuleTestMethodFilter.java
deleted file mode 100644
index acbdba084..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/ModuleTestMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.ModuleTest;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link ModuleTest} are run.
- */
-public class ModuleTestMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(ModuleTest.class) != null;
- }
-
- @Override
- public String describe() {
- return ModuleTestMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NameMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NameMethodFilter.java
deleted file mode 100644
index 56d2af9b6..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NameMethodFilter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import java.util.regex.Pattern;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-
-/**
- * A test method filter that makes sure to run only those tests, which have a fully qualified name that matches a specified regular expression.
- *
- * Note: The regular expression needs to be defined using the property {@value #PROPERTY_NAME_PREFIX}.
- *
- */
-@SuppressWarnings("nls")
-public class NameMethodFilter extends Filter {
-
- private static final String PROPERTY_NAME_PREFIX = "com.avaloq.test.namemethodfilter";
- private static final String REGULAR_EXPRESSION = System.getProperty(PROPERTY_NAME_PREFIX, "");
- private static final Pattern PATTERN = Pattern.compile(REGULAR_EXPRESSION);
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return PATTERN.matcher(getQualifiedMethodName(description)).matches();
- }
-
- @Override
- public String describe() {
- return NameMethodFilter.class.getSimpleName();
- }
-
- /**
- * Returns the qualified method name of the given {@link Description}.
- *
- * @param description
- * the {@link Description} which must describe a test method, must not be {@code null}
- * @return the qualified method name of the given {@link Description}
- */
- private String getQualifiedMethodName(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getClassName() + "." + description.getMethodName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NegatedFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NegatedFilter.java
deleted file mode 100644
index 37e9ec33a..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/NegatedFilter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-
-/**
- * A filter that inverts the filter criteria of the underlying filter.
- */
-public class NegatedFilter extends Filter {
-
- private final Filter underlyingFilter;
-
- /**
- * Creates a new instance of {@link NegatedFilter}.
- *
- * @param filter
- * the filter to negate, must not be {@code null}
- */
- public NegatedFilter(final Filter filter) {
- assert filter != null;
- this.underlyingFilter = filter;
- }
-
- @Override
- public boolean shouldRun(final Description description) {
- return !underlyingFilter.shouldRun(description);
- }
-
- @Override
- public String describe() {
- return "!" + underlyingFilter.describe(); //$NON-NLS-1$
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/PerformanceTestMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/PerformanceTestMethodFilter.java
deleted file mode 100644
index 628f6e1bb..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/PerformanceTestMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.PerformanceTest;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link PerformanceTest} are run.
- */
-public class PerformanceTestMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(PerformanceTest.class) != null;
- }
-
- @Override
- public String describe() {
- return PerformanceTestMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SorterUtil.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SorterUtil.java
deleted file mode 100644
index 6f92d9246..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SorterUtil.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import java.util.Comparator;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Sorter;
-import org.junit.runners.ParentRunner;
-
-
-/**
- * Utility to specify a {@link Sorter}.
- */
-@SuppressWarnings("nls")
-public final class SorterUtil {
-
- public static final String SORTER_ALPHANUMERIC = "alphanumeric";
- public static final String PROPERTY_SORTER = "com.avaloq.test.sorter";
- private static final String EMPTY = "";
- private final Sorter sorter;
-
- private static final class SingletonHolder {
- private static SorterUtil instance = new SorterUtil();
-
- static SorterUtil get() {
- return instance;
- }
- }
-
- /**
- * Returns the singleton instance of {@link SorterUtil}.
- *
- * @return the singleton instance of {@link SorterUtil}, never {@code null}
- */
- public static SorterUtil getInstance() {
- return SingletonHolder.get();
- }
-
- /**
- * Creates a new instance of {@link SorterUtil}.
- */
- private SorterUtil() {
- final String propertySorter = System.getProperty(PROPERTY_SORTER, EMPTY);
- if (SORTER_ALPHANUMERIC.equalsIgnoreCase(propertySorter)) {
- sorter = new Sorter(new Comparator() {
- @Override
- public int compare(final Description o1, final Description o2) {
- return o1.getDisplayName().compareTo(o2.getDisplayName());
- }
- });
- } else {
- sorter = Sorter.NULL;
- }
- }
-
- /**
- * Initializes the test sorter.
- *
- * @param parentRunner
- * the {@link ParentRunner} to initialize, must not be {@code null}
- */
- public void initializeSorter(final ParentRunner> parentRunner) {
- parentRunner.sort(sorter);
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SwtBotClassFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SwtBotClassFilter.java
deleted file mode 100644
index 920ae40a4..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SwtBotClassFilter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runner.manipulation.Filter;
-
-
-/**
- * A test filter that makes sure only SWT bot tests are run.
- *
- * Note: The SWT bot test classes must use the test runner class specified in the VM argument
- * `com.avaloq.tools.ddk.test.core.junit.runners.SwtBotClassFilter.runwithannotation` for them to be recognized.
- *
- */
-public class SwtBotClassFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestClass(description);
- final RunWith runWithAnnotation = description.getAnnotation(RunWith.class);
-
- return runWithAnnotation != null
- && System.getProperty(SwtBotClassFilter.class.getCanonicalName() + ".runwithannotation").equals(runWithAnnotation.value().getName()); //$NON-NLS-1$
- }
-
- @Override
- public String describe() {
- return SwtBotClassFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SystemTestMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SystemTestMethodFilter.java
deleted file mode 100644
index 256a11e2e..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/SystemTestMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.SystemTest;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link SystemTest} are run.
- */
-public class SystemTestMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(SystemTest.class) != null;
- }
-
- @Override
- public String describe() {
- return SystemTestMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/TestLabelFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/TestLabelFilter.java
deleted file mode 100644
index efe543ede..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/TestLabelFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.apache.commons.lang3.ArrayUtils;
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.TestLabels;
-
-
-/**
- * A test filter that makes sure to run only those {@link Description}s that are annotated with a specific {@link TestLabel}.
- */
-public class TestLabelFilter extends Filter {
- private final String label;
-
- public TestLabelFilter(final String label) {
- this.label = label;
- }
-
- @Override
- public boolean shouldRun(final Description description) {
- TestLabels labels = description.getAnnotation(TestLabels.class);
- return labels != null && ArrayUtils.contains(labels.value(), label);
- }
-
- @Override
- public String describe() {
- return TestLabelFilter.class.getSimpleName();
- }
-
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnitTestMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnitTestMethodFilter.java
deleted file mode 100644
index f443053a4..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnitTestMethodFilter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.UnitTest;
-
-
-/**
- * A test method filter that makes sure only tests annotated with @{@link UnitTest} are run.
- */
-public class UnitTestMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- return description.getAnnotation(UnitTest.class) != null;
- }
-
- @Override
- public String describe() {
- return UnitTestMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedBugMethodFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedBugMethodFilter.java
deleted file mode 100644
index 6b7629657..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedBugMethodFilter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.BugTest;
-
-
-/**
- * A test method filter that makes sure only unresolved bug tests are run.
- */
-public class UnresolvedBugMethodFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- assert FilterRegistry.isTestMethod(description);
- final BugTest bugTestAnnotation = description.getAnnotation(BugTest.class);
- return bugTestAnnotation != null && bugTestAnnotation.unresolved();
- }
-
- @Override
- public String describe() {
- return UnresolvedBugMethodFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedIssueFilter.java b/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedIssueFilter.java
deleted file mode 100644
index 926e4127d..000000000
--- a/com.avaloq.tools.ddk.test.core/src/com/avaloq/tools/ddk/test/core/junit/runners/UnresolvedIssueFilter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.core.junit.runners;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
-import com.avaloq.tools.ddk.test.core.BugTest;
-import com.avaloq.tools.ddk.test.core.Issue;
-import com.avaloq.tools.ddk.test.core.Issues;
-
-
-/**
- * A test filter that makes sure only tests for unresolved issues are run.
- *
- * The filter checks if any of the related issues is unresolved. If there are no related issues specified, the test is not run.
- *
- */
-public class UnresolvedIssueFilter extends Filter {
-
- @Override
- public boolean shouldRun(final Description description) {
- if (FilterRegistry.isSuite(description)) {
- return true;
- }
- // else: test class or test method
- final Issues issuesAnnotation = description.getAnnotation(Issues.class);
- if (issuesAnnotation != null) {
- for (final Issue issueAnnotation : issuesAnnotation.value()) {
- if (issueAnnotation != null && !issueAnnotation.fixed()) {
- return true;
- }
- }
- }
- final Issue issueAnnotation = description.getAnnotation(Issue.class);
- if (issueAnnotation != null && !issueAnnotation.fixed()) {
- return true;
- }
- final BugTest bugTestAnnotation = description.getAnnotation(BugTest.class);
- if (bugTestAnnotation != null && bugTestAnnotation.unresolved()) { // NOPMD SimplifyBooleanReturns
- return true;
- }
- return FilterRegistry.isTestClass(description); // if it is a test class we still want to check (and maybe run) its children
- }
-
- @Override
- public String describe() {
- return UnresolvedIssueFilter.class.getSimpleName();
- }
-}
diff --git a/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/SwtBotRecordingTestRunner.java b/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/SwtBotRecordingTestRunner.java
deleted file mode 100644
index 1e97cfdc4..000000000
--- a/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/SwtBotRecordingTestRunner.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.ui.junit.runners;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
-import org.junit.internal.runners.statements.InvokeMethod;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import com.avaloq.tools.ddk.test.core.AbstractSystemTest;
-import com.avaloq.tools.ddk.test.core.junit.runners.ClassRunner;
-import com.avaloq.tools.ddk.test.ui.swtbot.CoreSwtbotTools;
-
-
-/**
- * A {@link org.junit.runner.Runner} to use with swt bot tests featuring screenshot recording.
- */
-// suppress warning restriction of org.junit.internal.runners.statements.InvokeMethod
-@SuppressWarnings("restriction")
-public class SwtBotRecordingTestRunner extends ClassRunner {
- /**
- * Used to mark a test class or method to define the recording interval in milliseconds to use for the {@link SwtBotRecordingTestRunner}.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD, ElementType.TYPE})
- public static @interface RecordingInterval {
- /**
- * Returns the recording interval value in milliseconds.
- *
- * @return the recording interval value in milliseconds
- */
- long value();
- }
-
- private final TestRunRecording testRunRecording;
-
- /**
- * Creates a new instance of {@link SwtBotRecordingTestRunner}.
- * Only called reflectively. Do not use programmatically.
- *
- * @param testClass
- * the test class to run
- * @throws InitializationError
- * if any initialization failed
- */
- public SwtBotRecordingTestRunner(final Class extends AbstractSystemTest> testClass) throws InitializationError {
- super(testClass);
- CoreSwtbotTools.initializePreferences();
- testRunRecording = new TestRunRecording(getTestClass().getJavaClass(), SWTBotPreferences.SCREENSHOTS_DIR);
- // TODO: add custom made {@link org.junit.runners.model.Statement} to check for exceptions during the test
- // (by default test failures are reported only after the teardown has taken place)
- }
-
- @Override
- public void run(final RunNotifier notifier) {
- try {
- notifier.removeListener(testRunRecording); // remove existing listeners that could be added by suite or class runners
- notifier.addListener(testRunRecording);
- super.run(notifier);
- } finally {
- notifier.removeListener(testRunRecording);
- }
- }
-
- @Override
- protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
- testRunRecording.setRecordingInterval(getRecordingInterval(method));
- super.runChild(method, notifier);
- }
-
- @Override
- protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
- return new InvokeMethod(method, test) {
- @Override
- // CHECKSTYLE:CHECK-OFF IllegalThrow // inherited JUnit throw style
- public void evaluate() throws Throwable {
- // CHECKSTYLE:CHECK-ON IllegalThrow
- try {
- super.evaluate();
- // CHECKSTYLE:CHECK-OFF IllegalCatch // catching in order to act upon but then throwing the exception again
- } catch (final Throwable throwable) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- testRunRecording.methodInvokeFailure(throwable);
- throw throwable;
- }
- }
- };
- }
-
- /**
- * Computes the capture interval to use for recording the given test method.
- * Checks first the annotation {@link RecordingInterval} of the method,
- * then the annotations of the test class.
- * Falls back to the default setting if no annotations were found.
- *
- * @param method
- * the method under test
- * @return the framerate to use for recording the given test method
- */
- private long getRecordingInterval(final FrameworkMethod method) {
- RecordingInterval recordingInterval = method.getAnnotation(RecordingInterval.class);
- if (recordingInterval != null) {
- return recordingInterval.value();
- }
- for (Annotation annotation : getTestClass().getAnnotations()) {
- if (annotation.annotationType().equals(RecordingInterval.class)) {
- return ((RecordingInterval) annotation).value();
- }
- }
- return TestRunRecording.DEFAULT_RECORDING_INTERVAL;
- }
-}
diff --git a/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/TestRunRecording.java b/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/TestRunRecording.java
deleted file mode 100644
index 69c0da2c9..000000000
--- a/com.avaloq.tools.ddk.test.ui/src/com/avaloq/tools/ddk/test/ui/junit/runners/TestRunRecording.java
+++ /dev/null
@@ -1,726 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.test.ui.junit.runners;
-
-import java.awt.AWTException;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Robot;
-import java.awt.Toolkit;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.management.LockInfo;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MonitorInfo;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import java.nio.charset.StandardCharsets;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Set;
-import java.util.logging.Logger;
-
-import javax.imageio.ImageIO;
-
-import org.eclipse.emf.common.util.WrappedException;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
-import org.eclipse.swtbot.swt.finder.results.VoidResult;
-import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
-import org.eclipse.ui.PlatformUI;
-import org.junit.runner.Description;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunListener;
-
-import com.avaloq.tools.ddk.annotations.SuppressFBWarnings;
-import com.avaloq.tools.ddk.test.core.AbstractTestStep;
-import com.avaloq.tools.ddk.test.core.TestStepListener;
-import com.google.common.collect.Sets;
-import com.google.common.primitives.Longs;
-
-
-/**
- * Recording of a test run.
- */
-// CHECKSTYLE:OFF
-@SuppressWarnings("nls")
-public class TestRunRecording extends RunListener implements TestStepListener, MouseListener {
- private static final String NEW_LINE = "\r\n";
- private static final String FILE_INFORMATION_SEPARATOR = "__";
- private static final int MOUSE_POINTER_SIZE = 24;
- private static final int INFO_BORDER_SIZE = 3;
- // CHECKSTYLE:ON
- // private static final int FILE_READ_BUFFER = 2048;
- private static final int INFO_FONT_SIZE = 18;
- private static final Logger LOGGER = Logger.getLogger(TestRunRecording.class.getSimpleName());
- private static final String IMAGE_TYPE = SWTBotPreferences.SCREENSHOT_FORMAT;
- private static final String IMAGE_FILE_EXTENSION = '.' + IMAGE_TYPE;
- private static final String CALL_STACK_FILE_EXTENSION = ".txt";
- private static boolean screenshotsCleared;
- private final Robot robot;
- private final Toolkit toolkit = Toolkit.getDefaultToolkit();
- private static final int STACK_DEPTH = 80;
- private static final ThreadMXBean THREAD_BEAN = ManagementFactory.getThreadMXBean();
-
- /**
- * The recording interval defines the (approximate) maximum interval in milliseconds between two consecutive screenshots.
- */
- public static final long DEFAULT_RECORDING_INTERVAL = 500;
- private static final int MINIMAL_RECORDING_INTERVAL = 100;
- private long recordingInterval;
-
- private final String screenshotFolder;
- private final Class> testClass;
- private String testClassName;
- private String testMethodName;
- private AbstractTestStep currentTestStep;
- private TestStepState currentTestStepState;
-
- private Thread captureThread;
- private final Object lock = new Object(); // used for synchronizing with anonymous classes
- private boolean captureThreadRunning;
- private long lastCaptureTime;
-
- private boolean testFailed;
- /** The associated exception in case of a failure. */
- private Throwable exception;
- private boolean testStepStarted;
- private boolean mouseClicked;
- private boolean mousePressedDown;
- private MouseEvent mouseEvent;
-
- /**
- * Creates a new instance of {@link TestRunRecording}.
- *
- * @param testClass
- * the class under test
- * @param screenshotFolder
- * the folder dedicated for screenshots
- */
- public TestRunRecording(final Class> testClass, final String screenshotFolder) {
- this(testClass, screenshotFolder, DEFAULT_RECORDING_INTERVAL);
- }
-
- /**
- * Creates a new instance of {@link TestRunRecording}.
- *
- * @param testClass
- * the class under test
- * @param screenshotFolder
- * the folder dedicated for screenshots
- * @param recordingInterval
- * the interval in milliseconds between two consecutive screenshots
- */
- public TestRunRecording(final Class> testClass, final String screenshotFolder, final long recordingInterval) {
- this.testClass = testClass;
- this.screenshotFolder = screenshotFolder;
- setRecordingInterval(recordingInterval);
- try {
- robot = new Robot();
- } catch (AWTException e) {
- throw new WrappedException("TestRunRecording cannot be used in a headless environment.", e);
- }
- }
-
- /**
- * Sets the interval in milliseconds between two consecutive screenshots.
- *
- * @param recordingInterval
- * the new recording interval in milliseconds
- */
- public final void setRecordingInterval(final long recordingInterval) {
- this.recordingInterval = Math.max(recordingInterval, MINIMAL_RECORDING_INTERVAL);
- }
-
- @Override
- @SuppressWarnings("PMD.JUnit4TestShouldUseTestAnnotation")
- @SuppressFBWarnings("AT_STALE_THREAD_WRITE_OF_PRIMITIVE")
- public void testStarted(final Description description) {
- if (!screenshotsCleared) {
- deleteDirectoryContents(new File(screenshotFolder));
- screenshotsCleared = true;
- }
- testFailed = false;
- testStepStarted = false;
- if (description.getTestClass() != null) {
- testClassName = description.getTestClass().getName();
- } else {
- testClassName = testClass.getSimpleName();
- }
- testMethodName = description.getMethodName();
- AbstractTestStep.registerTestStepListener(this);
- UIThreadRunnable.syncExec(new VoidResult() {
- @Override
- public void run() {
- PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().addMouseListener(TestRunRecording.this);
- }
- });
- start();
- }
-
- @Override
- @SuppressWarnings("PMD.JUnit4TestShouldUseTestAnnotation")
- public void testFinished(final Description description) {
- stop();
- AbstractTestStep.removeTestStepListener(this);
- UIThreadRunnable.syncExec(new VoidResult() {
- @Override
- public void run() {
- PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().removeMouseListener(TestRunRecording.this);
- }
- });
- if (!testFailed) {
- deleteScreenshots();
- }
- }
-
- @Override
- @SuppressWarnings("PMD.JUnit4TestShouldUseTestAnnotation")
- public void testFailure(final Failure failure) {
- methodInvokeFailure(failure.getException());
- }
-
- @Override
- public void stepStateChanged(final AbstractTestStep testStep, final TestStepState testStepState, final Throwable throwable) {
- synchronized (lock) {
- this.currentTestStep = testStep;
- this.currentTestStepState = testStepState;
- testStepStarted = true;
- if (TestStepState.FAILED == testStepState || TestStepState.ERRORED == testStepState) {
- exception = throwable;
- testFailed = true;
- }
- createScreenshot(0); // always create a screenshot when the step state changes
- createCallStack(0);
- }
- }
-
- /**
- * Handles an exception caused by invoking the test method.
- *
- * @param throwable
- * the thrown {@link Throwable}, must not be {@code null}
- */
- public void methodInvokeFailure(final Throwable throwable) {
- synchronized (lock) {
- if (!testFailed) {
- exception = throwable;
- testFailed = true;
- createScreenshot(0); // immediately create a screenshot when a test failure is reported
- createCallStack(0);
- }
- }
- }
-
- /**
- * Creates a new asynchronous thread that regularly creates screenshots of the running test environment.
- * Stops a previously started and still running thread.
- */
- private void start() {
- if (captureThreadRunning) {
- stop();
- }
- deleteScreenshots();
- captureThreadRunning = true;
- captureThread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (captureThreadRunning) {
- synchronized (lock) {
- // if test steps are used, only create continuous screenshots in the run step state; for all other states 1 screenshot is enough
- if (currentTestStep != null && TestStepState.RUN == currentTestStepState) {
- createScreenshot(recordingInterval);
- createCallStack(recordingInterval);
- }
- }
- try {
- Thread.sleep(recordingInterval);
- } catch (final InterruptedException e) {
- // ignore, because #createScreenshot will make sure that a minimal recording interval is retained
- }
- }
- }
- });
- captureThread.start();
- }
-
- /**
- * Stops the asynchronous thread from creating screenshots.
- */
- @SuppressFBWarnings("AT_STALE_THREAD_WRITE_OF_PRIMITIVE")
- private void stop() {
- captureThreadRunning = false;
- try {
- captureThread.join();
- } catch (final InterruptedException e) {
- // ignore: the capture thread is no longer important and shall silently be removed
- }
- }
-
- /**
- * Creates a new screenshot, if the last screenshot is older than the minimal recording interval.
- */
- private void createScreenshot() {
- createScreenshot(MINIMAL_RECORDING_INTERVAL);
- }
-
- /**
- * Creates a new screenshot, if the last screenshot is older than the minimal recording interval.
- */
- private void createCallStack() {
- createCallStack(MINIMAL_RECORDING_INTERVAL);
- }
-
- /**
- * Creates a new screenshot, if the last screenshot is older than the provided captureInterval.
- *
- * @param captureInterval
- * the minimal interval in milliseconds which determines if the screenshot is created
- */
- private void createScreenshot(final long captureInterval) {
- synchronized (lock) {
- if (System.currentTimeMillis() > lastCaptureTime + captureInterval) {
- lastCaptureTime = System.currentTimeMillis(); // save time at beginning, so that a failed screenshot results in a skipped frame
- final BufferedImage image = capture();
- process(image);
- try {
- store(image);
- } catch (IOException e) {
- LOGGER.warning("Could not create screenshot: " + getImageFileName());
- }
- }
- }
- }
-
- /**
- * Creates a new call stack record, if the last record is older than the provided captureInterval.
- *
- * @param captureInterval
- * the minimal interval in milliseconds which determines if the call stack is created
- */
- private void createCallStack(final long captureInterval) {
- synchronized (lock) {
- if (System.currentTimeMillis() > lastCaptureTime + captureInterval) {
- lastCaptureTime = System.currentTimeMillis(); // save time at beginning
- final String image = captureCallStack();
- try {
- storeCallStack(image);
- } catch (IOException e) {
- LOGGER.warning("Could not create screenshot: " + getImageFileName());
- }
- }
- }
- }
-
- /**
- * Captures a screenshot.
- *
- * @return the {@link BufferedImage}, never {@code null}
- */
- private BufferedImage capture() {
- final Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
- return robot.createScreenCapture(screenBounds);
- }
-
- /**
- * Captures a call stack.
- *
- * @return the call stack with test status information, never {@code null}
- */
- @SuppressWarnings("PMD.InsufficientStringBufferDeclaration")
- private String captureCallStack() {
- StringBuilder trace = new StringBuilder();
- // Same info as on the screenshot
- trace.append("TEST: ").append(testClassName).append('.').append(testMethodName).append(NEW_LINE);
- if (testStepStarted && currentTestStep != null && currentTestStepState != null) {
- String colonWithSpace = ": ";
- trace.append("TEST STEP: ").append(currentTestStep.getName()).append(colonWithSpace).append(currentTestStepState.toString()).append(NEW_LINE);
- if (testFailed && exception != null) {
- trace.append("TEST FAILED: ").append(exception.getClass().getSimpleName()).append(colonWithSpace).append(exception.getMessage()).append(NEW_LINE);
- }
- }
- trace.append(getThreadInfo());
- return trace.toString();
- }
-
- /**
- * Gets the task name.
- *
- * @param id
- * the id
- * @param name
- * the name
- * @return the task name
- */
- private static String getTaskName(final long id, final String name) {
- if (name == null) {
- return Long.toString(id);
- }
- return id + " (" + name + ")";
- }
-
- /**
- * Gathers the thread ids of threads that look deadlocked.
- *
- * @return the thread ids of deadlocked threads
- */
- private static Set getDeadlockThreadIds() {
- Set deadlockedThreads = Sets.newHashSet();
- long[] dead = THREAD_BEAN.findDeadlockedThreads();
- if (dead != null) {
- deadlockedThreads.addAll(Longs.asList(dead));
- }
- dead = THREAD_BEAN.findMonitorDeadlockedThreads();
- if (dead != null) {
- deadlockedThreads.addAll(Longs.asList(dead));
- }
- return deadlockedThreads;
- }
-
- /**
- * Prints the owned locks for the thread.
- * Must have explicitly obtained Monitor and Synchronizer information for anything to show up from here.
- *
- * @param info
- * the {@code:ThreadInfo} for the thread in question, must not be {@code:null}
- * @return the owned lock information
- */
- private static String getOwnedLockInfo(final ThreadInfo info) {
- StringBuilder trace = new StringBuilder(" Holding locks for:").append(NEW_LINE);
- for (LockInfo lock : info.getLockedSynchronizers()) {
- trace.append(" ").append(lock.toString()).append(NEW_LINE);
- }
- for (MonitorInfo monitor : info.getLockedMonitors()) {
- trace.append(" ").append(monitor.toString()).append(NEW_LINE);
- }
- return trace.toString();
- }
-
- /**
- * Print the thread's stack trace.
- *
- * @param info
- * the {@code:ThreadInfo} for the thread in question, must not be {@code:null}
- * @return the thread stack trace
- */
- @SuppressWarnings("PMD.InsufficientStringBufferDeclaration")
- private static String getCallStackTrace(final ThreadInfo info) {
- StringBuilder trace = new StringBuilder(" Stack:").append(NEW_LINE);
- int frameCount = 0;
- for (StackTraceElement frame : info.getStackTrace()) {
- trace.append(" ").append(frame.toString()).append(NEW_LINE);
- // Can't request lock information AND limit call stack size with only one ThreadInfo request. Fake it instead.
- if (frameCount++ >= STACK_DEPTH) {
- trace.append(" ...").append(NEW_LINE);
- break;
- }
- }
- return trace.toString();
- }
-
- /**
- * Print all of the thread's information and stack traces.
- *
- * @return the thread info
- */
- private static String getThreadInfo() {
- boolean contention = THREAD_BEAN.isThreadContentionMonitoringEnabled();
- Set deadlockedThreads = getDeadlockThreadIds();
- ThreadInfo[] threadInfos = THREAD_BEAN.dumpAllThreads(true, true);
- // CHECKSTYLE:OFF MagicNumber
- StringBuilder trace = new StringBuilder(200).append(threadInfos.length).append(" active threads").append(NEW_LINE);
- // CHECKSTYLE:ON
- for (ThreadInfo info : threadInfos) {
- if (info == null) {
- trace.append(" Inactive").append(NEW_LINE);
- continue;
- }
- boolean isDeadlocked = deadlockedThreads.contains(info.getThreadId());
- trace.append("Thread ").append(getTaskName(info.getThreadId(), info.getThreadName()));
- if (isDeadlocked) {
- trace.append(" <>");
- }
- trace.append(NEW_LINE);
- Thread.State state = info.getThreadState();
- trace.append(" State: ").append(state).append(NEW_LINE);
- trace.append(" Blocked count: ").append(info.getBlockedCount()).append(NEW_LINE);
- trace.append(" Waited count: ").append(info.getWaitedCount()).append(NEW_LINE);
- if (contention) {
- trace.append(" Blocked time: ").append(info.getBlockedTime()).append(NEW_LINE);
- trace.append(" Waited time: ").append(info.getWaitedTime()).append(NEW_LINE);
- }
- if (state == Thread.State.WAITING) {
- trace.append(" Waiting on ").append(info.getLockName()).append(NEW_LINE);
- } else if (state == Thread.State.BLOCKED) {
- trace.append(" Blocked on ").append(info.getLockName()).append(NEW_LINE);
- trace.append(" Blocked by ").append(getTaskName(info.getLockOwnerId(), info.getLockOwnerName())).append(NEW_LINE);
- }
- if (state == Thread.State.WAITING || state == Thread.State.BLOCKED || isDeadlocked) {
- trace.append(getOwnedLockInfo(info));
- }
- trace.append(getCallStackTrace(info));
- }
- return trace.toString();
- }
-
- /**
- * Processes the given screenshot by adding corresponding information to the image.
- *
- * @param image
- * the {@link BufferedImage}, must not be {@code null}
- */
- private void process(final BufferedImage image) {
- if (image == null) {
- return;
- }
- final Graphics2D graphics = image.createGraphics();
- // draw mouse location
- if (mouseEvent != null) {
- drawCrosshair(graphics, mouseEvent.x, mouseEvent.y);
- }
- // draw capture information
- int x = image.getWidth() / 2;
- int y = 0;
- drawInfoBox(graphics, testClassName + "." + testMethodName, x, y);
- if (testStepStarted && currentTestStep != null && currentTestStepState != null) {
- y += getInfoBoxHeight() + INFO_BORDER_SIZE;
- drawInfoBox(graphics, currentTestStep.getName() + ": " + currentTestStepState.toString(), x, y);
- if (testFailed && exception != null) {
- final String message = exception.getMessage();
- if (message != null) {
- y += getInfoBoxHeight() + INFO_BORDER_SIZE;
- drawInfoBox(graphics, exception.getClass().getSimpleName() + ": " + message, x, y);
- }
- }
- }
- }
-
- /**
- * Draws a crosshair at the given screen coordinates on the captured image.
- *
- * @param graphics
- * the {@link Graphics2D}, must not be {@code null}
- * @param x
- * the x screen coordinate
- * @param y
- * the y screen coordinate
- */
- private void drawCrosshair(final Graphics2D graphics, final int x, final int y) {
- if (mouseClicked) {
- graphics.setColor(Color.GREEN);
- } else if (mousePressedDown) {
- graphics.setColor(Color.RED);
- } else {
- graphics.setColor(Color.BLUE);
- }
- graphics.drawOval(x - MOUSE_POINTER_SIZE / 2, y - MOUSE_POINTER_SIZE / 2, MOUSE_POINTER_SIZE, MOUSE_POINTER_SIZE);
- graphics.drawOval(x - MOUSE_POINTER_SIZE / 2 + 1, y - MOUSE_POINTER_SIZE / 2 + 1, MOUSE_POINTER_SIZE - 2, MOUSE_POINTER_SIZE - 2);
- graphics.drawLine(x, y - MOUSE_POINTER_SIZE / 2, x, y + MOUSE_POINTER_SIZE / 2);
- graphics.drawLine(x - MOUSE_POINTER_SIZE / 2, y, x + MOUSE_POINTER_SIZE / 2, y);
- }
-
- /**
- * Draws a black box with an info text on the captured image.
- *
- * @param graphics
- * the {@link Graphics2D}, must not be {@code null}
- * @param info
- * the text to draw, must not be {@code null}
- * @param x
- * the center x coordinate of the box on the screenshot image
- * @param y
- * the top y coordinate of the box on the screenshot image
- */
- private void drawInfoBox(final Graphics2D graphics, final String info, final int x, final int y) {
- graphics.setFont(new Font("Arial", Font.PLAIN, INFO_FONT_SIZE));
- final int stringWidth = graphics.getFontMetrics().stringWidth(info);
- final int leftCoord = x - stringWidth / 2;
- graphics.setColor(Color.BLACK);
- graphics.fillRoundRect(leftCoord - INFO_BORDER_SIZE, y, stringWidth + 2 * INFO_BORDER_SIZE, INFO_FONT_SIZE
- + 2 * INFO_BORDER_SIZE, INFO_BORDER_SIZE, INFO_BORDER_SIZE);
- if (testFailed) {
- graphics.setColor(Color.RED);
- } else {
- graphics.setColor(Color.GREEN);
- }
- graphics.drawString(info, leftCoord, y + INFO_FONT_SIZE + INFO_BORDER_SIZE);
- }
-
- /**
- * Returns the height an info box has.
- *
- * @return the height an info box has
- */
- private int getInfoBoxHeight() {
- return INFO_FONT_SIZE + 2 * INFO_BORDER_SIZE;
- }
-
- /**
- * Stores the captured image.
- *
- * @param image
- * the {@link BufferedImage}, must not be {@code null}
- * @throws IOException
- * if the image could not be written to file.
- */
- private void store(final BufferedImage image) throws IOException {
- final File screenshotDirectory = new File(getScreenshotDirectory());
- screenshotDirectory.mkdirs();
- ImageIO.write(image, IMAGE_TYPE, new File(getImageFileName()));
- }
-
- /**
- * Stores the call stack.
- *
- * @param trace
- * the call stack information to store, must not be {@code null}
- * @throws IOException
- * if the call stack could not be written to file.
- */
- private void storeCallStack(final String trace) throws IOException {
- // Put it next to screenshots (intentional)
- final File screenshotDirectory = new File(getScreenshotDirectory());
- screenshotDirectory.mkdirs();
- PrintWriter out = new PrintWriter(getCallStackFileName(), StandardCharsets.UTF_8);
- out.print(trace);
- out.close();
- }
-
- /**
- * Returns the image file name to use for the current screenshot.
- *
- * @return the image file name to use for the current screenshot, never {@code null}
- */
- private String getImageFileName() {
- return getFileNamePrefix() + IMAGE_FILE_EXTENSION;
- }
-
- /**
- * Returns the image file name to use for the current screenshot.
- *
- * @return the image file name to use for the current screenshot, never {@code null}
- */
- private String getCallStackFileName() {
- return getFileNamePrefix() + CALL_STACK_FILE_EXTENSION;
- }
-
- /**
- * Returns a prefix for a file name.
- *
- * @return Prefix for trace file names
- */
- private String getFileNamePrefix() {
- final StringBuilder result = new StringBuilder(getScreenshotDirectory());
- final Date date = new Date(lastCaptureTime); // NOPMD ReplaceJavaUtilDate
- final DateFormat formatter = new SimpleDateFormat("HH.mm.ss.SSS", Locale.UK);
- final String formattedDate = formatter.format(date);
- result.append(formattedDate);
- if (testStepStarted && currentTestStep != null) {
- result.append(FILE_INFORMATION_SEPARATOR).append(currentTestStep.getName());
- if (currentTestStepState != null) {
- result.append(FILE_INFORMATION_SEPARATOR).append(currentTestStepState.toString());
- }
- } else if (testFailed) {
- result.append("__FAILED");
- }
- return result.toString();
- }
-
- /**
- * Returns the screenshot directory for the current test method.
- *
- * @return the screenshot directory for the current test method, never {@code null}
- */
- private String getScreenshotDirectory() {
- return getTestClassScreenshotDirectory() + testMethodName + File.separatorChar;
- }
-
- /**
- * Returns the screenshot directory for the current test class.
- *
- * @return the screenshot directory for the current test class, never {@code null}
- */
- private String getTestClassScreenshotDirectory() {
- return screenshotFolder + File.separatorChar + testClassName + File.separatorChar;
- }
-
- /**
- * Deletes all screenshots taken with this {@link TestRunRecording} for the current test.
- * If the containing folder remains empty, then it is removed too.
- */
- private void deleteScreenshots() {
- deleteDirectory(new File(getScreenshotDirectory()));
- // delete the directory of the test class too (works only if there are no other test method directories)
- new File(getTestClassScreenshotDirectory()).delete();
- }
-
- /**
- * Deletes a directory and all its children.
- *
- * @param path
- * the {@link File} folder to delete
- * @return {@code true} if successful, {@code false} otherwise
- */
- private boolean deleteDirectory(final File path) {
- final boolean success = deleteDirectoryContents(path);
- return success && path.delete();
- }
-
- /**
- * Deletes all contents (recursively) of a directory.
- *
- * @param path
- * the {@link File} folder for which the contents are to be deleted
- * @return {@code true} if successful, {@code false} otherwise
- */
- private boolean deleteDirectoryContents(final File path) {
- boolean success = true;
- if (path.exists()) {
- final File[] files = path.listFiles();
- for (final File file : files) {
- if (file.isDirectory()) {
- success &= deleteDirectory(file);
- } else {
- success &= file.delete();
- }
- }
- }
- return success;
- }
-
- @Override
- public void mouseDoubleClick(final MouseEvent e) {
- // do nothing special, it will be displayed as 1 total click.
- }
-
- @Override
- public void mouseDown(final MouseEvent e) {
- mouseEvent = e;
- mousePressedDown = true;
- }
-
- @Override
- public void mouseUp(final MouseEvent e) {
- mousePressedDown = false;
- mouseEvent = e;
- mouseClicked = true;
- createScreenshot();
- createCallStack();
- mouseClicked = false;
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.export.test/src/com/avaloq/tools/ddk/xtext/test/export/ExportTestSuite.java b/com.avaloq.tools.ddk.xtext.export.test/src/com/avaloq/tools/ddk/xtext/test/export/ExportTestSuite.java
index 767126c1d..6439fdfb3 100644
--- a/com.avaloq.tools.ddk.xtext.export.test/src/com/avaloq/tools/ddk/xtext/test/export/ExportTestSuite.java
+++ b/com.avaloq.tools.ddk.xtext.export.test/src/com/avaloq/tools/ddk/xtext/test/export/ExportTestSuite.java
@@ -16,6 +16,7 @@
import com.avaloq.tools.ddk.xtext.export.exporting.ExportExportingTest;
import com.avaloq.tools.ddk.xtext.export.formatting.ExportFormattingTest;
import com.avaloq.tools.ddk.xtext.export.scoping.ExportScopingTest;
+import com.avaloq.tools.ddk.xtext.export.validation.ExportValidationOkTest;
import com.avaloq.tools.ddk.xtext.export.validation.ExportValidationTest;
@@ -23,6 +24,6 @@
* Empty class serving only as holder for JUnit4 annotations.
*/
@Suite
-@SelectClasses({ExportFormattingTest.class, ExportValidationTest.class, ExportScopingTest.class, ExportExportingTest.class})
+@SelectClasses({ExportFormattingTest.class, ExportValidationTest.class, ExportValidationOkTest.class, ExportScopingTest.class, ExportExportingTest.class})
public class ExportTestSuite {
}
diff --git a/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/test/generator/GeneratorTestSuite.java b/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/test/generator/GeneratorTestSuite.java
index 337612d31..efbd202e4 100644
--- a/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/test/generator/GeneratorTestSuite.java
+++ b/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/test/generator/GeneratorTestSuite.java
@@ -18,6 +18,7 @@
import com.avaloq.tools.ddk.xtext.generator.expression.ExpressionsExtentionsTest;
import com.avaloq.tools.ddk.xtext.generator.test.util.EClassComparatorTest;
import com.avaloq.tools.ddk.xtext.generator.test.util.GraphTest;
+import com.avaloq.tools.ddk.xtext.generator.xbase.test.XbaseGeneratorFragmentTest;
/**
@@ -30,7 +31,8 @@
CompilationContextTest.class,
ExpressionsExtentionsTest.class,
EClassComparatorTest.class,
- GraphTest.class
+ GraphTest.class,
+ XbaseGeneratorFragmentTest.class
// @Format-On
})
diff --git a/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/xbase/test/XbaseGeneratorFragmentTest.xtend b/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/xbase/test/XbaseGeneratorFragmentTest.xtend
index 54acad8d6..9a95fd615 100644
--- a/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/xbase/test/XbaseGeneratorFragmentTest.xtend
+++ b/com.avaloq.tools.ddk.xtext.generator.test/src/com/avaloq/tools/ddk/xtext/generator/xbase/test/XbaseGeneratorFragmentTest.xtend
@@ -13,7 +13,11 @@ package com.avaloq.tools.ddk.xtext.generator.xbase.test
import com.avaloq.tools.ddk.test.core.jupiter.BugTest
import org.eclipse.emf.common.util.BasicEList
+import org.eclipse.emf.common.util.URI
+import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EPackage
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.AbstractElement
import org.eclipse.xtext.AbstractMetamodelDeclaration
import org.eclipse.xtext.AbstractRule
@@ -25,6 +29,8 @@ import org.eclipse.xtext.RuleCall
import org.eclipse.xtext.TypeRef
import org.eclipse.xtext.XtextPackage
+import static org.mockito.ArgumentMatchers.any
+import static org.mockito.ArgumentMatchers.eq
import static org.mockito.Mockito.mock
import static org.mockito.Mockito.when
import org.eclipse.xtext.xtext.generator.xbase.XbaseUsageDetector
@@ -52,6 +58,16 @@ class XbaseGeneratorFragmentTest {
val detector = new XbaseUsageDetector
+ // Shared EClass instance used as the resolved Xtype::XImportSection. EcoreUtil2.isAssignableFrom
+ // returns true via reference equality when the rule's type classifier is this same instance.
+ val EClass mockXtypeXImportSectionEClass = mock(EClass)
+ val ResourceSet mockResourceSet = mock(ResourceSet) => [
+ when(getEObject(any(URI), eq(true))).thenReturn(mockXtypeXImportSectionEClass)
+ ]
+ val Resource mockResource = mock(Resource) => [
+ when(resourceSet).thenReturn(mockResourceSet)
+ ]
+
/**
* Set expectations prior to calling usesXImportSection.apply().
*
@@ -70,6 +86,19 @@ class XbaseGeneratorFragmentTest {
when(mockType.metamodel).thenReturn(mockMetamodel)
when(mockMetamodel.EPackage).thenReturn(mockEPackage)
when(mockEPackage.name).thenReturn(packageName)
+
+ // The current XbaseUsageDetector navigates rule.eResource().getResourceSet() to look up the
+ // Xtype XImportSection EClass, then compares it (via EcoreUtil2.isAssignableFrom) against the
+ // rule's type classifier. Treat (xtypePackageName + XImportSection) as the canonical match
+ // by giving such rules the same EClass instance the resource-set lookup returns; everything
+ // else gets a fresh distinct mock so isAssignableFrom evaluates false.
+ when(mockRule.eResource).thenReturn(mockResource)
+ val EClass classifier = if (xtypePackageName.equals(packageName) && xImportSectionRuleName.equals(ruleName)) {
+ mockXtypeXImportSectionEClass
+ } else {
+ mock(EClass)
+ }
+ when(mockType.classifier).thenReturn(classifier)
}
/**
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractTest.java
deleted file mode 100644
index 9b3115d2f..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractTest.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.common.util.WrappedException;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.actions.WorkspaceModifyOperation;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.runner.RunWith;
-
-import com.avaloq.tools.ddk.test.core.AfterAll;
-import com.avaloq.tools.ddk.test.core.BeforeAll;
-import com.avaloq.tools.ddk.test.core.BugTestAwareRule;
-import com.avaloq.tools.ddk.test.core.IssueAwareRule;
-import com.avaloq.tools.ddk.test.core.LoggingRule;
-import com.avaloq.tools.ddk.test.core.mock.ExtensionRegistryMock;
-import com.avaloq.tools.ddk.test.core.mock.ServiceMock;
-import com.avaloq.tools.ddk.xtext.test.junit.runners.XtextClassRunner;
-import com.google.common.collect.ImmutableList;
-
-
-/**
- * Provides a test class specific custom test framework for tests that run in the ACF environment.
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
-@RunWith(XtextClassRunner.class)
-@SuppressWarnings("nls")
-public abstract class AbstractTest {
-
- /**
- * Prefix for customer sources.
- * Consider also: com.avaloq.tools.asmd.testbase.TestUtil.CUSTR_PREFIX
- * The duplicated definition of the prefix must be harmonized based on harmonization of test plugins.
- */
- protected static final String CUSTOMER_SOURCE_PREFIX = "custr_";
-
- protected static final String PROJECT_NAME = "SDK";
-
- private static final String HIGH_LATENCY_PROPERTY = "com.avaloq.tools.hl.supported";
-
- private static final String LANGUAGE_VERSION_CACHING_PROPERTY = "com.avaloq.tools.LanguageConfigCaching";
-
- private static Map, TestInformation> testInformationMap = new HashMap, TestInformation>();
-
- @Rule
- // CHECKSTYLE:CHECK-OFF Visibility MethodRules cannot be private
- public final LoggingRule watchman = LoggingRule.getInstance();
- // CHECKSTYLE:CHECK-ON Visibility
-
- /**
- * Enables support for unresolved bug tests.
- */
- @Rule
- // CHECKSTYLE:CHECK-OFF Visibility MethodRules cannot be private
- public BugTestAwareRule bugTestRule = BugTestAwareRule.getInstance();
- // CHECKSTYLE:CHECK-ON Visibility
-
- @Rule
- // CHECKSTYLE:CHECK-OFF VisibilityModifier
- public final IssueAwareRule issueRule = IssueAwareRule.getInstance();
-
- // CHECKSTYLE:CHECK-ON VisibilityModifier
-
- protected ITestProjectManager getTestProjectManager() {
- return getTestUtil().getTestProjectManager();
- }
-
- /**
- * Returns the URI for the given target source file.
- *
- * @param fullSourceName
- * full source name
- * @return URI of source
- */
- public URI getTargetSourceUri(final String fullSourceName) {
- return getTestProjectManager().createTestSourceUri(fullSourceName);
- }
-
- /**
- * Returns a list of all kernel source file names that this test will require.
- * This can be overridden to extend or replace the returned list.
- *
- * @return list of all required kernel source file names
- */
- protected List getRequiredSourceFileNames() {
- List requiredSources = new LinkedList();
- String testSourceFileName = getTestSourceFileName();
- if (testSourceFileName != null && testSourceFileName.length() > 0) {
- requiredSources.add(testSourceFileName);
- }
- return requiredSources;
- }
-
- /**
- * Registers all required sources for this test.
- * This method can be overridden to register other required source files.
- */
- protected void registerRequiredSources() {
- addSourcesToWorkspace(getRequiredSourceFileNames());
- }
-
- /**
- * Non-static instance set up before all tests.
- */
- @BeforeAll
- public final void setUp() {
- synchronized (testInformationMap) {
- if (!testInformationMap.containsKey(this.getClass())) {
- testInformationMap.put(this.getClass(), new TestInformation());
- beforeAllTests();
- }
- }
- }
-
- /**
- * Non-static instance tear down after all tests.
- */
- @AfterAll
- public final void tearDown() {
- synchronized (testInformationMap) {
- afterAllTests();
- ExtensionRegistryMock.assertUnMocked();
- ServiceMock.assertAllMocksRemoved();
- testInformationMap.remove(this.getClass());
- }
- }
-
- /**
- * This method prepares the test environment for a test. It is called by the JUnit framework before each test.
- * If it is run the first time, it calls the beforeClass method first. Do not call this method manually!
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
- @Before
- public final void before() {
- beforeEachTest();
- }
-
- /**
- * This method cleans up the test environment after a test. It is called by the JUnit framework after each test.
- * If no more tests are to be run, it calls the afterClass method. Do not call this method manually!
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
- @After
- public final void after() {
- afterEachTest();
- }
-
- /**
- * Prepares the test class after the test class has been instantiated. This method can be used to setup the test class before any test is run.
- * Do not use JUnit annotation.
- * Exceptions are wrapped and handed over to the JUnit framework.
- */
- protected void beforeAllTests() {
- // check method annotations to ensure test framework policies
- System.setProperty(HIGH_LATENCY_PROPERTY, Boolean.FALSE.toString());
- System.setProperty(LANGUAGE_VERSION_CACHING_PROPERTY, Boolean.FALSE.toString());
- enforceAnnotationPolicies();
- getTestProjectManager().setup(ImmutableList. of());
- registerRequiredSources();
- getTestProjectManager().build();
- }
-
- /**
- * After the last task has run but before the test class instance has been garbage collected, this method is called to clean up the test environment.
- * Do not use JUnit annotation.
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
- protected void afterAllTests() {
- getTestProjectManager().teardown();
- System.clearProperty(LANGUAGE_VERSION_CACHING_PROPERTY);
- System.setProperty(HIGH_LATENCY_PROPERTY, Boolean.TRUE.toString());
- }
-
- /**
- * Prepares for the next test. This method can be used to (re-)initialize the test environment before a (next) test is run. Resource allocations must be dealt
- * with in {@link afterEachTest}.
- * Do not use JUnit annotation.
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
- @SuppressWarnings("PMD.EmptyMethodInAbstractClassShouldBeAbstract")
- protected void beforeEachTest() {
- // empty
- }
-
- /**
- * Called after each test to clean up initializations done in {@link beforeEachTest}.
- * Do not use JUnit annotation.
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
- @SuppressWarnings("PMD.EmptyMethodInAbstractClassShouldBeAbstract")
- protected void afterEachTest() {
- // empty
- }
-
- /**
- * Registers a source that is required by the test class.
- * The source will be removed from the system when {@link afterAllTests} is called.
- * All exceptions are wrapped and handed over to the JUnit framework.
- *
- * @param sourceFileName
- * the name of the file where the source is located, and where the content of the source shall be written to. This is the source name available
- * during the test.
- */
- protected void addSourceToWorkspace(final String sourceFileName) {
- addSourceToWorkspace(sourceFileName, getResourceContent(sourceFileName));
- }
-
- /**
- * Registers a kernel source that is required by the test class.
- * The source will be removed from the system when {@link afterAllTests} is called.
- * All exceptions are wrapped and handed over to the JUnit framework.
- *
- * @param sourceFileName
- * the name of the file where the content of the source shall be written to. This is the source name available
- * during the test.
- * @param sourceContent
- * the content of the source that shall be written to the file in workspace.
- */
- protected void addKernelSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- addSourceToWorkspace(sourceFileName, sourceContent.toString());
- }
-
- /**
- * Registers a customer source that is required by the test class.
- * The source will be removed from the system when {@link afterAllTests} is called.
- * All exceptions are wrapped and handed over to the JUnit framework.
- *
- * @param sourceFileName
- * the name of the file where the content of the source shall be written to. This is the source name available
- * during the test.
- * @param sourceContent
- * the content of the source that shall be written to the file in workspace.
- */
- protected void addCustomerSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- addSourceToWorkspace(CUSTOMER_SOURCE_PREFIX.concat(sourceFileName), sourceContent.toString());
- }
-
- /**
- * Registers a source that is required by the test class.
- * The source will be removed from the system when {@link afterAllTests} is called.
- * All exceptions are wrapped and handed over to the JUnit framework.
- *
- * @param sourceFileName
- * the name of the file where the content of the source shall be written to. This is the source name available
- * during the test.
- * @param sourceContent
- * the content of the source that shall be written to the file in workspace.
- */
- private void addSourceToWorkspace(final String sourceFileName, final String sourceContent) {
- createTestSource(sourceFileName, sourceContent);
- }
-
- /**
- * Returns the string contents of the loaded resource with the given name.
- *
- * @param sourceFileName
- * the file name
- * @return the string contents of the loaded resource
- */
- protected String getResourceContent(final String sourceFileName) {
- return TestSource.getResourceContent(this.getClass(), sourceFileName);
- }
-
- /**
- * Registers a set of sources that is required by the test class.
- * The sources will be removed from the system when {@link afterAllTests} is called.
- * All exceptions are wrapped and handed over to the JUnit framework.
- *
- * @param sourceFileNames
- * the names of the files where the sources are located, and where the content of the sources shall be written to.
- */
- private void addSourcesToWorkspace(final List sourceFileNames) {
- try {
- new WorkspaceModifyOperation() {
- @Override
- protected void execute(final IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
- for (String sourceFileName : sourceFileNames) {
- addSourceToWorkspace(sourceFileName);
- }
- }
- }.run(new NullProgressMonitor());
- } catch (InvocationTargetException e) {
- throw new WrappedException("failed adding sources to workspace", e);
- } catch (InterruptedException e) {
- throw new WrappedException("adding sources to workspace interrupted", e);
- }
- }
-
- protected Collection extends TestSource> getTestSources() {
- return getTestProjectManager().getTestSources();
- }
-
- /**
- * Returns the kernel {@link TestSource} for the given sourceFileName.
- *
- * @param sourceFileName
- * the file name of the {@link TestSource}
- * @return the {@link TestSource} for the given sourceFileName
- */
- protected XtextTestSource getTestSource(final String sourceFileName) {
- return (XtextTestSource) getTestProjectManager().getTestSource(sourceFileName);
- }
-
- /**
- * Returns the kernel {@link TestSource} for this test class.
- *
- * @return the {@link TestSource} for this test class
- */
- protected TestSource getTestSource() {
- return getTestProjectManager().getTestSource(getTestSourceFileName());
- }
-
- /**
- * Get the name of the main test source file.
- *
- * @return the file name of the main test source file
- */
- protected abstract String getTestSourceFileName();
-
- /**
- * The default implementation returns the name of the test class for the model name of the test source.
- * A test class needs to override this, if the name of the main test source model differs from the default.
- *
- * @return the name of the main test source model
- */
- protected String getTestSourceModelName() {
- return this.getClass().getSimpleName();
- }
-
- /**
- * Goes through all methods of this object and checks the annotations.
- *
- * Methods with a {@link @BeforeClass} or {@link @AfterClass} annotation will cause an exception to be thrown. For that purpose, use the {@link
- * beforeAllTests()} and {@link afterAllTests()} methods only.
- *
- */
- private void enforceAnnotationPolicies() {
- for (Method method : this.getClass().getMethods()) {
- // use this policy to not allow BeforeClass or AfterClass annotations.
- if (method.isAnnotationPresent(BeforeClass.class) || method.isAnnotationPresent(AfterClass.class)) {
- throw new IllegalJUnitAnnotation();
- }
- // use this policy to not allow Before or After annotations in subclasses.
- // if (!method.getDeclaringClass().equals(AbstractXtextTest.class) && (method.isAnnotationPresent(Before.class) ||
- // method.isAnnotationPresent(After.class))) {
- // throw new
- // IllegalJUnitAnnotation("Invalid annotation found. Before and After annotations are not permitted when using the AbstractXtextTest framework. Override
- // the methods 'before' and 'after' instead.");
- // }
- }
- }
-
- /**
- * Wait for validation jobs to finish.
- */
- protected void waitForValidation() {
- waitForJobsOfFamily(org.eclipse.xtext.ui.editor.validation.ValidationJob.XTEXT_VALIDATION_FAMILY);
- }
-
- /**
- * Wait for jobs of a given family to finish.
- *
- * @param family
- * to wait for.
- */
- protected void waitForJobsOfFamily(final Object family) {
- getTestUtil().waitForJobsOfFamily(family);
- }
-
- /**
- * Wait for synchronization jobs on opening/closing the editor.
- *
- * @param editor
- * editor part
- */
- protected void waitForEditorJobs(final IEditorPart editor) {
- getTestUtil().waitForEditorJobs(editor);
- }
-
- /**
- * Wait for jobs of a given family to appear. A {@code null} family will
- * cause this to wait for any job.
- *
- * @param family
- * to wait for, may be {@code null}
- * @param timeout
- * ms to wait for.
- */
- protected void waitForJobOfFamilyToAppear(final Object family, final long timeout) {
- final long timeLimit = System.currentTimeMillis() + timeout;
- do {
- if (Job.getJobManager().find(family).length > 0) {
- return;
- }
- } while (System.currentTimeMillis() < timeLimit);
- }
-
- /**
- * Returns the test information for the current test class.
- *
- * @return information for the current test class
- */
- protected TestInformation getTestInformation() {
- synchronized (testInformationMap) {
- return testInformationMap.get(this.getClass());
- }
- }
-
- /**
- * Create a test source for testing from an existing file.
- *
- * @param sourceFileName
- * file name for source
- * @param content
- * content of source
- * @return a new {@link TestSource} with the given parameters
- */
-
- protected TestSource createTestSource(final String sourceFileName, final String content) {
- TestSource testSource = new TestSource(sourceFileName, content);
- getTestProjectManager().addSourceToProject(testSource);
- return testSource;
- }
-
- /**
- * Get the test class utility for this test. The minimum functionality is given by
- * AbstractTestUtil, which does not require that any methods be overridden. Tests
- * that require more than this minimal functionality must override this method.
- *
- * This method is expected to always return the same instance, even when invoked on different instances of the test class. This is because the associated
- * {@link ITestProjectManager} is stateful and required by {@link #beforeAllTests()}, {@link #afterAllTests()}, and {@link #getTestSources()}.
- *
- * @return the test class utility for this test.
- */
- protected abstract AbstractTestUtil getTestUtil();
-
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextMarkerBasedTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextMarkerBasedTest.java
deleted file mode 100644
index 8d21509bc..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextMarkerBasedTest.java
+++ /dev/null
@@ -1,656 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.CrossReference;
-import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.xbase.lib.Procedures;
-import org.junit.Assert;
-
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-
-
-/**
- * Abstract class that supports Xtend based test implementations to use markers in the test sources.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractXtextMarkerBasedTest extends AbstractXtextTest {
-
- private static final String INVALID_TEST_CONFIGURATION = "Invalid test configuration. Missing org.eclipse.xtend.lib in MANIFEST.MF in this plugin?"; //$NON-NLS-1$
- private static final String LINE_BREAK = "\n";
- private static final String MARKER_START_GUARD = "##";
- private static final String MARKER_END_GUARD = "#";
- private static final String SPLITTING_LINE = "-------------------------------------------------\n";
- protected static final Pattern PATTERN = Pattern.compile(MARKER_START_GUARD + "(\\d+)" + MARKER_END_GUARD);
-
- /** The tag id. */
- private int localMarkerIdCounter;
-
- private final Map assertions = Maps.newHashMap();
- private final SortedMap errorsOnPosition = Maps.newTreeMap();
- /** Used Tags to find Duplicates. */
- private final Set usedTags = Sets.newHashSet();
-
- /**
- * Indicates if a testing source is a kernel or customer source.
- */
- protected enum TestSourceType {
- CLIENT_ALL,
- CLIENT_CUSTOMER
- }
-
- // --------------------------------------------------------------------------
- // AbstractModelAssertion
- // --------------------------------------------------------------------------
-
- /**
- * Interface for testing assertions on a given source position.
- */
- protected abstract class AbstractModelAssertion implements Procedures.Procedure2 {
-
- @Override
- public abstract void apply(EObject semanticModel, Integer pos);
-
- }
-
- // --------------------------------------------------------------------------
- // Methods of testing framework
- // --------------------------------------------------------------------------
-
- @Override
- protected void afterEachTest() {
- getMarkerTagsInfo().clearTags(localMarkerIdCounter);
- super.afterEachTest();
- assertions.clear();
- usedTags.clear();
- errorsOnPosition.clear();
- }
-
- @Override
- protected void beforeEachTest() {
- localMarkerIdCounter = 0;
- super.beforeEachTest();
- Assert.assertFalse(INVALID_TEST_CONFIGURATION, getMarkerTagsInfo().isInvalidTestClass());
- }
-
- // --------------------------------------------------------------------------
- // Methods to be used by the actual testing classes
- // --------------------------------------------------------------------------
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void addKernelSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- String processedContent = processContentAndRegisterOffsets(sourceFileName, sourceContent);
- super.addKernelSourceToWorkspace(sourceFileName, processedContent);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void addCustomerSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- String processedContent = processContentAndRegisterOffsets(CUSTOMER_SOURCE_PREFIX + sourceFileName, sourceContent);
- super.addCustomerSourceToWorkspace(sourceFileName, processedContent);
- }
-
- /**
- * Removes tags and stores them in the test info object.
- *
- * @param sourceFileName
- * Source file name, must not be {@code null}
- * @param sourceContent
- * Content of the test source (may contain tags), must not be {@code null}
- * @return Content without tags, never {@code null}
- */
- private String processContentAndRegisterOffsets(final String sourceFileName, final CharSequence sourceContent) {
- Map offsets = Maps.newHashMap();
- String content = removeMarkersFromContent(sourceContent, offsets);
- for (Entry tag : offsets.entrySet()) {
- getMarkerTagsInfo().registerRequiredSourceTag(tag.getKey(), sourceFileName, tag.getValue());
- }
- return content;
- }
-
- /**
- * Removes the Xtend markers from a source.
- *
- * @param sourceContent
- * the source content, not {@code null}
- * @param tagToOffset
- * Map to be populated with tag to offset pairs, must not be {@code null}
- * @return the content without markers, never {@code null}
- */
- private String removeMarkersFromContent(final CharSequence sourceContent, final Map tagToOffset) {
- StringBuffer withoutMarkers = new StringBuffer(sourceContent.length());
- Matcher m = PATTERN.matcher(sourceContent);
- while (m.find()) {
- m.appendReplacement(withoutMarkers, "");
- tagToOffset.put(Integer.parseInt(m.group(1)), withoutMarkers.length());
- }
- m.appendTail(withoutMarkers);
- return withoutMarkers.toString();
- }
-
- /**
- * Returns the model for the given source name and string.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- * @return Model element for the parsed source, may be {@code null}
- */
- protected EObject getModel(final String sourceFileName, final CharSequence sourceContent) {
- Map offsets = Maps.newHashMap();
- String content = removeMarkersFromContent(sourceContent, offsets);
- EObject root = null;
- try {
- root = getXtextTestUtil().getModel(sourceFileName, content);
- INode node = NodeModelUtils.getNode(root);
- for (Entry tag : offsets.entrySet()) {
- INode leafNode = NodeModelUtils.findLeafNodeAtOffset(node, tag.getValue() + 1);
- EObject context = NodeModelUtils.findActualSemanticObjectFor(leafNode);
- // Search for cross reference
- CrossReference crossReference = null;
- while (leafNode != null) {
- if (leafNode.getGrammarElement() instanceof CrossReference) {
- crossReference = (CrossReference) leafNode.getGrammarElement();
- break;
- }
- leafNode = leafNode.getParent();
- }
- getMarkerTagsInfo().registerLocalTag(tag.getKey(), context, crossReference);
- }
- } catch (IOException e) {
- fail("Exception while creating model from input string: " + e.getMessage()); //$NON-NLS-1$
- }
- return root;
- }
-
- /**
- * Does the same as get model, but returns void.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content
- * @param sourceContent
- * source
- */
- protected void registerModel(final String sourceFileName, final CharSequence sourceContent) {
- getModel(sourceFileName, sourceContent);
- }
-
- /**
- * Validate a kernel source given by a file name and content.
- * All not expected diagnostics are ignored.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, not {@code null}
- * @param sourceContent
- * source, not {@code null}
- */
- protected void validateKernelSource(final String sourceFileName, final CharSequence sourceContent) {
- validate(sourceFileName, TestSourceType.CLIENT_ALL, sourceContent);
- }
-
- /**
- * Validate a customer source given by a file name and content.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, not {@code null}
- * @param sourceContent
- * source, not {@code null}
- */
- protected void validateCustomerSource(final String sourceFileName, final CharSequence sourceContent) {
- validate(sourceFileName, TestSourceType.CLIENT_CUSTOMER, sourceContent);
- }
-
- // --------------------------------------------------------------------------
- // Methods to be used by more specific abstract classes
- // --------------------------------------------------------------------------
-
- /**
- * Add assertion to the list of assertions and return the corresponding string marker.
- *
- * @param assertion
- * assertion to be added, not {@code null}
- * @return
- * string marker corresponding to the added assertion
- */
- protected String addAssertion(final AbstractModelAssertion assertion) {
- // Assertions are given a local tag as they are local markers affecting and declared in only one source
- Integer markerId = getTag();
- assertions.put(markerId, assertion);
- return mark(markerId);
- }
-
- /**
- * Creates a mark with the given id. Use this method in tests to insert marks.
- *
- * If the given mark id is 0 then it means that the test was not well configured. All the id-s that are generated by {@link #getTag} start with 1, all the
- * global ids start with {@value com.avaloq.tools.asmd.testbase.scoping.TagCompilationParticipant#COUNTER_BASE}. Since it is unlikely to get local ids wrong,
- * the most common reason for global ids to be wrong is that they were not initialized. Global ids get initialized with active annotation
- * {@link com.avaloq.tools.asmd.testbase.scoping.Tag} that executes {@link com.avaloq.tools.asmd.testbase.scoping.TagCompilationParticipant}. Active
- * annotations do not get executed if {@code org.eclipse.xtend.lib} is missing in {@code MANIFEST.MF}. Thus we report this common mistake to the user via an
- * assertion.
- *
- *
- * @param id
- * Mark id
- * @return Mark text to be inserted in the source file, never {@code null}
- */
- protected String mark(final int id) {
- Assert.assertFalse("Tag with " + id + " used to mark more than one location.", usedTags.contains(id)); //$NON-NLS-1$ //$NON-NLS-2$
- usedTags.add(id);
- if (id < 1) {
- getMarkerTagsInfo().setTestClassInvalid();
- throw new AssertionError(INVALID_TEST_CONFIGURATION);
- }
- return MARKER_START_GUARD + id + MARKER_END_GUARD;
- }
-
- /**
- * Memorize an error that was detected during the validation of the current testing file.
- *
- * @param position
- * position of the error in file, not {@code null}
- * @param error
- * string with error, not {@code null}
- */
- protected void memorizeErrorOnPosition(final Integer position, final String error) {
- if (!errorsOnPosition.containsKey(position)) {
- errorsOnPosition.put(position, new StringBuilder());
- }
- errorsOnPosition.get(position).append(error);
- }
-
- /**
- * Processes all the inserted markers in a given source and creates a new {@link XtextTestSource} without the markers.
- *
- * @param sourceFileName
- * the name of the source, may be {@code null}
- * @param sourceType
- * the type of the source, may be {@code null}
- * @param sourceContent
- * the content of the source, must not be {@code null}
- * @return the {@link XtextTestSource} created.
- */
- protected XtextTestSource processMarkers(final String sourceFileName, final TestSourceType sourceType, final CharSequence sourceContent) {
- StringBuilder withoutMarkers = new StringBuilder();
- final Multimap positionToAssertionMap = LinkedHashMultimap.create();
- Matcher m = PATTERN.matcher(sourceContent);
- int lastEnd = 0;
- while (m.find()) {
- withoutMarkers.append(sourceContent.subSequence(lastEnd, m.start()));
- lastEnd = m.end();
- int markerId = Integer.parseInt(m.group(1));
- // save the position of the marker only if we are dealing with an assertion marker
- AbstractModelAssertion assertionMarker = assertions.get(markerId);
- if (assertionMarker != null) {
- positionToAssertionMap.put(withoutMarkers.length(), assertionMarker);
- }
- }
- // Add the rest part of input string
- withoutMarkers.append(sourceContent.subSequence(lastEnd, sourceContent.length()));
-
- // Calculate source name
- String fullSourceFileName = "";
- if (sourceType == TestSourceType.CLIENT_CUSTOMER) {
- fullSourceFileName = CUSTOMER_SOURCE_PREFIX;
- }
- fullSourceFileName = fullSourceFileName.concat(sourceFileName);
-
- EObject semanticModel;
- String withoutMarkersAsString = withoutMarkers.toString();
- XtextTestSource testSource = createTestSource(fullSourceFileName, withoutMarkersAsString);
- semanticModel = testSource.getModel();
- beforeApplyAssertions(testSource);
- // Run validations on markers
- for (Map.Entry entry : positionToAssertionMap.entries()) {
- entry.getValue().apply(semanticModel, entry.getKey());
- }
- return testSource;
- }
-
- /**
- * Validate a source given by a file name and content.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, not {@code null}
- * @param sourceType
- * defines if the source is a kernel or customer source, not {@code null}
- * @param sourceContent
- * source, not {@code null}
- */
- protected void validate(final String sourceFileName, final TestSourceType sourceType, final CharSequence sourceContent) {
- XtextTestSource testSource = processMarkers(sourceFileName, sourceType, sourceContent);
- processErrorsFound(testSource.getContent());
- afterValidate();
- }
-
- /**
- * Processes all the diagnostics in a given source.
- *
- * @param sourceWithoutMarkers
- * the source to process, must not be {@code null}
- */
- protected void processErrorsFound(final String sourceWithoutMarkers) {
- if (!errorsOnPosition.isEmpty()) {
- // CHECKSTYLE:OFF MagicNumber
- StringBuilder sb = new StringBuilder(100);
- // CHECKSTYLE:ON
- sb.append(memorizedErrorsToString(sourceWithoutMarkers));
- sb.append(SPLITTING_LINE);
- sb.append("List of all found diagnostics:\n");
- sb.append(getAdditionalErrorMessageInformation());
- assertEquals("Errors found. Consider compare view.", sourceWithoutMarkers, sb.toString());
- }
- }
-
- /**
- * Inject memorized errors into the input file on positions where they were detected.
- *
- * @param source
- * text of the input testing source, not {@code null}
- * @return
- * input testing source with injected errors, never {@code null}
- */
- private String memorizedErrorsToString(final String source) {
- StringBuilder result = new StringBuilder(120);
- StringBuilder errorBuffer = new StringBuilder(120);
- // Sort positions
- List positions = Lists.newArrayList(errorsOnPosition.keySet());
-
- int posIdx = 0;
- int sourceIdx = 0;
-
- while (sourceIdx < source.length()) {
- int lineBreakIndex = source.indexOf('\n', sourceIdx);
- if (lineBreakIndex < 0) {
- lineBreakIndex = source.length();
- }
- while (posIdx < positions.size() && positions.get(posIdx) < lineBreakIndex) {
- int nextPos = positions.get(posIdx);
- result.append(source.substring(sourceIdx, nextPos));
- result.append("');
- // Add error message to buffer
- errorBuffer.append(SPLITTING_LINE);
- errorBuffer.append("FAILURE ");
- errorBuffer.append(posIdx + 1);
- errorBuffer.append(": ");
- errorBuffer.append(errorsOnPosition.get(nextPos));
- sourceIdx = nextPos;
- posIdx++;
- }
- if (errorBuffer.length() > 0) {
- errorBuffer.append(SPLITTING_LINE);
- }
- result.append(source.substring(sourceIdx, lineBreakIndex));
- result.append(errorBuffer);
- errorBuffer = new StringBuilder();
- result.append(LINE_BREAK);
- sourceIdx = lineBreakIndex + 1;
- }
- result.append(source.substring(sourceIdx));
- result.append(errorBuffer);
- return result.toString();
- }
-
- /**
- * Searches an object for the given tag. First checks local tags. If not found then searches this tag in the required sources.
- *
- * @param tag
- * Tag
- * @return EObject or {@code null}
- */
- protected EObject getObjectForTag(final int tag) {
- EObject object = getMarkerTagsInfo().getModel(tag);
- if (object == null) {
- // Not in source under test
- String sourceName = getMarkerTagsInfo().getSource(tag);
- if (sourceName != null) {
- INode node = NodeModelUtils.findActualNodeFor(getTestSource(sourceName).getModel());
- INode leafNode = NodeModelUtils.findLeafNodeAtOffset(node, getMarkerTagsInfo().getOffset(tag));
- object = NodeModelUtils.findActualSemanticObjectFor(leafNode);
- }
- }
- assertNotNull("Tag " + tag + " should mark an object. Use «mark(TAG)» in a code snippet.", object); //$NON-NLS-1$//$NON-NLS-2$
- return object;
- }
-
- /**
- * Return the offset for the given tag.
- *
- * @param tag
- * The tag for which to find the offset
- * @return the offset found or {@code null} if the given tag is not marking an object
- */
- protected Integer getOffsetForTag(final int tag) {
- Integer offset = getMarkerTagsInfo().getOffset(tag);
- assertNotNull("Tag " + tag + " should mark an object. Use «mark(TAG)» in a code snippet.", offset); //$NON-NLS-1$//$NON-NLS-2$
- return offset;
- }
-
- /**
- * Generate a unique tag id.
- *
- * Use this method for local tags only. Global tags must use @Tag annotation to ensure the same value over multiple instances of the test class.
- *
- *
- * @return Tag id
- */
- public int getTag() {
- localMarkerIdCounter++;
- assertTrue("Too many local tags. Must be less than " + TagCompilationParticipant.COUNTER_BASE //$NON-NLS-1$
- + " per test method", localMarkerIdCounter < TagCompilationParticipant.COUNTER_BASE); //$NON-NLS-1$
- return localMarkerIdCounter;
- }
-
- /**
- * Return the {@link MarkerTagsInfo} associated to one test class.
- *
- * @return the associated {@link MarkerTagsInfo}
- */
- protected MarkerTagsInfo getMarkerTagsInfo() {
- MarkerTagsInfo info = (MarkerTagsInfo) getTestInformation().getTestObject(MarkerTagsInfo.class);
- if (info == null) {
- info = new MarkerTagsInfo();
- getTestInformation().putTestObject(MarkerTagsInfo.class, info);
- }
- return info;
- }
-
- /**
- * This class preserves information about tags in the required sources
- * for all tests within one test class. Tags for current test are also stored here.
- * One may prefer in the future to be able to clean tags for the current test after the test.
- */
- @SuppressWarnings("PMD.PublicMemberInNonPublicType") // Public methods needed for subclass access in other packages
- protected class MarkerTagsInfo {
-
- // For sources under test
- /** The tag to model. */
- private final Map tagToModel = Maps.newHashMap();
-
- /** The tag to cross reference. */
- private final Map tagToCrossReference = Maps.newHashMap();
-
- // For sources added early (only object referencing, no need to search cross references)
- /** The tag to source. */
- private final Map tagToSource = Maps.newHashMap();
-
- /** The tag to offset. */
- private final Map tagToOffset = Maps.newHashMap();
-
- private boolean invalidTestClass;
-
- /**
- * Registers one tag for the source under test.
- * This source is actually used for testing and we need both: outgoing cross references as well as declared elements.
- *
- * @param tag
- * New id for the tag
- * @param context
- * Current object that will correspond to this tag
- * @param crossReference
- * the cross reference {@code null} for declaration or the corresponding cross reference in the grammar for a reference
- */
- public void registerLocalTag(final int tag, final EObject context, final CrossReference crossReference) {
- tagToModel.put(tag, context);
- if (crossReference != null) {
- tagToCrossReference.put(tag, crossReference);
- }
- }
-
- /**
- * Register a tag in the required source. Only declarations are supported.
- *
- * @param tag
- * New tag (must be unique)
- * @param sourceName
- * Source name
- * @param offset
- * Offset within the source
- */
- public void registerRequiredSourceTag(final int tag, final String sourceName, final int offset) {
- tagToSource.put(tag, sourceName);
- tagToOffset.put(tag, offset);
- }
-
- /**
- * Returns the context model element for local tags.
- *
- * @param tag
- * Tag
- * @return Model element
- */
- public EObject getModel(final int tag) {
- return tagToModel.get(tag);
- }
-
- /**
- * Returns cross references for local tags.
- *
- * @param tag
- * Tag
- * @return Cross reference grammar element
- */
- public CrossReference getCrossReference(final int tag) {
- return tagToCrossReference.get(tag);
- }
-
- /**
- * Returns source name for global tag.
- *
- * @param tag
- * Tag
- * @return Source name
- */
- public String getSource(final int tag) {
- return tagToSource.get(tag);
- }
-
- /**
- * Returns offsets for global tags.
- *
- * @param tag
- * Tag
- * @return Offset
- */
- public Integer getOffset(final int tag) {
- return tagToOffset.get(tag);
- }
-
- /**
- * Clear local tags from current test. Clears all tags up to the id passed, but not outside the range reserved for local tags.
- *
- * @param maxId
- * the tag id
- */
- public void clearTags(final long maxId) {
- for (int i = 1; i <= Math.min(maxId, TagCompilationParticipant.COUNTER_BASE - 1); i++) {
- tagToCrossReference.remove(i);
- tagToModel.remove(i);
- tagToOffset.remove(i);
- tagToSource.remove(i);
- }
- }
-
- public boolean isInvalidTestClass() {
- return invalidTestClass;
- }
-
- /**
- * Marks the current test class as invalid. All tests within this class will report same error.
- */
- public void setTestClassInvalid() {
- this.invalidTestClass = true;
- }
- }
-
- /**
- * Before apply assertions.
- *
- * @param testSource
- * the test source, not {@code null}
- */
- @SuppressWarnings("PMD.UnusedFormalParameter")
- protected void beforeApplyAssertions(final XtextTestSource testSource) {
- }
-
- /**
- * Gets additional error message information.
- *
- * @return additional error message information, never {@code null}
- */
- protected String getAdditionalErrorMessageInformation() {
- return "";
- }
-
- /**
- * Returns an unmodifiable view of the tags generated by {@link getTag()}.
- *
- * @return the unmodifiable view of the {@link #usedTags} set
- */
- public Set getUsedTagsItems() {
- return Collections.unmodifiableSet(usedTags);
- }
-
- /**
- * Processing after validations.
- */
- protected void afterValidate() {
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTest.java
deleted file mode 100644
index 2ad786cb6..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.resource.XtextResource;
-
-
-/**
- * Provides a test class specific custom test framework for xtext languages. Provides a language specific {@link AbstractXtextTestUtil}.
- * All exceptions are wrapped and handed over to the JUnit framework.
- */
-public abstract class AbstractXtextTest extends AbstractTest {
-
- /**
- * Returns a language specific {@link AbstractXtextTestUtil}. Test classes specify which TestUtil to use by implementing this method.
- *
- * @return a language specific {@link AbstractXtextTestUtil}
- */
- protected abstract AbstractXtextTestUtil getXtextTestUtil();
-
- @Override
- protected final AbstractXtextTestUtil getTestUtil() {
- return getXtextTestUtil();
- }
-
- @Override
- protected XtextTestSource getTestSource() {
- return (XtextTestSource) super.getTestSource();
- }
-
- @Override
- protected XtextTestSource createTestSource(final String sourceFileName, final String content) {
- XtextTestSource testSource = new XtextTestSource(sourceFileName, content, getTestUtil().getResourceSet());
- getTestProjectManager().addSourceToProject(testSource);
- return testSource;
- }
-
- /**
- * The default implementation returns the name of the source model calling {@link getTestSourceModelName} and adds the default file extension for the grammar
- * of this test. A test class needs to override this, if the name of the main test source file differs from the default.
- *
- * @return the name of the main test source file
- */
- @Override
- protected String getTestSourceFileName() {
- return this.getTestSourceModelName() + '.' + getXtextTestUtil().getFileExtension();
- }
-
- /**
- * Returns the xtext resource loaded by {@link loadPrimarySource}.
- *
- * @return
- * the xtext resource loaded by {@link loadPrimarySource}.
- */
- protected XtextResource getXtextTestResource() {
- return getTestSource(getTestSourceFileName()).getXtextResource();
- }
-
- /**
- * Returns the semantic model from the xtext resource loaded by {@link loadPrimarySource}.
- *
- * @return
- * the semantic model from the xtext resource loaded by {@link loadPrimarySource}.
- */
- protected EObject getSemanticModel() {
- return getXtextTestResource().getParseResult().getRootASTElement();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void addKernelSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- refreshSourceContent(sourceFileName, sourceContent.toString());
- super.addKernelSourceToWorkspace(sourceFileName, sourceContent);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void addCustomerSourceToWorkspace(final String sourceFileName, final CharSequence sourceContent) {
- refreshSourceContent(CUSTOMER_SOURCE_PREFIX + sourceFileName, sourceContent.toString());
- super.addCustomerSourceToWorkspace(sourceFileName, sourceContent);
- }
-
- /**
- * Refresh the source content if it had already been added previously to the workspace.
- *
- * @param sourceFileName
- * the source file name
- * @param content
- * the content
- */
- private void refreshSourceContent(final String sourceFileName, final String content) {
- XtextTestSource xtextTestSource = getTestSource(sourceFileName);
- if (xtextTestSource != null) {
- xtextTestSource.setContent(content);
- }
- }
-
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTestUtil.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTestUtil.java
deleted file mode 100644
index b6be5ddae..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/AbstractXtextTestUtil.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test; //NOPMD
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.emf.common.util.Diagnostic;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.common.util.WrappedException;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.util.Diagnostician;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.xtext.diagnostics.AbstractDiagnostic;
-import org.eclipse.xtext.nodemodel.ICompositeNode;
-import org.eclipse.xtext.nodemodel.ILeafNode;
-import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.resource.FileExtensionProvider;
-import org.eclipse.xtext.resource.XtextResource;
-import org.eclipse.xtext.resource.XtextResourceSet;
-import org.eclipse.xtext.serializer.ISerializer;
-import org.eclipse.xtext.ui.editor.model.IXtextDocument;
-import org.eclipse.xtext.ui.testing.util.ResourceLoadHelper;
-import org.eclipse.xtext.util.StringInputStream;
-import org.eclipse.xtext.validation.AbstractValidationDiagnostic;
-import org.eclipse.xtext.validation.FeatureBasedDiagnostic;
-import org.eclipse.xtext.validation.Issue;
-import org.eclipse.xtext.validation.RangeBasedDiagnostic;
-import org.eclipse.xtext.xbase.lib.Pair;
-
-import com.avaloq.tools.ddk.xtext.test.model.ModelUtil;
-import com.avaloq.tools.ddk.xtext.test.validation.ValidationHelper;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.inject.Injector;
-
-
-/**
- * Utility for Xtext tests.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractXtextTestUtil extends AbstractTestUtil implements ResourceLoadHelper /* , IInjectorProvider */ {
-
- private final ModelUtil modelUtil = new ModelUtil();
- private final ValidationHelper validationHelper = new ValidationHelper();
-
- private static final String ERROR = "ERROR %d: ";
- private static final String ERROR_MARKER = "";
- private static final String SPLITTER = "------------------------\n";
-
- /**
- * Returns the current injector used in this plugin.
- *
- * @return the current injector for this language
- * @deprecated this method should be implemented only and not called directly; use {@link #get(Class)} instead
- */
- @Deprecated
- protected abstract Injector getInjector();
-
- /**
- * Parses the given instance and returns the model representation.
- *
- * @param sourceFileName
- * to associate the source with, used to determine the source content type
- * @param content
- * String representation of the content to parse
- * @return model representation
- * @throws IOException
- * may be thrown if the instance cannot be parsed
- */
- public final EObject getModel(final String sourceFileName, final String content) throws IOException {
- XtextResource resource = getResource(getTestProjectManager().createTestSourceUri(sourceFileName), content);
- return resource.getParseResult().getRootASTElement();
- }
-
- /**
- * Creates a resource with the given URI and content.
- *
- * @param uri
- * to associate the model with
- * @param content
- * String representation of the create a resource from
- * @return {@link XtextResource} created
- * @throws IOException
- * may be thrown when trying to load the given content
- */
- protected final XtextResource getResource(final URI uri, final String content) throws IOException {
- StringInputStream instanceStream = new StringInputStream(content);
- XtextResourceSet rs = getResourceSet();
- XtextResource resource = (XtextResource) rs.createResource(uri);
- rs.getResources().add(resource);
- resource.load(instanceStream, null);
- EcoreUtil.resolveAll(resource);
- return resource;
- }
-
- public String getDefaultSourceName() {
- return "mytestmodel";
- }
-
- @Override
- public XtextResource getResourceFor(final InputStream stream) {
- XtextResourceSet rs = getResourceSet();
- XtextResource resource = (XtextResource) rs.createResource(getTestProjectManager().createTestSourceUri(getDefaultSourceName() + '.' + getFileExtension()));
- rs.getResources().add(resource);
- try {
- resource.load(stream, null);
- } catch (IOException e) {
- throw new WrappedException("Could not create XtextResource from input stream.", e);
- }
- EcoreUtil.resolveAll(resource);
- return resource;
- }
-
- /**
- * Validates the provided document and returns a list of issues found.
- *
- * @param document
- * to validate
- * @return list of issues found
- */
- public List getIssues(final IXtextDocument document) {
- return validationHelper.getIssues(document);
- }
-
- /**
- * Use current injector to get a class instance.
- *
- * @param
- * Class type
- * @param clazz
- * class of object to get.
- * @return object of given class
- */
- public T get(final Class clazz) {
- return getInjector().getInstance(clazz);
- }
-
- /**
- * File extension associated with the instance's grammar.
- *
- * @return grammar specific file extension
- */
- public String getFileExtension() {
- return get(FileExtensionProvider.class).getPrimaryFileExtension();
- }
-
- /**
- * Creates a grammar specific instance of {@link XtextResourceSet}.
- *
- * @return grammar specific {@link XtextResourceSet}
- */
- public XtextResourceSet getResourceSet() {
- return get(XtextResourceSet.class);
- }
-
- /**
- * Creates a grammar specific instance of {@link ISerializer}.
- *
- * @return grammar specific {@link ISerializer}
- */
- public ISerializer getSerializer() {
- return get(ISerializer.class);
- }
-
- /**
- * Creates a grammar specific instance of {@link Diagnostician}.
- *
- * @return grammar specific {@link Diagnostician}
- */
- public Diagnostician getDiagnostician() {
- return get(Diagnostician.class);
- }
-
- /**
- * Gets the first instance of given type containing a given structural feature with given value using a given context object.
- *
- * @param
- * the generic type
- * @param context
- * the context object
- * @param type
- * the type
- * @return the first instance found or null if none found matching given criteria
- */
- public T getFirstInstanceOf(final EObject context, final Class type) {
- return modelUtil.getFirstInstanceOf(context, type);
- }
-
- /**
- * Gets the all instances of given type type having given value value on structural feature feature.
- *
- * @param
- * the generic type
- * @param context
- * the context
- * @param type
- * the type
- * @param feature
- * the feature
- * @param value
- * the value
- * @return the all instances of
- */
- public Iterable getAllInstancesOf(final EObject context, final Class type, final EStructuralFeature feature, final Object value) {
- return modelUtil.getAllInstancesOf(context, type, feature, value);
- }
-
- /**
- * Gets the first instance of given type containing a given structural feature with given value using a given context object.
- *
- * @param
- * the generic type
- * @param context
- * the context object
- * @param type
- * the type
- * @param feature
- * the structural feature
- * @param value
- * the value
- * @return the first instance found or null if none found matching given criteria
- */
- public T getFirstInstanceOf(final EObject context, final Class type, final EStructuralFeature feature, final Object value) {
- return modelUtil.getFirstInstanceOf(context, type, feature, value);
- }
-
- /**
- * Validates a source with a given name and content.
- *
- * @param sourceFileName
- * source name
- * @param sourceContent
- * content
- */
- public void validateSource(final String sourceFileName, final CharSequence sourceContent) {
- String sourceContentAsString = sourceContent.toString();
- EObject root;
- try {
- root = getModel(sourceFileName, sourceContentAsString);
- } catch (IOException e) {
- fail("Model creation failed: " + e.getMessage());
- return;
- }
-
- // Store all the validation errors
- Set errors = Sets.newHashSet();
- errors.addAll(Collections2.filter(getDiagnostician().validate(root).getChildren(), new Predicate() {
- @Override
- public boolean apply(final Diagnostic input) {
- return input.getSeverity() == Diagnostic.ERROR;
- }
- }));
-
- Map errorMessages = Maps.newHashMap();
- for (Diagnostic diagnostic : errors) {
- Pair result = processDiagnostic(diagnostic);
- if (result != null) {
- errorMessages.put(result.getKey(), result.getValue());
- }
- }
-
- // Store all the resource errors
- for (AbstractDiagnostic diagnostic : Iterables.filter(root.eResource().getErrors(), AbstractDiagnostic.class)) {
- errorMessages.put(diagnostic.getOffset(), diagnostic.getMessage());
- }
-
- List offsets = Lists.newArrayListWithExpectedSize(errorMessages.size());
- offsets.addAll(errorMessages.keySet());
- Collections.sort(offsets);
-
- // Append all the error messages to the end of the source
- int errorNumber = 1;
- ListIterator offsetIterator = offsets.listIterator();
- StringBuilder sourceContentWithErrors = new StringBuilder(sourceContent);
- while (offsetIterator.hasNext()) {
- sourceContentWithErrors.append(SPLITTER);
- sourceContentWithErrors.append(String.format(ERROR, errorNumber++));
- sourceContentWithErrors.append(errorMessages.get(offsetIterator.next())).append('\n');
- }
- if (errorNumber > 1) {
- sourceContentWithErrors.append(SPLITTER);
- }
-
- // Insert all the error markers () to the source
- // Done in inverse order to avoid the confusion with offset adjustments
- while (offsetIterator.hasPrevious()) {
- sourceContentWithErrors.insert(offsetIterator.previous(), String.format(ERROR_MARKER, --errorNumber));
- }
-
- assertEquals("Errors found: ", sourceContentAsString, sourceContentWithErrors.toString());
- }
-
- /**
- * Gets the offset and the error message for a given {@link Diagnostic}.
- *
- * @param diagnostic
- * instance of {@link Diagnostic}
- * @return
- * offset and error message
- */
- private Pair processDiagnostic(final Diagnostic diagnostic) {
- // CHECKSTYLE:OFF MagicNumber
- StringBuilder errorMessage = new StringBuilder(50);
- // CHECKSTYLE:ON
- if (diagnostic instanceof AbstractValidationDiagnostic) {
- AbstractValidationDiagnostic avd = (AbstractValidationDiagnostic) diagnostic;
- errorMessage.append("Unexpected issue found. Code '");
- errorMessage.append(avd.getIssueCode()).append("'\n");
- errorMessage.append(avd.getMessage());
- if (avd instanceof FeatureBasedDiagnostic && ((FeatureBasedDiagnostic) avd).getFeature() != null) {
- List nodes = NodeModelUtils.findNodesForFeature(avd.getSourceEObject(), ((FeatureBasedDiagnostic) avd).getFeature());
- if (nodes != null && !nodes.isEmpty()) {
- return new Pair(findFirstNonHiddenLeafNode(nodes.get(0)).getTotalOffset(), errorMessage.toString());
- }
- } else if (avd instanceof RangeBasedDiagnostic) {
- return new Pair(((RangeBasedDiagnostic) avd).getOffset(), errorMessage.toString());
- } else {
- return new Pair(NodeModelUtils.getNode(avd.getSourceEObject()).getTotalOffset(), errorMessage.toString());
- }
- }
- return null;
- }
-
- /**
- * Given an AST node, find the first non-hidden leaf node among child nodes using deep search.
- * For the sake of compatibility the method can handle LeafNodes and CompositeNodes.
- * In case of a LeafNode the result is the input node itself.
- *
- * @param node
- * entry point
- * @return
- * first node for which isHidden() is false or the original node
- */
- public INode findFirstNonHiddenLeafNode(final INode node) {
- if (node instanceof ICompositeNode) {
- for (ILeafNode leaf : node.getLeafNodes()) {
- if (!leaf.isHidden()) {
- return leaf;
- }
- }
- }
- return node;
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/contentassist/AbstractAcfContentAssistTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/contentassist/AbstractAcfContentAssistTest.java
deleted file mode 100644
index af4c27998..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/contentassist/AbstractAcfContentAssistTest.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.contentassist;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.fail;
-
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.emf.common.util.WrappedException;
-import org.eclipse.jface.text.contentassist.ICompletionProposal;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextMarkerBasedTest;
-import com.avaloq.tools.ddk.xtext.test.AcfContentAssistProcessorTestBuilder;
-import com.avaloq.tools.ddk.xtext.test.TagCompilationParticipant;
-import com.google.common.collect.Maps;
-import com.google.inject.Injector;
-
-
-/**
- * The Class AcfContentAssistTest provides utility operations for non-UI content assist
- * tests. It allows testing content assist on non-complete models step by step, as a user
- * would also use it when defining a new model in the corresponding editor.
- */
-// CHECKSTYLE:OFF
-@SuppressWarnings("nls")
-public abstract class AbstractAcfContentAssistTest extends AbstractXtextMarkerBasedTest {
- private final AcfContentAssistMarkerTagsInfo acfContentAssistMarkerTagInfo = new AcfContentAssistMarkerTagsInfo();
- private static final String AT_LEAST_ONE_PROPOSAL_WAS_PROVIDED = "At least one proposal was provided";
- private static final String EXPECTED_PROPOSALS_NOT_SET = "No expected proposals provided to check against actual proposals.";
- // CHECKSTYLE:ON
- private static final String SEPARATOR = ", ";
-
- /**
- * Creates a new completion proposal builder.
- *
- * @return the content assist processor test builder
- */
- protected AcfContentAssistProcessorTestBuilder newBuilder() {
- try {
- return new AcfContentAssistProcessorTestBuilder(getXtextTestUtil().get(Injector.class), getTestUtil());
- // CHECKSTYLE:OFF
- } catch (Exception e) {
- // CHECKSTYLE:ON
- throw new WrappedException("Could not create ContentAssistProcessorTestBuilder.", e);
- }
- }
-
- /**
- * Gets the completion proposal display strings.
- *
- * @param computedProposals
- * the computed proposals
- * @return the completion proposal display strings
- */
- private String getCompletionProposalDisplayStrings(final ICompletionProposal... computedProposals) {
- String result = "";
- for (ICompletionProposal p : computedProposals) {
- result += p.getDisplayString() + SEPARATOR; // NOPMD
- }
- if (result != null && result.length() > SEPARATOR.length()) {
- return result.substring(0, result.length() - SEPARATOR.length());
- }
- return null;
- }
-
- /**
- * Iterate over given computed completion proposals and compare resulting display string with each expected proposal text. Fail if one or more expected
- * proposals not found.
- *
- * @param computedProposals
- * the computed proposals
- * @param positiveTest
- * indicates the type of test.
- * TRUE: the test is positive and must fail if proposals not found.
- * FALSE: the test is negative and must fail if proposals found.
- * @param proposals
- * the expected proposals as display strings
- */
- private void assertCompletionProposal(final ICompletionProposal[] computedProposals, final boolean positiveTest, final String... proposals) {
- assertNotEquals(AT_LEAST_ONE_PROPOSAL_WAS_PROVIDED, proposals.length, 0);
- for (final String s : proposals) {
- boolean foundProposal = false;
- for (ICompletionProposal p : computedProposals) {
- if (s.equals(p.getDisplayString())) {
- foundProposal = true;
- break;
- }
- }
- if (positiveTest && !foundProposal) {
- fail(MessageFormat.format("Expected to find proposal \"{0}\" but could only find \"{1}\"", s, getCompletionProposalDisplayStrings(computedProposals)));
- } else if (!positiveTest && foundProposal) {
- fail(MessageFormat.format("Not expected to find proposal \"{0}\" but found \"{1}\"", s, getCompletionProposalDisplayStrings(computedProposals)));
- }
- }
- }
-
- /**
- * Iterate over given computed completion proposals and compare resulting display string with each expected proposal text. Fail if one or more expected
- * proposals not found.
- *
- * @param computedProposals
- * the computed proposals
- * @param expectedProposals
- * the expected proposals as display strings
- */
- protected void assertCompletionProposal(final ICompletionProposal[] computedProposals, final String... expectedProposals) {
- assertCompletionProposal(computedProposals, true, expectedProposals);
- }
-
- /**
- * Iterate over given computed completion proposals and compare resulting display string with each expected proposal text. Fail if one or more expected
- * proposals not found.
- *
- * @param cursorPosition
- * the cursor position within the main test source
- * @param expectedProposals
- * the expected proposals as display strings
- */
- protected void assertCompletionProposal(final int cursorPosition, final String... expectedProposals) {
- assertCompletionProposal(newBuilder().computeCompletionProposals(getTestSource(), cursorPosition), expectedProposals);
- }
-
- /**
- * Iterate over given computed completion proposals and compare resulting display string with each expected proposal text. Fail if one or more not expected
- * proposals found.
- *
- * @param computedProposals
- * the computed proposals
- * @param expectedProposals
- * the not expected proposals as display strings
- */
- protected void assertNotCompletionProposal(final ICompletionProposal[] computedProposals, final String... expectedProposals) {
- assertCompletionProposal(computedProposals, false, expectedProposals);
- }
-
- /**
- * Ensures that the list of expected proposals corresponds exactly the list of computed proposals.
- *
- * @param computedProposals
- * the computed proposals
- * @param expectedProposals
- * the expected proposals as display strings
- */
- protected void assertExactlyCompletionProposal(final ICompletionProposal[] computedProposals, final String... expectedProposals) {
- assertNotEquals(AT_LEAST_ONE_PROPOSAL_WAS_PROVIDED, expectedProposals.length, 0);
-
- Set computedProposalsAsSet = new HashSet();
- for (ICompletionProposal p : computedProposals) {
- computedProposalsAsSet.add(p.getDisplayString());
- }
-
- Set expectedProposalsAsSet = new HashSet();
- expectedProposalsAsSet.addAll(Arrays.asList(expectedProposals));
-
- if (computedProposalsAsSet.size() != expectedProposalsAsSet.size()) {
- // Calculate missing templates
- Set missing = new HashSet(expectedProposalsAsSet);
- missing.removeAll(computedProposalsAsSet);
- if (!missing.isEmpty()) {
- fail(MessageFormat.format("Proposals not found: \"{0}\".", missing.toString()));
- }
- // Calculate false positives
- Set notExpected = new HashSet(computedProposalsAsSet);
- notExpected.removeAll(expectedProposalsAsSet);
- if (!notExpected.isEmpty()) {
- fail(MessageFormat.format("Not expected: \"{0}\".", notExpected.toString()));
- }
- }
- }
-
- /**
- * Asserts the expected valid and invalid proposals based on the given registered source filename.
- *
- * @param sourceFileName
- * the filename of the test source that the proposals were to be computed from, must not be {@code null}
- */
- private void assertSourceProposals(final String sourceFileName) {
- try {
- AcfContentAssistProcessorTestBuilder builder = newBuilder().append(getTestSource(sourceFileName).getContent());
- assertFalse(EXPECTED_PROPOSALS_NOT_SET, (acfContentAssistMarkerTagInfo.expectedProposalMap.isEmpty()
- && acfContentAssistMarkerTagInfo.notExpectedProposalMap.isEmpty() && acfContentAssistMarkerTagInfo.expectedExactlyProposalMap.isEmpty()));
- for (int markerId : getUsedTagsItems()) {
- final ICompletionProposal[] proposals = builder.computeCompletionProposals(getOffsetForTag(markerId));
- if (acfContentAssistMarkerTagInfo.expectedProposalMap.containsKey(markerId)) {
- assertCompletionProposal(proposals, acfContentAssistMarkerTagInfo.expectedProposalMap.get(markerId));
- }
- if (acfContentAssistMarkerTagInfo.notExpectedProposalMap.containsKey(markerId)) {
- assertNotCompletionProposal(proposals, acfContentAssistMarkerTagInfo.notExpectedProposalMap.get(markerId));
- }
- if (acfContentAssistMarkerTagInfo.expectedExactlyProposalMap.containsKey(markerId)) {
- assertExactlyCompletionProposal(proposals, acfContentAssistMarkerTagInfo.expectedExactlyProposalMap.get(markerId));
- }
- }
- // CHECKSTYLE:OFF
- } catch (Exception e) {
- // CHECKSTYLE:ON
- throw new WrappedException("Could not assert the expected valid and invalid proposals.", e);
- }
- }
-
- /**
- * Asserts the proposals for the given kernel test filename and content.
- *
- * @param sourceFileName
- * the filename of the test source that the proposals were to be computed from, must not be {@code null}
- * @param sourceContent
- * the content of the test source, must not be {@code null}
- */
- protected void assertKernelSourceProposals(final String sourceFileName, final CharSequence sourceContent) {
- addKernelSourceToWorkspace(sourceFileName, sourceContent);
- assertSourceProposals(sourceFileName);
- }
-
- /**
- * Asserts the proposals for the given customer test filename and content.
- *
- * @param sourceFileName
- * the filename of the test source that the proposals were to be computed from, must not be {@code null}
- * @param sourceContent
- * the content of the test source, must not be {@code null}
- */
- protected void assertCustomerSourceProposals(final String sourceFileName, final CharSequence sourceContent) {
- addCustomerSourceToWorkspace(sourceFileName, sourceContent);
- assertSourceProposals(sourceFileName);
- }
-
- /**
- * Registers the marker with the given proposals. Each of the expected proposal must have a match with the computed proposals on the marked position.
- *
- * @param proposals
- * the expected proposals, must not be {@code null}
- * @return mark text to be inserted in the source file, never {@code null}
- */
- protected String expected(final String... proposals) {
- Integer markerId = getTag();
- acfContentAssistMarkerTagInfo.expectedProposalMap.put(markerId, proposals);
- return mark(markerId);
- }
-
- /**
- * Registers the marker with the given proposals. The expected proposals must EXACTLY match the computed proposals on the marked position.
- *
- * @param proposals
- * the exact expected proposals, must not be {@code null}
- * @return mark text to be inserted in the source file, never {@code null}
- */
- protected String expectedExactly(final String... proposals) {
- Integer markerId = getTag();
- acfContentAssistMarkerTagInfo.expectedExactlyProposalMap.put(markerId, proposals);
- return mark(markerId);
- }
-
- /**
- * Registers the marker with the given proposals. Each of the expected proposal must NOT match with any of the computed proposals on the marked position.
- *
- * @param proposals
- * the expected invalid proposals, must not be {@code null}
- * @return mark text to be inserted in the source file, never {@code null}
- */
- protected String notExpected(final String... proposals) {
- Integer markerId = getTag();
- acfContentAssistMarkerTagInfo.notExpectedProposalMap.put(markerId, proposals);
- return mark(markerId);
- }
-
- /**
- * Stores the valid proposals in a corresponding map using the given marker id.
- * This method will return the marker id that will be used to {@link #mark()} the position in
- * which the valid proposals are expected.
- * Use {@link #getTag()} for the marker id when accessing locally. For global declarations, use @Tag annotation for marker id.
- *
- * @param markerId
- * the unique marker id, must not be {@code null}}
- * @param proposals
- * the expected valid proposals, must not be {@code null}
- * @return the marker id, never {@code null}
- */
- protected int expected(final int markerId, final String... proposals) {
- acfContentAssistMarkerTagInfo.expectedProposalMap.put(markerId, proposals);
- return markerId;
- }
-
- /**
- * Stores the invalid proposals in a corresponding map using the given marker id.
- * This method will return the marker id that will be used to {@link #mark()} the position in which the proposals are not expected.
- * Use {@link #getTag()} for the marker id when accessing locally. For global declarations, use @Tag annotation for marker id.
- *
- * @param markerId
- * the unique marker id, must not be {@code null}}
- * @param proposals
- * the expected invalid proposals, must not be {@code null}
- * @return the marker id, never {@code null}
- */
- protected int notExpected(final int markerId, final String... proposals) {
- acfContentAssistMarkerTagInfo.notExpectedProposalMap.put(markerId, proposals);
- return markerId;
- }
-
- /**
- * Stores the exact valid proposals in a corresponding map using the given marker id.
- * This method will return the marker id that will be used to {@link #mark()} the position in which the exact proposals are expected.
- * Use {@link #getTag()} for the marker id when accessing locally. For global declarations, use @Tag annotation for marker id.
- *
- * @param markerId
- * the unique marker id, must not be {@code null}}
- * @param proposals
- * the expected exact proposals, must not be {@code null}
- * @return the marker id, never {@code null}
- */
- protected int expectedExactly(final int markerId, final String... proposals) {
- acfContentAssistMarkerTagInfo.expectedExactlyProposalMap.put(markerId, proposals);
- return markerId;
- }
-
- /**
- * This class preserves information about tags in the sources for all tests within
- * a content assist test class.
- */
- private final class AcfContentAssistMarkerTagsInfo extends MarkerTagsInfo {
- private final Map expectedProposalMap = Maps.newHashMap();
- private final Map notExpectedProposalMap = Maps.newHashMap();
- private final Map expectedExactlyProposalMap = Maps.newHashMap();
-
- @Override
- public void clearTags(final long maxId) {
- super.clearTags(maxId);
- expectedProposalMap.entrySet().removeIf(entry -> entry.getKey() < TagCompilationParticipant.COUNTER_BASE);
- notExpectedProposalMap.entrySet().removeIf(entry -> entry.getKey() < TagCompilationParticipant.COUNTER_BASE);
- expectedExactlyProposalMap.entrySet().removeIf(entry -> entry.getKey() < TagCompilationParticipant.COUNTER_BASE);
- }
- }
-
- @Override
- protected AcfContentAssistMarkerTagsInfo getMarkerTagsInfo() {
- AcfContentAssistMarkerTagsInfo info = (AcfContentAssistMarkerTagsInfo) getTestInformation().getTestObject(AcfContentAssistMarkerTagsInfo.class);
- if (info == null) {
- info = acfContentAssistMarkerTagInfo;
- getTestInformation().putTestObject(AcfContentAssistMarkerTagsInfo.class, acfContentAssistMarkerTagInfo);
- }
- return info;
- }
-
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/conversion/AbstractValueConverterServiceTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/conversion/AbstractValueConverterServiceTest.java
deleted file mode 100644
index a29ad22df..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/conversion/AbstractValueConverterServiceTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.conversion;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.xtext.AbstractRule;
-import org.eclipse.xtext.IGrammarAccess;
-import org.eclipse.xtext.conversion.IValueConverterService;
-import org.eclipse.xtext.conversion.ValueConverterException;
-
-import com.avaloq.tools.ddk.xtext.grammar.KeywordCollector;
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTest;
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-
-/**
- * Base class for testing a language {@link IValueConverterService} implementation.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractValueConverterServiceTest extends AbstractXtextTest {
- /** ID regular expression does not allow digits as first character. */
- public static final String INVALID_ID_NUMBER = "1something";
- /** ID regular expression does not allow #. */
- public static final String INVALID_ID_NONALPHANUM = "#";
- /** ID regular expression does not allow any '.'. */
- public static final String INVALID_ID_WITHDOT = "someValidIdentifier.something";
- protected static final Set INVALID_IDENTIFIERS = ImmutableSet.of(
-// @Format-Off
- INVALID_ID_NUMBER,
- INVALID_ID_NONALPHANUM,
- INVALID_ID_WITHDOT
-// @Format-On
- );
-
- private final Map keywordCollectors = Maps.newHashMap();
-
- /**
- * Returns the {@link IGrammarAccess}.
- *
- * @return the {@link IGrammarAccess}, never {@code null}
- */
- protected IGrammarAccess getGrammarAccess() {
- final IGrammarAccess grammarAccess = getXtextTestUtil().get(IGrammarAccess.class);
- assertNotNull("The IGrammarAccess must be registered in order to test the IValueConverterService.", grammarAccess);
- return grammarAccess;
- }
-
- /**
- * Returns whether keyword case is ignored.
- *
- * Note: The default is {@code true}, i.e. keyword case is ignored.
- *
- *
- * @return whether keyword case is ignored
- */
- protected boolean isIgnoreCase() {
- return true;
- }
-
- /**
- * Gets or creates the {@link KeywordCollector} instance for the given {@link AbstractRule}.
- *
- * @param rule
- * the {@link AbstractRule}, must not be {@code null}
- * @return the {@link KeywordCollector} instance for the given {@link AbstractRule}, never {@code null}
- */
- protected KeywordCollector getKeywordCollector(final AbstractRule rule) {
- KeywordCollector keywordCollector = keywordCollectors.get(rule);
- if (keywordCollector == null) {
- keywordCollector = new KeywordCollector(rule, isIgnoreCase());
- keywordCollectors.put(rule, keywordCollector);
- }
- return keywordCollector;
- }
-
- /**
- * Returns the {@link IValueConverterService}.
- *
- * @return the {@link IValueConverterService}, never {@code null}
- */
- protected IValueConverterService getValueConverterService() {
- final IValueConverterService valueConverterService = getXtextTestUtil().get(IValueConverterService.class);
- assertNotNull("The IValueConverterService must be registered in order to test it.", valueConverterService);
- return valueConverterService;
- }
-
- /**
- * Asserts that the value-to-string conversion resulted in a string that is equal to the specified input value.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- * @param value
- * the value to be converted, must not be {@code null}
- */
- protected void assertToStringConvertedEquals(final AbstractRule rule, final String value) {
- final String actual = getValueConverterService().toString(value, rule.getName());
- assertEquals("Converted value must be equal to input value.", value, actual);
- }
-
- /**
- * Asserts that the value-to-string conversion resulted in a string that is equal to the specified input value surrounded by double-quotes.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- * @param value
- * the value to be converted, must not be {@code null}
- */
- protected void assertToStringConvertedQuoted(final AbstractRule rule, final String value) {
- final String actual = getValueConverterService().toString(value, rule.getName());
- assertEquals("Quotes expected", '"' + value + '"', actual);
- }
-
- /**
- * Asserts that the value-to-string conversion for all the specified values results in strings that are equal to the specified input values surrounded by
- * double-quotes.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- * @param values
- * values to be converted, must not be {@code null}
- */
- protected void assertToStringConvertedQuoted(final AbstractRule rule, final Iterable values) {
- List failures = Lists.newArrayList();
- for (String value : values) {
- String actual = getValueConverterService().toString(value, rule.getName());
- if (!actual.equals('"' + value + '"')) {
- failures.add(value);
- }
- }
- if (!failures.isEmpty()) {
- fail("All specified values must be quoted. The following invalid identifiers were not enquoted: " + Joiner.on(", ").join(failures));
- }
- }
-
- /**
- * Asserts that the value-to-string conversion for the keywords listed by the specified rule (or one of rules it calls) leaves them unchanged.
- *
- * @param rule
- * the rule used for the value-to-string conversion and whose keywords are tested, must not be {@code null}
- */
- protected void assertToStringLeavesRuleKeywordsUnchanged(final AbstractRule rule) {
- assertToStringLeavesRuleKeywordsUnchanged(rule, null);
- }
-
- /**
- * Asserts that the value-to-string conversion for the keywords listed by the specified rule (or one of rules it calls) leaves them unchanged.
- *
- * @param rule
- * the rule used for the value-to-string conversion and whose keywords are tested, must not be {@code null}
- * @param exceptions
- * the keywords used in the rule that are not valid by themselves (e.g. '.' or other special characters that cannot stand alone), may be {@code null}
- */
- protected void assertToStringLeavesRuleKeywordsUnchanged(final AbstractRule rule, final Collection exceptions) {
- final Collection keywords = getKeywordCollector(rule).getKeywords();
- if (exceptions != null) {
- keywords.removeAll(exceptions);
- }
- for (final String keyword : keywords) {
- assertToStringConvertedEquals(rule, keyword);
- }
- }
-
- /**
- * Asserts that the value-to-string conversion for values that do not match the ID terminal rule regular expression results in the values surrounded by
- * double-quotes.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertToStringNonIDQuoted(final AbstractRule rule) {
- assertToStringConvertedQuoted(rule, INVALID_IDENTIFIERS);
- }
-
- /**
- * Asserts that the value-to-string conversion for all of the specified values results in a {@link ValueConverterException} thrown.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- * @param valueList
- * the list of values to be converted, must not be {@code null}
- */
- protected void assertToStringFails(final AbstractRule rule, final Iterable valueList) {
- List failures = Lists.newArrayList(valueList);
- for (String value : valueList) {
- try {
- getValueConverterService().toString(value, rule.getName());
- } catch (ValueConverterException e) {
- failures.remove(value);
- }
- }
- if (!failures.isEmpty()) {
- fail("The following invalid identifiers did not cause a ValueConverterException: " + Joiner.on(", ").join(failures));
- }
- }
-
- /**
- * Asserts that the value-to-string conversion for values that do not match the ID terminal rule regular expression results in a
- * {@link ValueConverterException} thrown.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertToStringNonIDFails(final AbstractRule rule) {
- assertToStringFails(rule, INVALID_IDENTIFIERS);
- }
-
- /**
- * Asserts that the value-to-string conversion for values that are part of the rule language but are not listed by the rule results in a
- * {@link ValueConverterException} thrown.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertToStringOtherKeywordsFail(final AbstractRule rule) {
- assertToStringFails(rule, getKeywordCollector(rule).getOtherKeywords());
- }
-
- /**
- * Asserts that the value-to-string conversion for values that are part of the rule language but are not listed by the rule results in quoted strings.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertToStringOtherKeywordsQuoted(final AbstractRule rule) {
- assertToStringConvertedQuoted(rule, getKeywordCollector(rule).getOtherKeywords());
- }
-
- /**
- * Asserts that the value-to-string conversion for values that keywords listed by the rule leaves them unchanged while other language keywords or invalid IDs
- * result in a {@link ValueConverterException} thrown.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertToStringOnlyListedKeywordsAllowed(final AbstractRule rule) {
- assertToStringLeavesRuleKeywordsUnchanged(rule);
- assertToStringOtherKeywordsFail(rule);
- assertToStringNonIDFails(rule);
- }
-
- /**
- * Asserts that boolean values convert to "true" for {@link Boolean#TRUE} and "false" for {@link Boolean#FALSE}.
- *
- * @param rule
- * the rule used for the value-to-string conversion, must not be {@code null}
- */
- protected void assertBooleanValueToString(final AbstractRule rule) {
- final String actualTrue = getValueConverterService().toString(Boolean.TRUE, rule.getName());
- assertEquals("Converted value must be \"true\".", Boolean.TRUE.toString(), actualTrue);
- final String actualFalse = getValueConverterService().toString(Boolean.FALSE, rule.getName());
- assertEquals("Converted value must be \"false\".", Boolean.FALSE.toString(), actualFalse);
- // Check that the converter is for the correct type
- try {
- getValueConverterService().toString("false", rule.getName());
- throw new AssertionError("Converter must not accept String.");
- } catch (final ClassCastException expected) {
- // expected; do nothing
- } catch (final ValueConverterException expected) {
- // expected; do nothing
- }
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/formatting/AbstractFormattingTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/formatting/AbstractFormattingTest.java
deleted file mode 100644
index 14bc96dd2..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/formatting/AbstractFormattingTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.formatting;
-
-import java.util.List;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.formatting.INodeModelFormatter;
-import org.eclipse.xtext.formatting.INodeModelFormatter.IFormattedRegion;
-import org.eclipse.xtext.nodemodel.ICompositeNode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.resource.SaveOptions;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTest;
-
-
-/**
- * Base class for formatting tests.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractFormattingTest extends AbstractXtextTest {
-
- private static final String CR_LF = "\r\n";
- private static final String LF = "\n";
-
- @Override
- protected List getRequiredSourceFileNames() {
- List result = super.getRequiredSourceFileNames();
- result.add(getExpectedTestSourceFileName());
- return result;
- }
-
- @Override
- protected String getTestSourceModelName() {
- return super.getTestSourceModelName() + "Input";
- }
-
- /**
- * The default implementation returns the default source model name for the test class and adds 'Expected'.
- * this test. A test class needs to override this, if the name of the expected formatting test source model differs from the default.
- *
- * @return the name of the expected formatting test source model
- */
- private String getExpectedTestSourceModelName() {
- return super.getTestSourceModelName() + "Expected";
- }
-
- /**
- * The default implementation returns the default source model name for the test class and adds 'Expected' and the default file extension for the grammar of
- * this test. A test class needs to override this, if the name of the expected formatting test source file differs from the default.
- *
- * @return the name of the expected formatting test source file
- */
- protected String getExpectedTestSourceFileName() {
- return getExpectedTestSourceModelName() + "." + getXtextTestUtil().getFileExtension();
- }
-
- /**
- * Test formatting based on the NodeModel.
- */
- @Test
- public void formattedNodeModel() {
- assertFormattedNodeModel();
- }
-
- /**
- * Test formatting based on the ParseTreeConstructor.
- */
- public void formattedParseTreeConstructor() {
- assertFormattedParseTreeConstructor();
- }
-
- /**
- * Test preservation of formatting using ParseTreeConstructor.
- */
- public void preservedParseTreeConstructor() {
- assertPreservedParseTreeConstructor();
- }
-
- /**
- * Test preservation of formatting using NodeModelFormatter.
- */
- @Test
- public void preservedNodeModel() {
- assertPreservedNodeModel();
- }
-
- /**
- * Test formatting based on the ParseTreeConstructor.
- */
- protected final void assertFormattedParseTreeConstructor() {
- assertFormattedParseTreeConstructor(getSemanticModel(), getTestSource(getExpectedTestSourceFileName()).getContent());
- }
-
- /**
- * Test formatting based on the NodeModel.
- *
- * @param offset
- * Offset from which to start formatting
- * @param length
- * Length of region to format
- */
- private void assertFormattedNodeModel(final int offset, final int length) {
- assertFormattedNodeModel(getSemanticModel(), getTestSource().getContent(), getTestSource(getExpectedTestSourceFileName()).getContent(), offset, length);
- }
-
- /**
- * Test formatting based on the NodeModel.
- */
- private void assertFormattedNodeModel() {
- assertFormattedNodeModel(0, getTestSource().getContent().length());
- }
-
- /**
- * Test preservation of formatting.
- */
- private void assertPreservedNodeModel() {
- String expectedContent = getTestSource(getExpectedTestSourceFileName()).getContent();
- assertFormattedNodeModel(getTestSource(getExpectedTestSourceFileName()).getModel(), expectedContent, expectedContent, 0, expectedContent.length());
- }
-
- /**
- * Test preservation of formatting.
- */
- protected final void assertPreservedParseTreeConstructor() {
- assertFormattedParseTreeConstructor(getTestSource(getExpectedTestSourceFileName()).getModel(), getTestSource(getExpectedTestSourceFileName()).getContent());
- }
-
- /**
- * Test formatting based on the ParseTreeConstructor.
- *
- * @param model
- * the model to be serialized and compared with expected string
- * @param expected
- * Expected formatted String
- */
- private void assertFormattedParseTreeConstructor(final EObject model, final String expected) {
- String actual = getXtextTestUtil().getSerializer().serialize(model, SaveOptions.newBuilder().format().getOptions());
- Assert.assertEquals("Formatted ParseTree", expected.replaceAll(CR_LF, LF), actual.replaceAll(CR_LF, LF));
- }
-
- /**
- * Test formatting based on the NodeModel.
- *
- * @param model
- * the model to check
- * @param input
- * String representing a serialized model
- * @param expected
- * Expected formatted String
- * @param offset
- * Offset from which to start formatting
- * @param length
- * Length of region to format
- */
- private void assertFormattedNodeModel(final EObject model, final String input, final String expected, final int offset, final int length) {
- ICompositeNode node = NodeModelUtils.getNode(model).getRootNode();
- IFormattedRegion region = getXtextTestUtil().get(INodeModelFormatter.class).format(node, offset, length);
- String actual = input.substring(0, offset) + region.getFormattedText() + input.substring(length + offset);
- Assert.assertEquals("Formatted NodeModel", expected.replaceAll(CR_LF, LF), actual.replaceAll(CR_LF, LF));
- }
-
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/generator/AbstractGeneratorTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/generator/AbstractGeneratorTest.java
deleted file mode 100644
index 597ffcea2..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/generator/AbstractGeneratorTest.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.generator;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Sets.newHashSet;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.pde.core.project.IBundleProjectDescription;
-import org.eclipse.ui.actions.WorkspaceModifyOperation;
-import org.eclipse.xtext.resource.FileExtensionProvider;
-import org.eclipse.xtext.ui.XtextProjectHelper;
-import org.eclipse.xtext.ui.testing.util.IResourcesSetupUtil;
-import org.eclipse.xtext.ui.testing.util.JavaProjectSetupUtil;
-import org.eclipse.xtext.ui.util.PluginProjectFactory;
-import org.junit.AfterClass;
-import org.junit.Assert;
-
-import com.google.common.base.Functions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.io.CharStreams;
-import com.google.common.io.Resources;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-
-/**
- * A base class for xtext generator tests. Allows creating a project and adding files.
- */
-@SuppressWarnings({"PMD.AbstractClassWithoutAbstractMethod", "nls"})
-public abstract class AbstractGeneratorTest {
- private static final String MESSAGE_GENERATED_FILE_MUST_EXIST = "Generated file ''{0}'' must exist.";
- private static final String MESSAGE_GENERATED_CODE_MUST_BE_CORRECT = "Generated contents of ''{0}'' must be correct.";
-
- private static final String FORWARD_SLASH = "/"; //$NON-NLS-1$
-
- private static final Logger LOGGER = LogManager.getLogger(AbstractGeneratorTest.class);
-
- private static Map projects = new HashMap();
-
- private final Set files = newHashSet();
- protected static final List REQUIRED_BUNDLES = newArrayList(//
- "org.eclipse.xtext.xbase.lib", //$NON-NLS-1$
- "org.eclipse.xtend.lib", // //$NON-NLS-1$
- "org.eclipse.emf.ecore", //$NON-NLS-1$
- "org.eclipse.xtext", // //$NON-NLS-1$
- "org.eclipse.osgi", //$NON-NLS-1$
- "org.eclipse.xtend", //$NON-NLS-1$
- "org.eclipse.core.runtime", //$NON-NLS-1$
- "org.eclipse.xtext.xbase" //$NON-NLS-1$
- );
-
- @Inject
- private FileExtensionProvider fileExtensionProvider;
-
- @Inject
- private Provider projectFactoryProvider;
-
- /**
- * Clean up after all tests have terminated.
- */
- @AfterClass
- public static void cleanUp() {
- try {
- IResourcesSetupUtil.cleanWorkspace();
- } catch (CoreException e) {
- LOGGER.error(e.getMessage(), e);
- }
- }
-
- /**
- * Initializes a project with the given name and sources.
- *
- * @param projectName
- * the name of the project
- * @param sourceFileNames
- * the source file names, mapping input filename to output filename
- * @throws CoreException
- * the {@link CoreException}
- */
- public void initializeProject(final String projectName, final Map sourceFileNames) throws CoreException {
- initializeProject(projectName, null, REQUIRED_BUNDLES, null, null, sourceFileNames);
- }
-
- /**
- * Initializes a project with the given name, required bundles and sources.
- *
- * @param projectName
- * the name of the project
- * @param folders
- * the folders to create (source and source-generated folders will be created unless methods are overridden and specified as null or empty), or
- * {@code null} if none
- * @param requiredBundles
- * required bundles of the project to be created, or {@code null} if none
- * @param importedPackages
- * imported packages of the project to be created, or {@code null} if none
- * @param exportedPackages
- * exported packages of the project to be created, or {@code null} if none
- * @param sourceFileNames
- * the source file names, mapping input filename to output filename
- * @throws CoreException
- * the {@link CoreException}
- */
- public void initializeProject(final String projectName, final List folders, final List requiredBundles, final List importedPackages, final List exportedPackages, final Map sourceFileNames) throws CoreException {
- // a project must be created
- createPluginProject(projectName, folders, requiredBundles, importedPackages, exportedPackages);
- // sources are copied into the project and then built by the Xtext builder
- addSourcesToWorkspace(projectName, sourceFileNames);
-
- // wait for build to finish, otherwise included catalog may not be resolvable
- IResourcesSetupUtil.waitForBuild();
- }
-
- /**
- * Gets the full file name.
- *
- * @param projectName
- * the name of the project
- * @param fileName
- * the file name
- * @return the full file name
- */
- protected String getFullFileName(final String projectName, final String fileName) {
- if (fileName.startsWith(FORWARD_SLASH)) {
- // it is assumed that a full path is provided
- return fileName;
- }
- if (fileName.contains(FORWARD_SLASH)) {
- // it is assumed that a fully qualified file name in the boundaries of the current project is provided, only add the project name suffix
- return '/' + projectName + '/' + fileName;
- }
- String extension = (fileName.indexOf('.') != -1) ? "" : '.' + fileExtensionProvider.getPrimaryFileExtension(); //$NON-NLS-1$
- return getSourceFolderPath(projectName) + fileName + extension;
- }
-
- /**
- * Gets the file with given file name.
- *
- * @param fileName
- * the file name
- * @return the file
- */
- protected IFile getFile(final String fileName) {
- final String fileNameWithExtension = fileName.indexOf('.') > 0 ? fileName : fileName + '.' + fileExtensionProvider.getPrimaryFileExtension();
- return Iterables.find(files, new Predicate() {
- @Override
- public boolean apply(final IFile input) {
- return fileNameWithExtension.equals(input.getName());
- }
- });
- }
-
- /**
- * Gets the project with the given name or creates and returns it if it is non-existent.
- *
- * @param projectName
- * the name of the project
- * @return the project
- * @throws CoreException
- * the core exception
- */
- protected IProject getOrCreatePluginProject(final String projectName) throws CoreException {
- if (!projects.containsKey(projectName) || projects.get(projectName) == null) {
- return createPluginProject(projectName, null, REQUIRED_BUNDLES, null, null);
- }
- return projects.get(projectName);
- }
-
- /**
- * Creates and returns a project with the given name and the given required bundles.
- *
- * @param projectName
- * the name of the project
- * @param folders
- * the folders to create (source and source-generated folders will be created unless methods are overridden and specified as null or empty)
- * @param requiredBundles
- * required bundles of the project to be created, or {@code null} if none
- * @param importedPackages
- * imported packages of the project to be created, or {@code null} if none
- * @param exportedPackages
- * exported packages of the project to be created, or {@code null} if none
- * @return the project
- * @throws CoreException
- * the core exception
- */
- protected IProject createPluginProject(final String projectName, final List folders, final List requiredBundles, final List importedPackages, final List exportedPackages) throws CoreException { // NOPMD
- // NPathComplexity
- final PluginProjectFactory projectFactory = projectFactoryProvider.get();
- projectFactory.setProjectName(projectName);
- String sourceFolderName = getSourceFolderName();
- if (sourceFolderName != null && sourceFolderName.length() > 0) {
- projectFactory.addFolders(Arrays.asList(sourceFolderName));
- }
- String sourceFolderGeneratedName = getSourceFolderGeneratedName();
- if (sourceFolderGeneratedName != null && sourceFolderGeneratedName.length() > 0) {
- projectFactory.addFolders(Arrays.asList(sourceFolderGeneratedName));
- }
- if (folders != null) {
- projectFactory.addFolders(folders);
- }
- projectFactory.addBuilderIds(JavaCore.BUILDER_ID, "org.eclipse.pde.ManifestBuilder", "org.eclipse.pde.SchemaBuilder", XtextProjectHelper.BUILDER_ID); //$NON-NLS-1$ //$NON-NLS-2$
- projectFactory.addProjectNatures(JavaCore.NATURE_ID, IBundleProjectDescription.PLUGIN_NATURE, XtextProjectHelper.NATURE_ID);
- if (requiredBundles != null) {
- projectFactory.addRequiredBundles(requiredBundles);
- }
- if (importedPackages != null) {
- projectFactory.addImportedPackages(importedPackages);
- }
- if (exportedPackages != null) {
- projectFactory.addExportedPackages(exportedPackages);
- }
- final IProject[] result = new IProject[1];
- WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
-
- @SuppressWarnings("deprecation")
- @Override
- protected void execute(final IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
- result[0] = projectFactory.createProject(monitor, null);
- IJavaProject javaProject = JavaCore.create(result[0]);
- JavaProjectSetupUtil.makeJava5Compliant(javaProject);
- JavaProjectSetupUtil.addJreClasspathEntry(javaProject);
- }
- };
- try {
- operation.run(new NullProgressMonitor());
- } catch (InvocationTargetException e) {
- return null;
- } catch (InterruptedException e) {
- return null;
- }
- return projects.put(projectName, result[0]);
- }
-
- /**
- * Returns the name of the source folder.
- *
- * @return the name of the source folder
- */
- protected String getSourceFolderName() {
- return "src"; //$NON-NLS-1$
- }
-
- /**
- * Returns the name of the source folder for generated sources.
- *
- * @return the name of the source folder for generated sources
- */
- protected String getSourceFolderGeneratedName() {
- return "src-gen"; //$NON-NLS-1$
- }
-
- /**
- * Adds sources with given file names to the {@link #getSourceFolderName()} folder of current project. If resources
- * to be added to workspace do not contain a file extension in their file name, it is nevertheless added on files
- * created.
- *
- * @param projectName
- * the name of the project
- * @param sourceFileNames
- * the source file names
- */
- public void addSourcesToWorkspace(final String projectName, final List sourceFileNames) {
- addSourcesToWorkspace(projectName, Maps.uniqueIndex(sourceFileNames, Functions. identity()));
- }
-
- /**
- * Adds sources with given file names to the {@link #getSourceFolderName()} folder of current project. If resources
- * to be added to workspace do not contain a file extension in their file name, it is nevertheless added on files
- * created.
- *
- * @param projectName
- * the name of the project
- * @param sourceFileNames
- * the source file names, mapping input filename to output filename
- */
- public void addSourcesToWorkspace(final String projectName, final Map sourceFileNames) {
- try {
- new WorkspaceModifyOperation() {
- @Override
- protected void execute(final IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException {
- for (String inputFileName : sourceFileNames.keySet()) {
- // Calculate output filename
- final String outputFileName = sourceFileNames.get(inputFileName);
- try {
- final String contents = getContents(inputFileName);
- // Create URI including file extension
- URI resourceURI = URI.createPlatformResourceURI(getFullFileName(projectName, outputFileName), true);
- IResourcesSetupUtil.createFile(resourceURI.toPlatformString(true), contents);
- } catch (IOException e) {
- LOGGER.error("failed adding file to workspace: " + outputFileName, e); //$NON-NLS-1$
- Assert.fail("Error adding file " + outputFileName + " to workspace: " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- }
- }.run(new NullProgressMonitor());
- } catch (InvocationTargetException e) {
- Assert.fail("Error adding files to workspace: " + e.getMessage()); //$NON-NLS-1$
- } catch (InterruptedException e) {
- Assert.fail("Error adding files to workspace: " + e.getMessage()); //$NON-NLS-1$
- }
- }
-
- /**
- * Gets the full path to the {@link #getSourceFolderName()} folder.
- *
- * @param projectName
- * the name of the project
- * @return the source folder path
- */
- protected String getSourceFolderPath(final String projectName) {
- return '/' + projectName + '/' + getSourceFolderName() + '/';
- }
-
- /**
- * Gets the {@link IFile} of the given project and path.
- *
- * @param projectName
- * the name of the project
- * @param filePath
- * the file path
- * @return the {@link IFile} of the given project and path
- */
- protected IFile getFileFromProject(final String projectName, final String filePath) {
- return ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getFile(filePath);
- }
-
- /**
- * Gets the contents of a given file. Contents are returned as a single string.
- *
- * @param file
- * the file
- * @return the file contents
- * @throws CoreException
- * thrown if file could not be read
- * @throws IOException
- * thrown if file could not be read
- */
- public String getContents(final IFile file) throws IOException, CoreException {
- try (InputStreamReader reader = new InputStreamReader(file.getContents(), StandardCharsets.UTF_8)) {
- return normalizeLineBreaks(CharStreams.toString(reader));
- }
- }
-
- /**
- * Gets the contents of a specified resource using the default charset.
- *
- * @param resourceName
- * the name of the resource
- * @return the normalized contents of the specified resource
- * @throws IOException
- * if model could not be read
- */
- public String getContents(final String resourceName) throws IOException {
- URL resource = Resources.getResource(this.getClass(), resourceName);
- return normalizeLineBreaks(Resources.toString(resource, Charset.defaultCharset()));
- }
-
- /**
- * Asserts that generation was successful, i.e. the given file exists, and the content is expected.
- *
- * @param projectName
- * the name of the project
- * @param fileName
- * the name of the generated file
- * @param expectedGeneratedContent
- * the expected content of the generated file
- * @throws IOException
- * the {@link IOException}
- * @throws CoreException
- * the {@link CoreException}
- */
- public void assertFileGenerated(final String projectName, final String fileName, final String expectedGeneratedContent) throws IOException, CoreException {
- IFile generatedFile = getFileFromProject(projectName, fileName);
- Assert.assertTrue(MessageFormat.format(MESSAGE_GENERATED_FILE_MUST_EXIST, generatedFile.toString()), generatedFile.exists());
-
- String actualGeneratedContent = getContents(generatedFile);
- Assert.assertEquals(MessageFormat.format(MESSAGE_GENERATED_CODE_MUST_BE_CORRECT, generatedFile.toString()), expectedGeneratedContent, actualGeneratedContent);
- }
-
- /**
- * Replaces all \r\n with \n.
- *
- * @param text
- * input text
- * @return the normalized test
- */
- public String normalizeLineBreaks(final String text) {
- return text.replaceAll("\r\n", "\n");
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/SwtBotRecordingXtextTestRunner.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/SwtBotRecordingXtextTestRunner.java
deleted file mode 100644
index 8ce51a3bc..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/SwtBotRecordingXtextTestRunner.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.junit.runners;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
-import org.junit.internal.runners.statements.InvokeMethod;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import com.avaloq.tools.ddk.test.core.AbstractSystemTest;
-import com.avaloq.tools.ddk.test.ui.junit.runners.TestRunRecording;
-import com.avaloq.tools.ddk.test.ui.swtbot.CoreSwtbotTools;
-
-
-/**
- * A {@link org.junit.runner.Runner} to use with swt bot tests featuring screenshot recording.
- */
-// suppress warning restriction of org.junit.internal.runners.statements.InvokeMethod
-@SuppressWarnings("restriction")
-public class SwtBotRecordingXtextTestRunner extends XtextClassRunner {
- /**
- * Used to mark a test class or method to define the recording interval in milliseconds to use for the {@link SwtBotRecordingXtextTestRunner}.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD, ElementType.TYPE})
- public static @interface RecordingInterval {
- /**
- * Returns the recording interval value in milliseconds.
- *
- * @return the recording interval value in milliseconds
- */
- long value();
- }
-
- private final TestRunRecording testRunRecording;
-
- /**
- * Creates a new instance of {@link SwtBotRecordingXtextTestRunner}.
- * Only called reflectively. Do not use programmatically.
- *
- * @param testClass
- * the test class to run
- * @throws InitializationError
- * if any initialization failed
- */
- public SwtBotRecordingXtextTestRunner(final Class extends AbstractSystemTest> testClass) throws InitializationError {
- super(testClass);
- CoreSwtbotTools.initializePreferences();
- testRunRecording = new TestRunRecording(getTestClass().getJavaClass(), SWTBotPreferences.SCREENSHOTS_DIR);
- // TODO: add custom made {@link org.junit.runners.model.Statement} to check for exceptions during the test
- // (by default test failures are reported only after the teardown has taken place)
- }
-
- @Override
- public void run(final RunNotifier notifier) {
- try {
- notifier.removeListener(testRunRecording); // remove existing listeners that could be added by suite or class runners
- notifier.addListener(testRunRecording);
- super.run(notifier);
- } finally {
- notifier.removeListener(testRunRecording);
- }
- }
-
- @Override
- protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
- testRunRecording.setRecordingInterval(getRecordingInterval(method));
- super.runChild(method, notifier);
- }
-
- @Override
- protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
- return new InvokeMethod(method, test) {
- @Override
- // CHECKSTYLE:CHECK-OFF IllegalThrow // inherited JUnit throw style
- public void evaluate() throws Throwable {
- // CHECKSTYLE:CHECK-ON IllegalThrow
- try {
- super.evaluate();
- // CHECKSTYLE:CHECK-OFF IllegalCatch // catching in order to act upon but then throwing the exception again
- } catch (final Throwable throwable) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- testRunRecording.methodInvokeFailure(throwable);
- throw throwable;
- }
- }
- };
- }
-
- /**
- * Computes the capture interval to use for recording the given test method.
- * Checks first the annotation {@link RecordingInterval} of the method,
- * then the annotations of the test class.
- * Falls back to the default setting if no annotations were found.
- *
- * @param method
- * the method under test
- * @return the framerate to use for recording the given test method
- */
- private long getRecordingInterval(final FrameworkMethod method) {
- RecordingInterval recordingInterval = method.getAnnotation(RecordingInterval.class);
- if (recordingInterval != null) {
- return recordingInterval.value();
- }
- for (Annotation annotation : getTestClass().getAnnotations()) {
- if (annotation.annotationType().equals(RecordingInterval.class)) {
- return ((RecordingInterval) annotation).value();
- }
- }
- return TestRunRecording.DEFAULT_RECORDING_INTERVAL;
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/XtextClassRunner.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/XtextClassRunner.java
deleted file mode 100644
index ea9c0da38..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/junit/runners/XtextClassRunner.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.junit.runners;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.eclipse.xtext.testing.XtextRunner;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.internal.AssumptionViolatedException;
-import org.junit.internal.runners.model.EachTestNotifier;
-import org.junit.internal.runners.statements.RunAfters;
-import org.junit.internal.runners.statements.RunBefores;
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-import org.junit.runner.manipulation.NoTestsRemainException;
-import org.junit.runner.manipulation.Sorter;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.ParentRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import com.avaloq.tools.ddk.test.core.AfterAll;
-import com.avaloq.tools.ddk.test.core.BeforeAll;
-import com.avaloq.tools.ddk.test.core.BugTest;
-import com.avaloq.tools.ddk.test.core.IntegrationTest;
-import com.avaloq.tools.ddk.test.core.ModuleTest;
-import com.avaloq.tools.ddk.test.core.MultipleTestProblems;
-import com.avaloq.tools.ddk.test.core.PerformanceTest;
-import com.avaloq.tools.ddk.test.core.Retry;
-import com.avaloq.tools.ddk.test.core.SystemTest;
-import com.avaloq.tools.ddk.test.core.UnitTest;
-import com.avaloq.tools.ddk.test.core.junit.runners.SorterUtil;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-
-/**
- * A JUnit runner extending the {@link XtextRunner} with support for @BeforeAll and @AfterAll annotated methods. These methods will be run once for a
- * given test class before the first test method and after the last test method respectively.
- *
- *
Test Methods
Considered are all those methods of the test class that are annotated with one (or more) of the following test annotations:
- *
- * - {@link Test}
- *
- {@link UnitTest}
- *
- {@link ModuleTest}
- *
- {@link IntegrationTest}
- *
- {@link SystemTest}
- *
- {@link PerformanceTest}
- *
- {@link BugTest}
- *
- *
- *
- *
Execution Order
The order of execution of the test methods is random by default. This can be changed by setting a specific sorter using the property
- * 'com.avaloq.test.sorter'. Available sorters:
- *
- *
- *
- *
Multiple Test Runs
The number of runs for each test can be set using the system property {@value #PROPERTY_TEST_RUNS}. By default a test is run
- * exactly once, i.e. the number is set to 1.
- *
- *
- * The runner can be configured to retry a failing test. The system property {@value #PROPERTY_TEST_RETRIES} allows to specify how many times at most a failing
- * test shall be retried. By default a failing test is not retried, i.e. the number is set to 0. Note: Test retries are ignored if a value greater than
- * 1 has been set for {@value #PROPERTY_TEST_RUNS}, in which case the test will be run exactly the specified number of times, regardless of failures.
- *
- *
- * A test which succeeds at least once is regarded as successful. To make a test fail in the case where it failed at least once, set the system property
- * {@value #PROPERTY_UNSTABLE_FAIL} to {@code true} (default: {@code false}).
- *
- */
-@SuppressWarnings({"restriction", "deprecation"})
-public class XtextClassRunner extends XtextRunner {
- /** The system property for the number of test runs. */
- public static final String PROPERTY_TEST_RUNS = "com.avaloq.test.runs"; //$NON-NLS-1$
- /** The system property for the number of times a failing test shall be retried. */
- public static final String PROPERTY_TEST_RETRIES = "com.avaloq.test.retries"; //$NON-NLS-1$
- /** The system property to specify whether unstable tests shall fail. */
- public static final String PROPERTY_UNSTABLE_FAIL = "com.avaloq.test.unstablefail"; //$NON-NLS-1$
- /** Class-wide logger. */
- private static final Logger LOGGER = LogManager.getLogger(XtextClassRunner.class);
- private static final List> TEST_ANNOTATIONS = Lists.newArrayList(Test.class, UnitTest.class, ModuleTest.class, IntegrationTest.class, SystemTest.class, PerformanceTest.class, BugTest.class);
- private List expectedMethods;
- private int currentMethodIndex;
- private final int testRuns;
- private final int testRetries;
- private final boolean unstableFail;
- private Description description;
- private boolean descriptionOutdated = true;
-
- /**
- * Creates a new test class runner.
- *
- * @param klass
- * target test class, must not be {@code null}
- * @throws InitializationError
- * if the runner could not be initialized
- */
- public XtextClassRunner(final Class> klass) throws InitializationError {
- super(klass);
- SorterUtil.getInstance().initializeSorter(this);
- testRuns = Integer.parseInt(System.getProperty(PROPERTY_TEST_RUNS, "1")); //$NON-NLS-1$
- testRetries = Integer.parseInt(System.getProperty(PROPERTY_TEST_RETRIES, "0")); //$NON-NLS-1$
- unstableFail = Boolean.parseBoolean(System.getProperty(PROPERTY_UNSTABLE_FAIL, "false")); //$NON-NLS-1$
- }
-
- /**
- * Initializes this runner by initializing {@link #expectedMethods} with the list of methods which are expected to be called. This is then also checked by
- * {@link #methodBlock(FrameworkMethod)} and allows identifying the first and last methods correctly.
- */
- private void ensureInitialized() {
- if (expectedMethods == null) {
- try {
- final Method getChildrenMethod = ParentRunner.class.getDeclaredMethod("getFilteredChildren"); //$NON-NLS-1$
- getChildrenMethod.setAccessible(true);
- @SuppressWarnings("unchecked")
- final Collection testMethods = (Collection) getChildrenMethod.invoke(this);
- expectedMethods = ImmutableList.copyOf(Iterables.filter(testMethods, new Predicate() {
- @Override
- public boolean apply(final FrameworkMethod input) {
- return input.getAnnotation(Ignore.class) == null;
- }
- }));
- currentMethodIndex = 0;
- // CHECKSTYLE:OFF
- } catch (Exception e) {
- // CHECKSTYLE:ON
- throw new IllegalStateException(e);
- }
- }
- }
-
- @Override
- public Description getDescription() {
- if (descriptionOutdated) {
- description = super.getDescription();
- descriptionOutdated = false;
- }
- return description;
- }
-
- @Override
- protected void validateInstanceMethods(final List errors) {
- validatePublicVoidNoArgMethods(AfterAll.class, false, errors);
- validatePublicVoidNoArgMethods(BeforeAll.class, false, errors);
-
- super.validateInstanceMethods(errors);
- }
-
- @Override
- public void sort(final Sorter sorter) {
- super.sort(sorter);
- descriptionOutdated = true;
- }
-
- @Override
- public void filter(final Filter filter) throws NoTestsRemainException {
- super.filter(filter);
- descriptionOutdated = true;
- }
-
- @Override
- protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
- ensureInitialized();
- final boolean ignored = method.getAnnotation(Ignore.class) != null;
- if (!ignored) {
- Assert.assertEquals("Method " + method.getName() + " not equal", expectedMethods.get(currentMethodIndex++), method); //$NON-NLS-1$//$NON-NLS-2$
- }
- if (ignored || testRuns == 1 && testRetries == 0 && method.getAnnotation(Retry.class) == null) {
- super.runChild(method, notifier);
- } else {
- runRepeatedly(method, createNotifier(method, notifier));
- }
- }
-
- /**
- * Runs the test method repeatedly according to the number of runs or retries.
- *
- * @param method
- * the {@link FrameworkMethod}, must not be {@code null}
- * @param eachNotifier
- * the {@link EachTestNotifier}, must not be {@code null}
- */
- @SuppressWarnings("PMD.NPathComplexity")
- private void runRepeatedly(final FrameworkMethod method, final EachTestNotifier eachNotifier) {
-
- final Retry retryAnnotation = method.getAnnotation(Retry.class);
- final int retryAnnotationValue = retryAnnotation != null ? retryAnnotation.value() : 0;
- final int thisTestRetries = Math.max(retryAnnotationValue, testRetries);
-
- eachNotifier.fireTestStarted();
- try {
- final MultipleTestProblems problems = new MultipleTestProblems();
- final Collection failures = Lists.newArrayList();
- final Collection errors = Lists.newArrayList();
- int run = 0;
- int succeeded = 0;
- while (run < testRuns || (testRuns == 1 && succeeded == 0 && run < thisTestRetries + 1)) {
- try {
- run++;
- methodBlock(method).evaluate();
- succeeded++;
- } catch (AssumptionViolatedException e) {
- throw e;
- } catch (AssertionError exception) {
- failures.add(exception);
- problems.addProblem(exception);
- // CHECKSTYLE:CHECK-OFF IllegalCatch // we want to catch all possible errors
- } catch (Throwable throwable) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- errors.add(throwable);
- problems.addProblem(throwable);
- }
- }
- final String testCase = getTestClass().getJavaClass().getSimpleName() + '.' + method.getName();
- if (run > 1) {
- logRepeatedTestResult(testCase, run, succeeded, failures.size(), errors.size());
- }
- if (succeeded == 0) {
- problems.assertEmpty();
- }
- if (problems.hasProblems()) {
- if (unstableFail) {
- problems.assertEmpty();
- } else {
- final StringWriter stringWriter = new StringWriter();
- problems.printStackTrace(new PrintWriter(stringWriter));
- LOGGER.info(stringWriter.toString());
- }
- }
- } catch (AssumptionViolatedException e) { // NOPMD ExceptionAsFlowControl
- eachNotifier.addFailedAssumption(e);
- // CHECKSTYLE:CHECK-OFF IllegalCatch // we want to catch all possible errors
- } catch (Throwable e) {
- // CHECKSTYLE:CHECK-ON IllegalCatch
- eachNotifier.addFailure(e);
- } finally {
- eachNotifier.fireTestFinished();
- }
- }
-
- /**
- * Logs the repeated test result.
- *
- * @param testCase
- * the test case, must not be {@code null}
- * @param runs
- * the number of runs
- * @param succeeded
- * the number of succeeded runs
- * @param failures
- * the number of failed runs
- * @param errors
- * the number of errored runs
- */
- public void logRepeatedTestResult(final String testCase, final int runs, final int succeeded, final int failures, final int errors) {
- final StringBuilder testResult = new StringBuilder(testCase).append(" Repeated Test Result: "); //$NON-NLS-1$
- if (succeeded == runs) {
- testResult.append("SUCCESS"); //$NON-NLS-1$
- } else if (succeeded == 0) {
- testResult.append("FAILURE"); //$NON-NLS-1$
- } else {
- testResult.append("UNSTABLE"); //$NON-NLS-1$
- }
- testResult.append(" (").append(succeeded).append(" of ").append(runs).append(" succeeded"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- if (failures > 0) {
- testResult.append(", ").append(failures).append(" failed"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (errors > 0) {
- testResult.append(", ").append(errors).append(" errored"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- testResult.append(')');
- LOGGER.info(testResult.toString());
- }
-
- /**
- * Creates a notifier for each test.
- *
- * @param method
- * the {@link FrameworkMethod}, must not be {@code null}
- * @param notifier
- * the {@link RunNotifier}, must not be {@code null}
- * @return an instance of {@link EachTestNotifier}, never {@code null}
- */
- private EachTestNotifier createNotifier(final FrameworkMethod method, final RunNotifier notifier) {
- return new EachTestNotifier(notifier, describeChild(method));
- }
-
- /**
- * Adds any @BeforeAll methods to be run before the normal @Before annotated methods for the first test method only.
- *
- * {@inheritDoc}
- */
- @Override
- protected Statement withBefores(final FrameworkMethod method, final Object target, final Statement stmt) {
- ensureInitialized();
- Statement statement = super.withBefores(method, target, stmt); // NOPMD.CloseResource
- if (method.equals(expectedMethods.get(0))) {
- // reverse BeforeAll method order to get a 'runs top to bottom' order
- final List befores = Lists.reverse(getTestClass().getAnnotatedMethods(BeforeAll.class));
- statement = befores.isEmpty() ? statement : new RunBefores(statement, befores, target);
- }
- return statement;
- }
-
- /**
- * Adds any @AfterAll methods to be run after the normal @After annotated methods for the last test method only.
- *
- * {@inheritDoc}
- */
- @Override
- protected Statement withAfters(final FrameworkMethod method, final Object target, final Statement stmt) {
- ensureInitialized();
- Statement statement = super.withAfters(method, target, stmt); // NOPMD.CloseResource
- if (method.equals(Iterables.getLast(expectedMethods))) {
- final List afters = getTestClass().getAnnotatedMethods(AfterAll.class);
- statement = afters.isEmpty() ? statement : new RunAfters(statement, afters, target);
- }
- return statement;
- }
-
- /** {@inheritDoc} */
- @Override
- protected List computeTestMethods() {
- final Collection result = Sets.newHashSet();
- for (final Class extends Annotation> annotationClass : TEST_ANNOTATIONS) {
- result.addAll(getTestClass().getAnnotatedMethods(annotationClass));
- }
- return Lists.newArrayList(result);
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/jvmmodel/AbstractJvmModelInferrerTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/jvmmodel/AbstractJvmModelInferrerTest.java
deleted file mode 100644
index f48c475ba..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/jvmmodel/AbstractJvmModelInferrerTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.jvmmodel;
-
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EObject;
-
-import com.avaloq.tools.ddk.xtext.test.modelinference.AbstractModelInferrerTest;
-
-
-/**
- * Base class for JVM model inference test implementations.
- */
-public abstract class AbstractJvmModelInferrerTest extends AbstractModelInferrerTest {
-
- @Override
- protected Set getInferredElements(final EObject sourceElement) {
- return InferredJvmModelUtil.getInferredElements(sourceElement);
- }
-
- /**
- * Returns an inferred element of specified name and type for a given source element.
- *
- * @param sourceElement
- * a source {@link EObject}, must not be {@code null}
- * @param name
- * the name of the element, must not be {@code null}
- * @param clazz
- * the type of the element, must not be {@code null}
- * @return an inferred element, or {@code null} if nothing has been found
- */
- @Override
- protected EObject getInferredElement(final EObject sourceElement, final String name, final Class extends EObject> clazz) {
- return InferredJvmModelUtil.getInferredElement(sourceElement, name, clazz);
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/linking/AbstractLinkingTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/linking/AbstractLinkingTest.java
deleted file mode 100644
index 0f3e18ea3..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/linking/AbstractLinkingTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.linking;
-
-import static org.junit.Assert.assertEquals;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTest;
-
-
-/**
- * Test linking of a given input file.
- */
-@SuppressWarnings("PMD.AbstractClassWithoutAnyMethod")
-public abstract class AbstractLinkingTest extends AbstractXtextTest {
- private static final String NOT_RESOLVED_MESSAGE = "Cross-reference has not been resolved."; //$NON-NLS-1$
-
- /**
- * Asserts that the actualObject equals the expectedObject.
- *
- * @param expectedObject
- * the expected object
- * @param actualObject
- * the actual object
- */
- protected void assertReferenceResolved(final EObject expectedObject, final EObject actualObject) {
- assertEquals(NOT_RESOLVED_MESSAGE, EcoreUtil.getURI(expectedObject), EcoreUtil.getURI(actualObject));
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/modelinference/AbstractModelInferrerTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/modelinference/AbstractModelInferrerTest.java
deleted file mode 100644
index 919ac60d1..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/modelinference/AbstractModelInferrerTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.modelinference;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-
-import com.avaloq.tools.ddk.typesystem.typemodel.INamedElement;
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextMarkerBasedTest;
-import com.google.common.collect.Lists;
-
-
-/**
- * Abstract base class for model inference test implementations.
- */
-public abstract class AbstractModelInferrerTest extends AbstractXtextMarkerBasedTest {
-
- private boolean oldAutoBuildState;
-
- @Override
- protected void beforeAllTests() {
- super.beforeAllTests();
- oldAutoBuildState = getTestProjectManager().setAutobuild(true);
- }
-
- @Override
- protected void afterAllTests() {
- getTestProjectManager().setAutobuild(oldAutoBuildState);
- super.afterAllTests();
- }
-
- /**
- * Returns the inferred elements for the given source element.
- *
- * @param sourceElement
- * a source {@link EObject}, must not be {@code null} *
- * @return the inferred elements for the given source element, never {@code null}
- */
- protected abstract Set getInferredElements(EObject sourceElement);
-
- /**
- * Validates the list of sources for correctness.
- *
- * @param sourceNames
- * list of sources, must not be {@code null}
- */
- protected void validateSources(final String... sourceNames) {
- for (String sourceName : sourceNames) {
- getXtextTestUtil().validateSource(sourceName, getTestProjectManager().getTestSource(sourceName).getContent());
- }
- }
-
- @Override
- protected List getRequiredSourceFileNames() {
- return Lists.newArrayList(); // Override the behavior of the parent
- }
-
- /**
- * Builds the workspace or waits until it is built. Updates the {@link TestState} after that.
- */
- protected void build() {
- getTestProjectManager().build();
- }
-
- /**
- * Asserts that nothing has been inferred for the tagged element.
- *
- * @param tag
- * A tag for an element
- */
- protected void assertNoInference(final int tag) {
- assertNoInference(getObjectForTag(tag));
- }
-
- /**
- * Asserts that nothing has been inferred for a given source element.
- *
- * @param sourceElement
- * a source {@link EObject}, must not be {@code null}
- */
- protected void assertNoInference(final EObject sourceElement) {
- final Set inferredElements = getInferredElements(sourceElement);
- assertTrue("Unexpected inferred elements found: " + inferredElements.toString(), inferredElements.isEmpty()); //$NON-NLS-1$
- }
-
- /**
- * Returns an inferred element of specified name and type for a given tag.
- *
- * Note: Returns the first encountered, if multiple elements have the same name.
- *
- *
- * @param tag
- * the tag for the element that should infer an element, must not be {@code null}
- * @param name
- * the name of the element, must not be {@code null}
- * @param clazz
- * the type of the element, must not be {@code null}
- * @return an inferred element, or {@code null} if nothing has been found
- */
- protected EObject getInferredElement(final int tag, final String name, final Class extends EObject> clazz) {
- return getInferredElement(getObjectForTag(tag), name, clazz);
- }
-
- /**
- * Returns an inferred element of specified name and type for a given source element.
- *
- * @param sourceElement
- * a source {@link EObject}, must not be {@code null}
- * @param name
- * the name of the element, must not be {@code null}
- * @param clazz
- * the type of the element, must not be {@code null}
- * @return an inferred element, or {@code null} if nothing has been found
- */
- protected EObject getInferredElement(final EObject sourceElement, final String name, final Class extends EObject> clazz) {
- final Set inferredElements = getInferredElements(sourceElement);
- EObject target = null;
- for (final EObject obj : inferredElements) {
- if (clazz.isAssignableFrom(obj.getClass()) && ((INamedElement) obj).getName().equals(name)) {
- target = EcoreUtil.resolve(obj, sourceElement);
- break;
- }
- }
- return target;
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/resource/AbstractResourceDescriptionManagerTest.xtend b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/resource/AbstractResourceDescriptionManagerTest.xtend
deleted file mode 100644
index 8f0c29679..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/resource/AbstractResourceDescriptionManagerTest.xtend
+++ /dev/null
@@ -1,198 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.resource;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTest;
-import org.eclipse.xtext.resource.IResourceDescription
-import com.avaloq.tools.ddk.xtext.resource.AbstractCachingResourceDescriptionManager
-import org.eclipse.xtext.resource.IResourceDescriptions
-import org.eclipse.emf.common.util.URI
-import java.util.Collection
-import org.eclipse.xtext.resource.IResourceDescription.Delta
-import com.google.common.collect.HashMultiset
-import org.junit.Assert
-import com.google.common.collect.Sets
-import com.avaloq.tools.ddk.xtext.test.TestSource
-
-/**
- * Abstract base class for {@link AbstractCachingResourceDescriptionManager} tests.
- */
-abstract class AbstractResourceDescriptionManagerTest extends AbstractXtextTest {
-
- /**
- * Simple unchanged {@link Delta} implementation with {@link URI}.
- */
- static class UnchangedDelta implements Delta {
-
- val URI uri;
-
- new(URI uri) {
- this.uri = uri;
- }
-
- override getNew() {
- null
- }
-
- override getOld() {
- null
- }
-
- override getUri() {
- uri
- }
-
- override haveEObjectDescriptionsChanged() {
- false
- }
- }
-
- val AbstractCachingResourceDescriptionManager resourceDescriptionManager = testUtil.get(IResourceDescription.Manager) as AbstractCachingResourceDescriptionManager;
- val IResourceDescriptions index = testUtil.get(IResourceDescriptions);
-
- /**
- * Returns the {@link AbstractCachingResourceDescriptionManager) to use in the test.
- *
- * @return the {@link AbstractCachingResourceDescriptionManager) to use in the test, never {@code null}
- */
- def AbstractCachingResourceDescriptionManager getResourceDescriptionManager() {
- return resourceDescriptionManager;
- }
-
- /**
- * Returns the {@link IResourceDescriptions) to use in the test.
- *
- * @return the {@link IResourceDescriptions) to use in the test, never {@code null}
- */
- def IResourceDescriptions getResourceDescriptions() {
- return index;
- }
-
- /**
- * Returns the candidates for the affected resource computations.
- *
- * Note: By default, all registered sources are considered as candidates.
- *
- *
- * @return the candidates for the affected resource computation, never {@code null}
- */
- def Collection getCandidates() {
- var Collection candidates = testInformation.getTestObject(URI) as Collection;
- if (candidates === null) {
- candidates = Sets.newHashSet;
- testInformation.putTestObject(URI, candidates);
- }
- return candidates;
- }
-
- /**
- * Creates a {@link TestSource} and considers it as a candidate by default.
- *
- * @param sourceFileName
- * file name for the test source, must not be {@code null}
- * @param content
- * content of source, must not be {@code null}
- * @return a new {@link TestSource} with the given parameters, never {@code null}
- */
- override protected createTestSource(String sourceFileName, String content) {
- val testSource = super.createTestSource(sourceFileName, content);
- getCandidates().add(testSource.uri);
- return testSource;
- }
-
- /**
- * Creates a {@link Delta} for the given {@link URI}.
- *
- * Note: By default, the delta is an instance of {@link UnchangedDelta}
- *
- *
- * @param uri
- * the delta {@link URI}, must not be {@code null}
- * @return a new {@link Delta}, never {@code null}
- */
- def Delta createDelta(URI uri) {
- return new UnchangedDelta(uri);
- }
-
- /**
- * Returns the {@link URI} of the {@link TestSource} with the given file name.
- *
- * @param sourceFileName
- * file name for the test source, must not be {@code null}
- * @return the {@link URI} of the {@link TestSource} with the given file name, never {@code null}
- */
- def URI getUri(String sourceFileName) {
- return getTestSource(sourceFileName).uri;
- }
-
- /**
- * Asserts that the given delta causes the expected set of affected resources.
- *
- * Note: Uses the candidates returned by {@link #getCandidates()}.
- *
- *
- * @param deltaSourceName
- * the delta source name, must not be {@code null}
- * @param expectedSourceNames
- * the expected affected source names, must not be {@code null}
- */
- def assertAffectedResources(String deltaSourceName, String... expectedSourceNames) {
- val Collection expectedUris = Sets.newHashSet;
- for (sourceName : expectedSourceNames) {
- expectedUris.add(getUri(sourceName));
- }
- assertAffectedResources(Sets.newHashSet(getUri(deltaSourceName)), getCandidates(), expectedUris);
- }
-
- /**
- * Asserts that the given set of deltas causes the expected set of affected {@link URI}s.
- *
- * Note: Uses the candidates returned by {@link #getCandidates()}.
- *
- *
- * @param deltaUris
- * the delta {@link URI}s, must not be {@code null}
- * @param expectedUris
- * the expected affected {@link URI}s, must not be {@code null}
- */
- def assertAffectedResources(Collection deltaUris, Collection expectedUris) {
- assertAffectedResources(deltaUris, getCandidates(), expectedUris);
- }
-
- /**
- * Asserts that the given set of deltas causes the expected set of affected {@link URI}s.
- *
- * @param deltaUris
- * the delta {@link URI}s, must not be {@code null}
- * @param candidates
- * the potential candidates that can be affected, must not be {@code null}
- * @param expectedUris
- * the expected affected {@link URI}s, must not be {@code null}
- */
- def assertAffectedResources(Collection deltaUris, Collection candidates, Collection expectedUris) {
- assertDeltaAffectedResources(Sets.newHashSet(deltaUris.map[createDelta(it)]), candidates, expectedUris);
- }
-
- /**
- * Asserts that the given set of deltas causes the expected set of affected {@link URI}s.
- *
- * @param deltas
- * the {@link Delta}s, must not be {@code null}
- * @param candidates
- * the potential candidates that can be affected, must not be {@code null}
- * @param expectedUris
- * the expected affected {@link URI}s, must not be {@code null}
- */
- def assertDeltaAffectedResources(Collection deltas, Collection candidates, Collection expectedUris) {
- val result = getResourceDescriptionManager().getAffectedResources(deltas, candidates, getResourceDescriptions());
- Assert.assertEquals("Affected URIs must be correct.", HashMultiset.create(expectedUris), HashMultiset.create(result));
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/scoping/AbstractScopingTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/scoping/AbstractScopingTest.java
deleted file mode 100644
index 989fb29ce..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/scoping/AbstractScopingTest.java
+++ /dev/null
@@ -1,877 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.scoping;
-
-import static com.avaloq.tools.ddk.xtext.linking.AbstractFragmentProvider.REP_SEPARATOR;
-import static com.avaloq.tools.ddk.xtext.linking.AbstractFragmentProvider.SEGMENT_SEPARATOR;
-import static com.avaloq.tools.ddk.xtext.resource.AbstractSelectorFragmentProvider.EQ_OP;
-import static com.avaloq.tools.ddk.xtext.resource.AbstractSelectorFragmentProvider.SELECTOR_END;
-import static com.avaloq.tools.ddk.xtext.resource.AbstractSelectorFragmentProvider.SELECTOR_START;
-import static com.avaloq.tools.ddk.xtext.resource.AbstractSelectorFragmentProvider.UNIQUE;
-import static com.avaloq.tools.ddk.xtext.resource.AbstractSelectorFragmentProvider.VALUE_SEP;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-import java.util.regex.Pattern;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.util.EObjectResolvingEList;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.xtext.Assignment;
-import org.eclipse.xtext.CrossReference;
-import org.eclipse.xtext.EcoreUtil2;
-import org.eclipse.xtext.naming.QualifiedName;
-import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.resource.IEObjectDescription;
-import org.eclipse.xtext.resource.IResourceDescription;
-import org.eclipse.xtext.resource.IResourceServiceProvider;
-import org.eclipse.xtext.resource.XtextResource;
-import org.eclipse.xtext.scoping.IScope;
-import org.eclipse.xtext.scoping.IScopeProvider;
-import org.eclipse.xtext.util.Triple;
-import org.eclipse.xtext.xbase.lib.Pair;
-
-import com.avaloq.tools.ddk.caching.Regexps;
-import com.avaloq.tools.ddk.xtext.linking.AbstractFragmentProvider;
-import com.avaloq.tools.ddk.xtext.naming.QualifiedNames;
-import com.avaloq.tools.ddk.xtext.resource.IFingerprintComputer;
-import com.avaloq.tools.ddk.xtext.scoping.ContainerQuery;
-import com.avaloq.tools.ddk.xtext.scoping.IDomain;
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextMarkerBasedTest;
-import com.google.common.base.Function;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-
-/**
- * Base class for scoping tests.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractScopingTest extends AbstractXtextMarkerBasedTest {
- private static final String PARAMETER_EXPECTED_OBJECTS = "expectedObjects";
- private static final String PARAMETER_REFERENCE = "reference";
- private static final String PARAMETER_CONTEXT = "context";
- public static final String TOP_LEVEL_OBJECT_FRAGMENT = SEGMENT_SEPARATOR + "0" + SEGMENT_SEPARATOR + "1";
- public static final String TOP_LEVEL_SURROGATE_FRAGMENT = SEGMENT_SEPARATOR + "0" + REP_SEPARATOR + "2";
- public static final String INFERRED_DATA_DICTIONARY_FRAGMENT = SEGMENT_SEPARATOR + "1";
-
- private static final String NUMBER_OF_ELEMENTS_MESSAGE = "Incorrect number of elements in scope.";
- private static final Splitter FRAGMENT_SEGMENT_SPLITTER = Splitter.onPattern("(? expectedLinkAssertions = new ArrayList();
-
- /**
- * Creates a new instance of {@link AbstractScopingTest}.
- */
- public AbstractScopingTest() {
- this(new IDomain.NullMapper());
-
- }
-
- /**
- * Creates a new instance of {@link AbstractScopingTest}.
- *
- * @param domainMapper
- * the domainMapper to use
- */
- public AbstractScopingTest(final IDomain.Mapper domainMapper) {
- this.domainMapper = domainMapper;
- }
-
- /**
- * Returns all contents of the main {@link XtextTestResource}.
- *
- * @return all contents of the main {@link XtextTestResource}
- */
- @SuppressWarnings("unchecked")
- public Iterable getContents() {
- return (Iterable) getTestInformation().getTestObject(Iterable.class);
- }
-
- /**
- * Set up scoping.
- */
- @Override
- protected void beforeAllTests() {
- super.beforeAllTests();
- Iterable allContents = new Iterable() {
- @Override
- public Iterator iterator() {
- return getXtextTestResource().getAllContents();
- }
- };
- getTestInformation().putTestObject(Iterable.class, allContents);
- }
-
- @Override
- protected void afterEachTest() {
- assertTrue("Expected links were set with link(int) but testLinking(String, CharSequence) was never called", expectedLinkAssertions.isEmpty());
- super.afterEachTest();
- }
-
- /**
- * Returns the scope provider used for unit testing.
- *
- * @return the scope provider instance
- */
- protected IScopeProvider getScopeProvider() {
- return getXtextTestUtil().get(IScopeProvider.class);
- }
-
- /**
- * Check if scope expected is found in context provided.
- *
- * @param context
- * element from which an element shall be referenced
- * @param reference
- * to be used to filter the elements
- * @param expectedSourceName
- * (upper case!) name of scope element to look for (kernel source)
- * @param expectedSourceType
- * type of scope element to look for
- */
- protected void assertScope(final EObject context, final EReference reference, final String expectedSourceName, final String expectedSourceType) {
- assertScope(context, reference, QualifiedNames.safeQualifiedName(expectedSourceName), getTargetSourceUri(expectedSourceName + '.'
- + expectedSourceType).appendFragment(TOP_LEVEL_OBJECT_FRAGMENT));
- }
-
- /**
- * Check if scope expected is found in context provided.
- *
- * @param context
- * element from which an element shall be referenced
- * @param reference
- * to be used to filter the elements
- * @param expectedElementName
- * name of scope element to look for
- * @param expectedSourceName
- * (upper case!) name of the source within to look for the scope element
- * @param expectedSourceType
- * type of scope element to look for
- * @param referenceElementType
- * the type of the referenced element
- */
- @SuppressWarnings("PMD.UseObjectForClearerAPI")
- protected void assertScopeForElement(final EObject context, final EReference reference, final String expectedElementName, final String expectedSourceName, final String expectedSourceType, final String referenceElementType) {
- assertScope(context, reference, QualifiedNames.safeQualifiedName(expectedElementName), getTargetSourceUri(expectedSourceName + '.'
- + expectedSourceType).appendFragment(TOP_LEVEL_OBJECT_FRAGMENT + SEGMENT_SEPARATOR + referenceElementType));
- }
-
- /**
- * Check if scope expected is found in context provided.
- *
- * @param context
- * element from which an element shall be referenced
- * @param reference
- * to be used to filter the elements
- * @param expectedUris
- * of source referenced
- */
- protected void assertScope(final EObject context, final EReference reference, final URI... expectedUris) {
- assertScope(context, reference, Sets.newHashSet(expectedUris));
- }
-
- /**
- * Check if scope expected is found in context provided.
- *
- * @param context
- * element from which an element shall be referenced
- * @param reference
- * to be used to filter the elements
- * @param expectedUriSet
- * of source referenced
- */
- protected void assertScope(final EObject context, final EReference reference, final Set expectedUriSet) {
- IScope scope = getScopeProvider().getScope(context, reference);
- for (IEObjectDescription description : scope.getAllElements()) {
- expectedUriSet.remove(description.getEObjectURI());
- if (expectedUriSet.isEmpty()) {
- return;
- }
- }
- assertTrue("Expected URIs not found in scope: " + expectedUriSet, expectedUriSet.isEmpty());
- }
-
- /**
- * Checks if the given objects are in scope of the given reference for the given context.
- *
- * @param context
- * {@link EObject} element from which an element shall be referenced, must not be {@code null}
- * @param reference
- * the structural feature of {@code context} for which the scope should be asserted, must not be {@code null} and part of the context element
- * @param expectedObjects
- * for given scope, must not be {@code null}
- */
- protected void assertScopedObjects(final EObject context, final EReference reference, final EObject... expectedObjects) {
- Assert.isNotNull(expectedObjects, PARAMETER_EXPECTED_OBJECTS);
- assertScopedObjects(context, reference, Lists.newArrayList(expectedObjects));
- }
-
- /**
- * Checks if the given objects are in scope of the given reference for the given context.
- *
- * @param context
- * {@link EObject} element from which an element shall be referenced, must not be {@code null}
- * @param reference
- * the structural feature of {@code context} for which the scope should be asserted, must not be {@code null} and part of the context element
- * @param firstExpectedObjectCollection
- * for given scope, must not be {@code null}
- * @param furtherExpectedObjectCollections
- * for given scope, must not be {@code null}
- */
- @SuppressWarnings("unchecked")
- protected void assertScopedObjects(final EObject context, final EReference reference, final Collection extends EObject> firstExpectedObjectCollection, final Collection extends EObject>... furtherExpectedObjectCollections) {
- Assert.isNotNull(firstExpectedObjectCollection, "firstExpectedObjectCollection");
- Assert.isNotNull(furtherExpectedObjectCollections, "furtherExpectedObjectCollections");
- Collection consolidatedList = Lists.newArrayList(firstExpectedObjectCollection);
- for (Collection extends EObject> expectedObjects : furtherExpectedObjectCollections) {
- consolidatedList.addAll(expectedObjects);
- }
- assertScopedObjects(context, reference, consolidatedList);
- }
-
- /**
- * Checks if the scope of the given reference for the given context contains only the expected objects.
- * In addition, checks that the reference of the given context references at least one of the expected
- * objects. If the reference has multiplicity > 1, then every reference must reference at least
- * one of the expected objects.
- *
- * @param context
- * {@link EObject} from which the given objects shall be referenced, must not be {@code null}
- * @param reference
- * the structural feature of {@code context} for which the scope should be asserted, must not be {@code null} and part of the context element
- * @param expectedObjects
- * the objects expected in the scope, must not be {@code null}
- */
- protected void assertScopedObjects(final EObject context, final EReference reference, final Collection extends EObject> expectedObjects) {
- Assert.isNotNull(context, PARAMETER_CONTEXT);
- Assert.isNotNull(reference, PARAMETER_REFERENCE);
- Assert.isNotNull(expectedObjects, PARAMETER_EXPECTED_OBJECTS);
- Assert.isTrue(context.eClass().getEAllReferences().contains(reference), String.format("Contract for argument '%s' failed: Parameter is not within specified range (Expected: %s, Actual: %s).", PARAMETER_CONTEXT, "The context object must contain the given reference.", "Reference not contained by the context object!"));
- Set expectedUriSet = Sets.newHashSet();
- for (EObject object : expectedObjects) {
- expectedUriSet.add(EcoreUtil.getURI(object));
- }
- IScope scope = getScopeProvider().getScope(context, reference);
- Iterable allScopedElements = scope.getAllElements();
- Set scopedUriSet = Sets.newHashSet();
- for (IEObjectDescription description : allScopedElements) {
- URI uri = description.getEObjectURI();
- scopedUriSet.add(uri);
- }
- if (!expectedUriSet.equals(scopedUriSet)) {
- fail("The scope must exactly consist of the expected URIs. Missing " + Sets.difference(expectedUriSet, scopedUriSet) + " extra "
- + Sets.difference(scopedUriSet, expectedUriSet));
- }
- // test that link resolving worked
- boolean elementResolved;
- if (reference.isMany()) {
- @SuppressWarnings("unchecked")
- EList objects = (EList) context.eGet(reference, true);
- elementResolved = !objects.isEmpty(); // NOPMD
- for (Iterator objectIter = objects.iterator(); objectIter.hasNext() && elementResolved;) {
- EObject eObject = EcoreUtil.resolve(objectIter.next(), context);
- elementResolved = expectedUriSet.contains(EcoreUtil.getURI(eObject));
- }
- } else {
- EObject resolvedObject = (EObject) context.eGet(reference, true);
- elementResolved = expectedUriSet.contains(EcoreUtil.getURI(resolvedObject));
- }
- assertTrue("Linking must have resolved one of the expected objects.", elementResolved);
- }
-
- /**
- * Check if scope expected is found in context provided.
- *
- * @param context
- * element from which an element shall be referenced
- * @param reference
- * to be used to filter the elements
- * @param expectedName
- * name of scope element to look for
- * @param expectedUri
- * of source referenced
- */
- private void assertScope(final EObject context, final EReference reference, final QualifiedName expectedName, final URI expectedUri) {
- IScope scope = getScopeProvider().getScope(context, reference);
- Iterable descriptions = scope.getElements(expectedName);
- assertFalse("Description missing for: " + expectedName, Iterables.isEmpty(descriptions));
- URI currentUri = null;
- for (IEObjectDescription desc : descriptions) {
- currentUri = desc.getEObjectURI();
- if (currentUri.equals(expectedUri)) {
- return;
- }
- }
- assertEquals("Scope URI is not equal to expected URI", expectedUri, currentUri);
- }
-
- /**
- * Assert the scope for given elements.
- *
- * @param context
- * the context
- * @param reference
- * the reference
- * @param expectedSourceName
- * the name of the referenced source (without file extension)
- * @param expectedSourceType
- * type of scope element to look for
- * @param elementNames
- * array of tuples with the name and uri of each element
- */
- protected void assertScopeForElements(final EObject context, final EReference reference, final String expectedSourceName, final String expectedSourceType, final String[]... elementNames) {
- for (String[] elementName : elementNames) {
- assertScopeForElement(context, reference, elementName[0], expectedSourceName, expectedSourceType, elementName[1]);
- }
- int actualScopeSize = Iterables.size(getScopeProvider().getScope(context, reference).getAllElements());
- assertEquals(NUMBER_OF_ELEMENTS_MESSAGE, elementNames.length, actualScopeSize);
- }
-
- /**
- * Asserts the scope for the given context, reference, source type, and elements.
- *
- * @param context
- * the context object
- * @param reference
- * the reference feature
- * @param expectedSourceType
- * the source-type name
- * @param elements
- * list of triples with the expected elements, each triple ordered as: {element name, source name, URI fragment}
- */
- protected void assertScopeForElements(final EObject context, final EReference reference, final String expectedSourceType, final List> elements) {
- Iterable allElements = getScopeProvider().getScope(context, reference).getAllElements();
-
- // create a set containing the URIs (to avoid counting any duplicates the scope provider might have delivered)
- Set uris = new HashSet();
- for (IEObjectDescription d : allElements) {
- uris.add(d.getEObjectURI());
- }
-
- int actualScopeSizeWithoutDuplicates = uris.size();
- assertEquals(NUMBER_OF_ELEMENTS_MESSAGE, elements.size(), actualScopeSizeWithoutDuplicates);
- for (Triple elementName : elements) {
- assertScopeForElement(context, reference, elementName.getFirst(), elementName.getSecond(), expectedSourceType, elementName.getThird());
- }
- }
-
- /**
- * Asserts that the scope of the reference in the given context contains exactly the given sources.
- *
- * @param scopeContext
- * the context of the scope test
- * @param reference
- * the reference to check its scope for
- * @param modelElementClass
- * the {@link EClass} of the model element to find
- * @param sources
- * the array of sources
- */
- protected void assertScopeForSources(final EObject scopeContext, final EReference reference, final EClass modelElementClass, final String... sources) {
- assertScope(scopeContext, reference, getExpectedURIs(scopeContext, modelElementClass, sources));
- int actualScopeSize = Iterables.size(getScopeProvider().getScope(scopeContext, reference).getAllElements());
- assertEquals(NUMBER_OF_ELEMENTS_MESSAGE, sources.length, actualScopeSize);
- }
-
- /**
- * Returns the expected uris for the given sources in the given context.
- *
- * @param context
- * the context
- * @param modelElementClass
- * the class of the exported model element
- * @param sources
- * the sources to get the uris for
- * @return the expected uris for the given sources in the given context
- */
- private Set getExpectedURIs(final EObject context, final EClass modelElementClass, final String... sources) {
- Set expectedURIs = new HashSet();
- for (String source : sources) {
- expectedURIs.add(Iterables.get(getExportedObjects(context, modelElementClass, source), 0).getEObjectURI());
- }
- return expectedURIs;
- }
-
- /**
- * Gets the exported objects.
- *
- * @param context
- * the context
- * @param type
- * the type
- * @param resourcePattern
- * the resource pattern
- * @return the exported objects
- */
- public Iterable getExportedObjects(final EObject context, final EClass type, final String resourcePattern) {
- Pattern regexp = Regexps.fromGlob(URI.encodeSegment(resourcePattern, true));
- return Iterables.filter(ContainerQuery.newBuilder(domainMapper, type).execute(context), (o) -> regexp.matcher(o.getEObjectURI().lastSegment()).matches());
- }
-
- /**
- * Gets the exported names.
- *
- * @param execute
- * the execute
- * @return the exported names
- */
- public List getExportedNames(final Iterable execute) {
- return Lists.newArrayList(Iterables.transform(execute, new Function() {
- @Override
- public String apply(final IEObjectDescription from) {
- return from.getName().toString();
- }
- }));
- }
-
- /**
- * Checks if an object with given name (case sensitive) and type is exported.
- *
- * @param context
- * the context
- * @param name
- * the name
- * @param type
- * the type
- * @return true, if is exported
- */
- public boolean isExported(final EObject context, final String name, final EClass type) {
- return isExported(context, name, type, false);
- }
-
- /**
- * Checks if an object with given name, case sensitive or not, and type is exported.
- *
- * @param context
- * the context
- * @param name
- * the name
- * @param type
- * the type
- * @param ignoreCase
- * the ignore case
- * @return true, if is exported
- */
- public boolean isExported(final EObject context, final String name, final EClass type, final boolean ignoreCase) {
- List exportedNames = getExportedNames(ContainerQuery.newBuilder(domainMapper, type).execute(context));
- if (ignoreCase) {
- return Iterables.contains(Iterables.transform(exportedNames, new Function() {
- @Override
- public String apply(final String from) {
- return from.toLowerCase(); // NOPMD
- }
- }), name);
- } else {
- return exportedNames.contains(name);
- }
- }
-
- /**
- * Gets the resource description for a given Xtext resource.
- *
- * @param resource
- * the resource
- * @return the resource description
- */
- protected final IResourceDescription getResourceDescription(final XtextResource resource) {
- final IResourceServiceProvider resourceServiceProvider = resource.getResourceServiceProvider();
- final IResourceDescription.Manager descriptionManager = resourceServiceProvider.getResourceDescriptionManager();
- return descriptionManager.getResourceDescription(resource);
- }
-
- /**
- * Gets the fingerprint for a given resource description, returns null if resource description does not export any objects or if a non-existing
- * user data field was queried.
- *
- * @param description
- * the description
- * @return the fingerprint or null if no fingerprint found
- */
- protected String getFingerprint(final IResourceDescription description) {
- Iterable objects = description.getExportedObjects();
- if (!Iterables.isEmpty(objects)) {
- IEObjectDescription objectDescription = Iterables.get(objects, 0);
- return objectDescription.getUserData(IFingerprintComputer.RESOURCE_FINGERPRINT);
- }
- return null;
- }
-
- /**
- * Creates a top level URI fragment with a leading segment separator from the given segments
- * taking into account repetitions.
- *
- * @param segments
- * list of feature IDs, indexes (for multi valued features), and other fragment segments
- * @return URI fragment
- */
- public static String createTopLevelURIFragment(final Object... segments) {
- return createURIFragment(true, segments);
- }
-
- /**
- * Creates a URI fragment from the given segments taking into account repetitions.
- *
- * @param segments
- * list of feature IDs, indexes (for multi valued features), and other fragment segments
- * @return URI fragment
- */
- public static String createURIFragment(final Object... segments) {
- return createURIFragment(false, segments);
- }
-
- /**
- * Creates a URI fragment from the given segments taking into account repetitions.
- *
- * @param topLevel
- * whether the fragment is top level resulting in a leading segment separator.
- * @param segments
- * list of feature IDs, indexes (for multi valued features), and other fragment segments
- * @return URI fragment
- */
- @SuppressWarnings("PMD.UnusedPrivateMethod")
- private static String createURIFragment(final boolean topLevel, final Object... segments) {
- StringBuilder b = new StringBuilder();
- if (segments.length == 0) {
- return b.toString();
- }
- if (topLevel) {
- b.append(SEGMENT_SEPARATOR);
- }
- List parsedSegments = Lists.newArrayList();
- for (Object segment : segments) {
- Iterables.addAll(parsedSegments, FRAGMENT_SEGMENT_SPLITTER.split(segment.toString()));
- }
-
- String lastSegment = parsedSegments.get(0);
- int reps = 1;
- for (int i = 1; i < parsedSegments.size(); i++) {
- if (parsedSegments.get(i).equals(lastSegment)) {
- reps++;
- continue;
- }
- b.append(lastSegment);
- if (reps > 1) {
- b.append(REP_SEPARATOR).append(reps);
- reps = 1;
- }
- b.append(SEGMENT_SEPARATOR);
- lastSegment = parsedSegments.get(i);
- }
- b.append(lastSegment);
- if (reps > 1) {
- b.append(REP_SEPARATOR).append(reps);
- }
- return b.toString();
- }
-
- /**
- * Creates a URI fragment list segment for the given feature selection string and list index.
- *
- * @param feature
- * the feature selection string, must not be {@code null} or empty
- * @param index
- * the list index, must not be negative
- * @return the URI fragment list segment, never {@code null} or empty
- */
- public static String listFragmentSegment(final String feature, final int index) {
- return feature + AbstractFragmentProvider.LIST_SEPARATOR + index;
- }
-
- /**
- * Creates a URI fragment list segment for the given feature id and list index.
- *
- * @param featureId
- * the featureId, must not be negative
- * @param index
- * the list index, must not be negative
- * @return the URI fragment list segment, never {@code null} or empty
- */
- public static String listFragmentSegment(final int featureId, final int index) {
- return listFragmentSegment(String.valueOf(featureId), index);
- }
-
- /**
- * Creates a URI fragment segment to be used for languages using the {@code AbstractSelectorFragmentProvider}.
- *
- * @param containmentFeature
- * containment feature
- * @param selectorFeature
- * selector feature
- * @param value
- * value for selector feature
- * @param unique
- * if value is unique
- * @return URI fragment segment
- */
- public static String selectorFragmentSegment(final int containmentFeature, final int selectorFeature, final String value, final boolean unique) {
- StringBuilder builder = new StringBuilder();
- builder.append(containmentFeature).append(SELECTOR_START).append(selectorFeature).append(EQ_OP).append(VALUE_SEP).append(value).append(VALUE_SEP);
- if (unique) {
- builder.append(UNIQUE);
- }
- builder.append(SELECTOR_END);
- return builder.toString();
- }
-
- /**
- * Creates an expectation of a link. Use this method in tests to insert an expectation that a cross reference does actually point to the object tagged by the
- * target tag. Expectations can be tested by calling {@link #testExpectedLinking()}. Implicit items will be traversed.
- *
- * @see #mark(int)
- * @see #testLinking(String, CharSequence)
- * @param targetTag
- * Tag pointing to the destination object
- * @return Mark text to be inserted in the source file, never {@code null}
- */
- protected String link(final int targetTag) {
- return link(() -> getObjectForTag(targetTag));
- }
-
- /**
- * Creates an expectation of a link. Use this method in tests to insert an expectation that a cross reference does actually point to the object tagged by the
- * target tag. Expectations can be tested by calling {@link #testExpectedLinking()}. Implicit items will be traversed.
- *
- * @see #mark(int)
- * @see #testLinking(String, CharSequence)
- * @param getTargetObject
- * supplier to get the destination object, must not be {@code null}
- * @return Mark text to be inserted in the source file, never {@code null}
- */
- protected String link(final Supplier getTargetObject) {
- final int sourceTag = getTag();
- expectedLinkAssertions.add(() -> testLinking(sourceTag, getTargetObject.get()));
- return mark(sourceTag);
- }
-
- /**
- * Performs linking test. Checks expectations which were set in a source using {@link #link(int)} or {@link #link(Function, int).
- *
- * @see #link(int)
- * @see #link(Supplier)
- * @see #testLinking(int, EObject)
- * @param sourceFileNameAndContent
- * the file name and content, given as the key and value of the pair, respectively, must not be {@code null}
- */
- protected void testLinking(final Pair sourceFileNameAndContent) {
- testLinking(sourceFileNameAndContent.getKey(), sourceFileNameAndContent.getValue());
- }
-
- /**
- * Performs linking test. Checks expectations which were set in a source using {@link #link(int)} or {@link #link(Function, int).
- *
- * @see #link(int)
- * @see #link(Supplier)
- * @see #testLinking(int, EObject)
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- */
- protected void testLinking(final String sourceFileName, final CharSequence sourceContent) {
- registerModel(sourceFileName, sourceContent);
- expectedLinkAssertions.forEach(Runnable::run);
- expectedLinkAssertions.clear();
- }
-
- /**
- * Performs linking test. Checks that given cross reference tagged with sourceTag does actually point to the object tagged by the target tag.
- * Detailed error reporting can be viewed in a compare view. Implicit items will be traversed.
- *
- * @param sourceTag
- * Tag pointing to cross reference
- * @param targetTag
- * Tag pointing to the destination object
- */
- protected void testLinking(final int sourceTag, final int targetTag) {
- testLinking(sourceTag, getObjectForTag(targetTag), true);
- }
-
- /**
- * Performs linking test. Checks that the cross reference marked with sourceTag does actually point to the object provided as the second argument. Implicit
- * items will be traversed.
- *
- * @param sourceTag
- * Tag pointing to a cross reference
- * @param targetObject
- * Expected target object
- */
- protected void testLinking(final int sourceTag, final EObject targetObject) {
- testLinking(sourceTag, targetObject, true);
- }
-
- /**
- * Performs linking test. Checks that the source object is the same as the object pointed by targetTag provided as the second argument. Implicit
- * items will be traversed.
- *
- * @param sourceObject
- * Source object
- * @param targetTag
- * Tag to the expected target object
- */
- protected void testLinking(final EObject sourceObject, final int targetTag) {
- testLinking(sourceObject, targetTag, true);
- }
-
- /**
- * Performs linking test. Checks that the cross reference marked with sourceTag does actually point to the object provided as the second argument.
- *
- * @param sourceTag
- * Tag pointing to a cross reference
- * @param targetObject
- * Expected target object, must not be {@code null}
- * @param traverseImplicitItems
- * If target of a reference is an implicit item and this parameter is set to true, the test will get and compare the original object from which this
- * implicit item was created
- */
- protected void testLinking(final int sourceTag, final EObject targetObject, final boolean traverseImplicitItems) {
- assertNotNull("Target object must not be null.", targetObject); //$NON-NLS-1$
- CrossReference crossReference = getMarkerTagsInfo().getCrossReference(sourceTag);
- EObject referencedSourceObject = getCrossReferencedObject(sourceTag, traverseImplicitItems, crossReference);
- assertEObjectsAreEqual(referencedSourceObject, targetObject, crossReference);
- }
-
- /**
- * Performs linking test. Checks that the source object is the same as the object pointed by targetTag provided as the second argument.
- * Does not deal with cross-referencing.
- *
- * @param sourceObject
- * Source object, must not be {@code null}
- * @param targetTag
- * Tag to the referenced target object
- * @param traverseImplicitItems
- * If target of a reference is an implicit item and this parameter is set to true, the test will get and compare the original object from which this
- * implicit item was created
- */
- @SuppressWarnings("PMD.UnusedFormalParameter")
- protected void testLinking(final EObject sourceObject, final int targetTag, final boolean traverseImplicitItems) {
- assertNotNull("Source object must not be null.", sourceObject); //$NON-NLS-1$
- EObject referencedTargetObject = getObjectForTag(targetTag);
- assertEObjectsAreEqual(sourceObject, referencedTargetObject, null);
- }
-
- /**
- * Asserts whether the two objects are equal.
- *
- * @param sourceObject
- * First object needed for comparison.
- * @param targetObject
- * Target object needed for comparison.
- * @param crossReference
- * CrossReference object, can be {@code null}
- */
- protected void assertEObjectsAreEqual(final EObject sourceObject, final EObject targetObject, final CrossReference crossReference) {
- StringBuilder expected = new StringBuilder(80);
- StringBuilder found = new StringBuilder(80);
- if (crossReference != null) {
- String crossReferenceText = "Cross reference:\n" + crossReference.toString() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
- expected.append(crossReferenceText);
- found.append(crossReferenceText);
- }
- expected.append(LINKS_TO);
- found.append(LINKS_TO);
- URI targetUri = EcoreUtil.getURI(targetObject);
- expected.append(targetUri);
- String sourceObjectUri = EcoreUtil.getURI(sourceObject).toString();
- found.append(sourceObjectUri);
- expected.append(WHICH_CORRESPONDS_TO);
- INode node;
- node = NodeModelUtils.findActualNodeFor(targetObject);
- if (node != null) {
- expected.append(NodeModelUtils.getTokenText(node));
- } else {
- expected.append(NO_NODE_MODEL_COULD_BE_A_DERIVED_OBJECT);
- }
- found.append(WHICH_CORRESPONDS_TO);
- node = NodeModelUtils.findActualNodeFor(sourceObject);
- if (sourceObject.eIsProxy()) {
- found.append(UNRESOLVED_REFERENCE);
- } else if (node != null) {
- found.append(NodeModelUtils.getTokenText(node));
- } else {
- found.append(NO_NODE_MODEL_COULD_BE_A_DERIVED_OBJECT);
- }
- assertEquals("Errors found. Consider compare view.", expected.toString(), found.toString()); //$NON-NLS-1$
- }
-
- /**
- * Returns the referenced {@link EObject} pointed to by the cross reference.
- *
- * Note: For implicit item traversal to work, a custom implementation must be provided by overriding this method.
- *
- *
- * @param sourceTag
- * the source tag
- * @param traverseImplicitItems
- * If target of a reference is an implicit item and this parameter is set to true, the test will get and compare the original object from which this
- * implicit item was created.
- * @param crossReference
- * Cross reference to be resolved, must not be {@code null}
- * @return the referenced {@link EObject}, must not be {@code null}
- */
- @SuppressWarnings("PMD.UnusedFormalParameter")
- protected EObject getCrossReferencedObject(final int sourceTag, final boolean traverseImplicitItems, final CrossReference crossReference) {
- EObject context = getObjectForTag(sourceTag);
- if (crossReference == null) {
- throw new IllegalArgumentException(NLS.bind("Cross reference on object ''{0}'' could not be resolved.", context.toString())); //$NON-NLS-1$
- }
- // We only handle references in assignments
- Assignment assignment = EcoreUtil2.getContainerOfType(crossReference, Assignment.class);
- EObject sourceObject;
- String featureName = assignment.getFeature();
- EReference reference = (EReference) context.eClass().getEStructuralFeature(featureName);
- if (reference.isMany()) {
- Object featureValue = context.eGet(reference, false);
- assertTrue("List must be of type EObjectResolvingEList", featureValue instanceof EObjectResolvingEList); //$NON-NLS-1$
- @SuppressWarnings("unchecked")
- EList extends EObject> objects = (EObjectResolvingEList extends EObject>) context.eGet(reference, false);
- if (objects.size() == 1) {
- sourceObject = EcoreUtil.resolve(objects.get(0), context);
- } else {
- // TODO DSL-166: Handle this case when needed for tests.
- throw new AssertionError("Multiple references not supported yet"); //$NON-NLS-1$
- }
- } else {
- sourceObject = (EObject) context.eGet(reference, true);
- }
- assertNotNull("Bad test. Referenced object is null.", sourceObject); //$NON-NLS-1$
- return sourceObject;
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/AbstractValidationTest.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/AbstractValidationTest.java
deleted file mode 100644
index 7f529b690..000000000
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/AbstractValidationTest.java
+++ /dev/null
@@ -1,1221 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.test.validation;
-
-import static org.eclipse.xtext.validation.ValidationMessageAcceptor.INSIGNIFICANT_INDEX;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.eclipse.emf.common.util.BasicDiagnostic;
-import org.eclipse.emf.common.util.Diagnostic;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.xtext.EcoreUtil2;
-import org.eclipse.xtext.diagnostics.AbstractDiagnostic;
-import org.eclipse.xtext.linking.impl.XtextLinkingDiagnostic;
-import org.eclipse.xtext.nodemodel.ICompositeNode;
-import org.eclipse.xtext.nodemodel.INode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.resource.XtextResource;
-import org.eclipse.xtext.resource.XtextSyntaxDiagnostic;
-import org.eclipse.xtext.util.CancelIndicator;
-import org.eclipse.xtext.validation.AbstractValidationDiagnostic;
-import org.eclipse.xtext.validation.FeatureBasedDiagnostic;
-import org.eclipse.xtext.validation.RangeBasedDiagnostic;
-import org.eclipse.xtext.xbase.lib.Pair;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextMarkerBasedTest;
-import com.avaloq.tools.ddk.xtext.test.XtextTestSource;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.inject.Provider;
-
-
-/**
- * Base class for validation tests.
- */
-@SuppressWarnings({"nls", "PMD.ExcessiveClassLength"})
-// CHECKSTYLE:CHECK-OFF MultipleStringLiterals
-// CHECKSTYLE:OFF MagicNumber
-public abstract class AbstractValidationTest extends AbstractXtextMarkerBasedTest {
-
- public static final int NO_ERRORS = 0;
-
- static final String NO_ERRORS_FOUND_ON_RESOURCE_MESSAGE = "Expecting no errors on resource";
-
- private static final int SEVERITY_UNDEFINED = -1;
- private static final Map CODE_TO_NAME = ImmutableMap.of(Diagnostic.INFO, "INFO", Diagnostic.WARNING, "WARNING", Diagnostic.ERROR, "ERROR");
-
- private static final String LINE_BREAK = "\n";
- private static final String DOT_AND_LINEBREAK = "'." + LINE_BREAK;
-
- /**
- * All diagnostics of the current testing file.
- */
- private Diagnostic fileDiagnostics;
-
- /**
- * During validation of a source we monitor diagnostics, that are found in the source but were not expected by the test.
- * If the validation test is strict, then we will display these unexpected diagnostics as test error.
- */
- private final Set unexpectedDiagnostics = Sets.newLinkedHashSet();
- private final Set unexpectedResourceDiagnostics = Sets.newLinkedHashSet();
-
- /**
- * validation results calculated during test setUp.
- *
- * @return the diagnostic for the primary test source file
- */
- private Diagnostic getPrimaryDiagnostics() {
- Object obj = getTestInformation().getTestObject(Diagnostic.class);
- assertNotNull("getPrimaryDiagnostics(): Diagnostics of primary source not null.", obj);
- return (Diagnostic) obj;
- }
-
- /**
- * Returns the unexpectedDiagnostics.
- *
- * @return the unexpectedDiagnostics
- */
- protected Set getUnexpectedDiagnostics() {
- return unexpectedDiagnostics;
- }
-
- /**
- * Returns the unexpectedDiagnostics.
- *
- * @return the unexpectedDiagnostics
- */
- protected Set getUnexpectedResourceDiagnostics() {
- return unexpectedResourceDiagnostics;
- }
-
- /**
- * Assertion testing for {@link AbstractValidationDiagnostic validation issues} at a given source position.
- */
- protected class XtextDiagnosticAssertion extends AbstractModelAssertion {
-
- /** Issue code of the diagnostic. */
- private final String issueCode;
- /** Issue message of the diagnostic. */
- private final String message;
- /**
- * Indicates whether the assertion must find the issue.
- * Assertion creates an error if the existence of issue code for the target eobject doesn't correspond to the value of issueMustBeFound.
- */
- private final boolean issueMustBeFound;
-
- private final int expectedSeverity;
-
- protected XtextDiagnosticAssertion(final String issueCode, final boolean issueMustBeFound) {
- this(issueCode, issueMustBeFound, SEVERITY_UNDEFINED, null);
- }
-
- protected XtextDiagnosticAssertion(final String issueCode, final boolean issueMustBeFound, final int severity, final String message) {
- this.issueCode = issueCode;
- this.issueMustBeFound = issueMustBeFound;
- this.expectedSeverity = severity;
- this.message = message;
- }
-
- /**
- * Check if the given issue code is found among issue codes for the object, located at the given position.
- *
- * @param root
- * root object of the document
- * @param pos
- * position to locate the target object
- */
- @Override
- public void apply(final EObject root, final Integer pos) {
- final Diagnostic diagnostics = validate(root);
- final BasicDiagnostic diagnosticsOnTargetPosition = new BasicDiagnostic();
- boolean issueFound = false;
- int actualSeverity = SEVERITY_UNDEFINED;
- boolean expectedSeverityMatches = false;
- boolean expectedMessageMatches = false;
- String actualMessage = "";
-
- for (AbstractValidationDiagnostic avd : Iterables.filter(diagnostics.getChildren(), AbstractValidationDiagnostic.class)) {
- if (diagnosticPositionEquals(pos, avd)) {
- // Add issue to the list of issues at the given position
- diagnosticsOnTargetPosition.add(avd);
- if (avd.getIssueCode().equals(issueCode)) {
- issueFound = true;
- actualSeverity = avd.getSeverity();
- // True if the expected severity is not set, or if matches with the actual one
- expectedSeverityMatches = expectedSeverity == SEVERITY_UNDEFINED || expectedSeverity == actualSeverity;
- actualMessage = avd.getMessage();
- // True if message matches with actual message or message is null
- expectedMessageMatches = message == null || actualMessage.equals(message);
- if (issueMustBeFound) {
- // Remove the diagnostic from the list of non-expected diagnostics
- getUnexpectedDiagnostics().remove(avd);
- // Don't need to display error messages
- if (expectedSeverityMatches && expectedMessageMatches) {
- return;
- }
- }
- }
- }
- }
-
- // Create error message
- createErrorMessage(pos, diagnosticsOnTargetPosition, issueFound, expectedSeverityMatches, actualSeverity, expectedMessageMatches, actualMessage);
- }
-
- /**
- * Create an error message (if needed) based on the given input parameters.
- *
- * @param pos
- * position in the source to associate the message with
- * @param diagnosticsOnTargetPosition
- * diagnostics on the specifies position
- * @param issueFound
- * specifies whether an issue has been found at the given position
- * @param expectedSeverityMatches
- * true if expected severity equals actual one, false otherwise
- * @param actualSeverity
- * actual severity
- * @param expectedMessageMatches
- * expected message matches
- * @param actualMessage
- * actual message
- */
- private void createErrorMessage(final Integer pos, final BasicDiagnostic diagnosticsOnTargetPosition, final boolean issueFound, final boolean expectedSeverityMatches, final int actualSeverity, final boolean expectedMessageMatches, final String actualMessage) {
- StringBuilder errorMessage = new StringBuilder(180);
- if (issueMustBeFound && !issueFound) {
- errorMessage.append("Expected issue not found. Code '").append(issueCode).append('\n');
- } else if (!issueMustBeFound && issueFound) {
- errorMessage.append("There should be no issue with the code '").append(issueCode).append(DOT_AND_LINEBREAK);
- }
- if (issueFound && !expectedMessageMatches) {
- errorMessage.append("Expected message does not match. Expected: '").append(message).append("', Actual: '").append(actualMessage).append('\n');
- }
- // If the expected issue has been found, but the actual severity does not match with expected one
- if (issueMustBeFound && issueFound && !expectedSeverityMatches) {
- errorMessage.append("Severity does not match. Expected: ").append(CODE_TO_NAME.get(expectedSeverity)).append(". Actual: ").append(CODE_TO_NAME.get(actualSeverity)).append(".\n");
- }
- // Memorize error message
- if (errorMessage.length() > 0) {
- if (!diagnosticsOnTargetPosition.getChildren().isEmpty()) {
- errorMessage.append(" All issues at this position:\n");
- errorMessage.append(diagnosticsToString(diagnosticsOnTargetPosition, false));
- }
- memorizeErrorOnPosition(pos, errorMessage.toString());
- }
- }
-
- /**
- * Compare if the position of the given diagnostic equals to the given position in text.
- *
- * @param pos
- * position in text
- * @param avd
- * diagnostic that we check, if it has the same position as the given position in text
- * @return
- * TRUE if diagnostic has the same position as the given one, FALSE otherwise.
- */
- protected boolean diagnosticPositionEquals(final Integer pos, final AbstractValidationDiagnostic avd) {
- if (avd instanceof FeatureBasedDiagnostic && ((FeatureBasedDiagnostic) avd).getFeature() != null) {
- List nodes = NodeModelUtils.findNodesForFeature(avd.getSourceEObject(), ((FeatureBasedDiagnostic) avd).getFeature());
- if (nodes.isEmpty()) {
- INode node = NodeModelUtils.getNode(avd.getSourceEObject());
- INode firstNonHiddenLeafNode = getXtextTestUtil().findFirstNonHiddenLeafNode(node);
- if (firstNonHiddenLeafNode == null) {
- return issueMustBeFound;
- } else if (firstNonHiddenLeafNode.getTotalOffset() == pos) {
- return true;
- }
- } else {
- int avdIndex = ((FeatureBasedDiagnostic) avd).getIndex();
- for (int i = 0; i < nodes.size(); i++) {
- if (avdIndex == INSIGNIFICANT_INDEX || avdIndex == i) {
- INode firstNonHiddenLeafNode = getXtextTestUtil().findFirstNonHiddenLeafNode(nodes.get(i));
- if (firstNonHiddenLeafNode == null) {
- return issueMustBeFound;
- } else if (firstNonHiddenLeafNode.getTotalOffset() == pos) {
- return true;
- }
- }
- }
- }
- } else if (avd instanceof RangeBasedDiagnostic) {
- if (((RangeBasedDiagnostic) avd).getOffset() == pos) {
- return true;
- }
- } else {
- INode node = NodeModelUtils.getNode(avd.getSourceEObject());
- INode firstNonHiddenLeafNode = getXtextTestUtil().findFirstNonHiddenLeafNode(node);
- if (firstNonHiddenLeafNode == null) {
- return issueMustBeFound;
- } else if (firstNonHiddenLeafNode.getTotalOffset() == pos) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Assertion testing for {@link AbstractValidationDiagnostic validation issues} at a given source position.
- */
- private class ResourceDiagnosticAssertion extends AbstractModelAssertion {
-
- /** Issue code of the diagnostic. */
- private final String issueCode;
- /** Issue message of the diagnostic. */
- private final String message;
- /**
- * Indicates whether the assertion must find the issue.
- * Assertion creates an error if the existence of issue code for the target eobject doesn't correspond to the value of issueMustBeFound.
- */
- private final boolean issueMustBeFound;
-
- private final int expectedSeverity;
-
- protected ResourceDiagnosticAssertion(final String issueCode, final boolean issueMustBeFound, final int severity, final String message) {
- this.issueCode = issueCode;
- this.issueMustBeFound = issueMustBeFound;
- this.expectedSeverity = severity;
- this.message = message;
- }
-
- /**
- * Check if the given issue code is found among issue codes for the object, located at the given position.
- *
- * @param root
- * root object of the document
- * @param pos
- * position to locate the target object
- */
- @Override
- public void apply(final EObject root, final Integer pos) {
- Iterable diagnostics = null;
- switch (expectedSeverity) {
- case Diagnostic.ERROR:
- diagnostics = root.eResource().getErrors();
- break;
- case Diagnostic.WARNING:
- diagnostics = root.eResource().getWarnings();
- break;
- case SEVERITY_UNDEFINED:
- diagnostics = Iterables.concat(root.eResource().getErrors(), root.eResource().getWarnings());
- break;
- }
- final List diagnosticsOnTargetPosition = Lists.newArrayList();
- boolean issueFound = false;
- int actualSeverity = expectedSeverity;
- boolean expectedMessageMatches = false;
- String actualMessage = "";
-
- for (AbstractDiagnostic diag : Iterables.filter(diagnostics, AbstractDiagnostic.class)) {
- if (diagnosticPositionEquals(pos, diag)) {
- // Add issue to the list of issues at the given position
- diagnosticsOnTargetPosition.add(diag);
- if (diag.getCode() != null && diag.getCode().equals(issueCode)) {
- issueFound = true;
- if (expectedSeverity == SEVERITY_UNDEFINED) {
- actualSeverity = root.eResource().getErrors().contains(diag) ? Diagnostic.ERROR : Diagnostic.WARNING;
- }
- actualMessage = diag.getMessage();
- // True if message matches with actual message or message is null
- expectedMessageMatches = message == null || actualMessage.equals(message);
- // Don't need to display error messages
- if (issueMustBeFound) {
- // Remove the diagnostic from the list of non-expected diagnostics
- getUnexpectedResourceDiagnostics().remove(diag);
- // Don't need to display error messages
- if (expectedMessageMatches) {
- return;
- }
- }
- }
- }
- }
-
- // Create error message
- createErrorMessage(pos, diagnosticsOnTargetPosition, issueFound, true, actualSeverity, expectedMessageMatches, actualMessage);
- }
-
- /**
- * Create an error message (if needed) based on the given input parameters.
- *
- * @param pos
- * position in the source to associate the message with
- * @param diagnosticsOnTargetPosition
- * diagnostics on the specifies position
- * @param issueFound
- * specifies whether an issue has been found at the given position
- * @param expectedSeverityMatches
- * true if expected severity equals actual one, false otherwise
- * @param actualSeverity
- * actual severity
- * @param expectedMessageMatches
- * expected message matches
- * @param actualMessage
- * actual message
- */
- private void createErrorMessage(final Integer pos, final List diagnosticsOnTargetPosition, final boolean issueFound, final boolean expectedSeverityMatches, final int actualSeverity, final boolean expectedMessageMatches, final String actualMessage) {
- StringBuilder errorMessage = new StringBuilder(200);
- if (issueMustBeFound && !issueFound) {
- errorMessage.append("Expected issue not found. Code '").append(issueCode).append('\n');
- } else if (!issueMustBeFound && issueFound) {
- errorMessage.append("There should be no issue with the code '").append(issueCode).append(DOT_AND_LINEBREAK);
- }
- if (issueFound && !expectedMessageMatches) {
- errorMessage.append("Expected message does not match. Expected: '").append(message).append("', Actual: '").append(actualMessage).append('\n');
- }
- // If the expected issue has been found, but the actual severity does not match with expected one
- if (issueMustBeFound && issueFound && !expectedSeverityMatches) {
- errorMessage.append("Severity does not match. Expected: ").append(CODE_TO_NAME.get(expectedSeverity)).append(". Actual: ").append(CODE_TO_NAME.get(actualSeverity)).append(".\n");
- }
- // Memorize error message
- if (errorMessage.length() > 0) {
- if (!diagnosticsOnTargetPosition.isEmpty()) {
- errorMessage.append(" All issues at this position:\n");
- errorMessage.append(diagnosticsToString(diagnosticsOnTargetPosition, false));
- }
- memorizeErrorOnPosition(pos, errorMessage.toString());
- }
- }
-
- /**
- * Compare if the position of the given diagnostic equals to the given position in text.
- *
- * @param pos
- * position in text
- * @param diagnostic
- * diagnostic that we check, if it has the same position as the given position in text
- * @return
- * {@code true} if diagnostic has the same position as the given one, {@code false} otherwise.
- */
- private boolean diagnosticPositionEquals(final Integer pos, final AbstractDiagnostic diagnostic) {
- return diagnostic.getOffset() == pos;
- }
- }
-
- /**
- * Get a cached version of an object associated with the root object for a given key.
- *
- * @param
- * type of the associated object
- * @param root
- * root EObject
- * @param key
- * key identifying the type of the associated object
- * @param provider
- * provider to deliver an object if there is no cached version
- * @return
- * cached version of the associated object
- */
- protected T getCached(final EObject root, final String key, final Provider provider) {
- XtextResource res = (XtextResource) root.eResource();
- return res.getCache().get(key, res, provider);
- }
-
- /**
- * Validate the model.
- *
- * @param root
- * root EObject to validate
- * @return
- * validation results
- */
- protected Diagnostic validate(final EObject root) {
- return getCached(root, "DIAGNOSTIC", () -> getXtextTestUtil().getDiagnostician().validate(root));
- }
-
- /**
- * Display the path from root object to the target EObject.
- *
- * @param eObject
- * object to display the object path for
- * @param offset
- * string offset that is added in the beginning of each line
- * @return
- * object hierarchy as string (each object on a single line)
- */
- private String pathFromRootAsString(final EObject eObject, final String offset) {
- List hierarchy = Lists.newLinkedList();
-
- EObject currentObject = eObject;
- while (currentObject != null) {
- hierarchy.add(0, offset + currentObject.toString());
- currentObject = currentObject.eContainer();
- }
-
- return String.join("\n", hierarchy);
- }
-
- /**
- * Persist list diagnostics into string to display the list of issue codes.
- *
- * @param diagnostics
- * list of diagnostics
- * @param displayPathToTargetObject
- * if true, the path through the object hierarchy is printed out up to the root node
- * @return
- * string with list of issue codes, separated with a line break
- */
- // TODO (ACF-4153) generalize for all kinds of errors and move to AbstractXtextTest
- private String diagnosticsToString(final Diagnostic diagnostics, final boolean displayPathToTargetObject) {
- StringBuilder sb = new StringBuilder();
- for (Diagnostic diagnostic : diagnostics.getChildren()) {
- if (diagnostic instanceof AbstractValidationDiagnostic) {
- AbstractValidationDiagnostic avd = (AbstractValidationDiagnostic) diagnostic;
- sb.append(" ");
- sb.append(avd.getIssueCode());
- if (displayPathToTargetObject) {
- sb.append(" at line: ");
- ICompositeNode compositeNode = NodeModelUtils.findActualNodeFor(avd.getSourceEObject());
- if (compositeNode != null) {
- sb.append(compositeNode.getStartLine());
- } else {
- sb.append("Unknown");
- }
- sb.append(" on \n");
- sb.append(pathFromRootAsString(avd.getSourceEObject(), " "));
- }
- sb.append(LINE_BREAK);
- }
- }
- return sb.toString();
- }
-
- /**
- * Persist list diagnostics into string to display the list of issue codes.
- *
- * @param diagnostics
- * list of diagnostics
- * @param displayPathToTargetObject
- * if true, the path through the object hierarchy is printed out up to the root node
- * @return
- * string with list of issue codes, separated with a line break
- */
- // TODO (ACF-4153) generalize for all kinds of errors and move to AbstractXtextTest
- private String diagnosticsToString(final List diagnostics, final boolean displayPathToTargetObject) {
- StringBuilder sb = new StringBuilder(25);
- for (Resource.Diagnostic diagnostic : diagnostics) {
- if (diagnostic instanceof AbstractDiagnostic) {
- AbstractDiagnostic diag = (AbstractDiagnostic) diagnostic;
- sb.append(" ");
- sb.append(diag.getCode());
- if (displayPathToTargetObject) {
- sb.append(" at line: ");
- sb.append(diag.getLine());
- sb.append(" on \n");
- sb.append(" ");
- sb.append(diag.getUriToProblem());
- }
- sb.append(LINE_BREAK);
- }
- }
- return sb.toString();
- }
-
- @Override
- protected void beforeAllTests() {
- super.beforeAllTests();
- if (getTestSource() != null) {
- Diagnostic primaryDiagnostics = getXtextTestUtil().getDiagnostician().validate(getSemanticModel());
- getTestInformation().putTestObject(Diagnostic.class, primaryDiagnostics);
- }
- }
-
- /**
- * Register a new validation marker with the given issue code. Expects an info.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String info(final String issueCode) {
- return info(issueCode, null);
- }
-
- /**
- * Register a new validation marker with the given issue code and message. Expects an info.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @param message
- * the expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String info(final String issueCode, final String message) {
- return addAssertion(new XtextDiagnosticAssertion(issueCode, true, Diagnostic.INFO, message));
- }
-
- /**
- * Register a new validation marker with the given issue code. Expects a warning if the condition is {@code true}, no diagnostic otherwise.
- *
- * @param condition
- * the condition when the marker is expected
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String warningIf(final boolean condition, final String issueCode) {
- if (condition) {
- return warning(issueCode);
- } else {
- return noDiagnostic(issueCode);
- }
- }
-
- /**
- * Register a new validation marker with the given issue code. Expects a warning.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String warning(final String issueCode) {
- return warning(issueCode, null);
- }
-
- /**
- * Register a new validation marker with the given issue code and message. Expects a warning.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @param message
- * the expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String warning(final String issueCode, final String message) {
- return addAssertion(new XtextDiagnosticAssertion(issueCode, true, Diagnostic.WARNING, message));
- }
-
- /**
- * Register a new validation marker with the given issue code. Expects an error if the condition is {@code true}, no diagnostic otherwise.
- *
- * @param condition
- * the condition when the marker is expected
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String errorIf(final boolean condition, final String issueCode) {
- if (condition) {
- return error(issueCode);
- } else {
- return noDiagnostic(issueCode);
- }
- }
-
- /**
- * Register a new validation marker with the given issue code. Expects an error.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String error(final String issueCode) {
- return error(issueCode, null);
- }
-
- /**
- * Register a new validation marker with the given issue code and message. Expects an error.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @param message
- * the expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String error(final String issueCode, final String message) {
- return addAssertion(new XtextDiagnosticAssertion(issueCode, true, Diagnostic.ERROR, message));
- }
-
- /**
- * Register a new validation marker with the given issue code.
- * The issue is expected to be found in the test file.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String diagnostic(final String issueCode) {
- return diagnostic(issueCode, null);
- }
-
- /**
- * Register a new validation marker with the given issue code and message.
- * The issue and message are expected to be found in the test file.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @param message
- * the expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String diagnostic(final String issueCode, final String message) {
- return addAssertion(new XtextDiagnosticAssertion(issueCode, true, SEVERITY_UNDEFINED, message));
- }
-
- /**
- * Register a new linking error validation marker.
- * The issue is expected to be found in the test file.
- *
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String linkingError() {
- return linkingError(null);
- }
-
- /**
- * Register a new linking error validation marker with the given message.
- * The issue is expected to be found in the test file.
- *
- * @param message
- * issuethe expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String linkingError(final String message) {
- return addAssertion(new ResourceDiagnosticAssertion(org.eclipse.xtext.diagnostics.Diagnostic.LINKING_DIAGNOSTIC, true, Diagnostic.ERROR, message));
- }
-
- /**
- * Register a new resource validation marker with the given issue code and message.
- * The issue is expected to be found in the test file.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @param message
- * the expected issue message
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String resourceDiagnostic(final String issueCode, final String message) {
- return addAssertion(new ResourceDiagnosticAssertion(issueCode, true, Diagnostic.ERROR, message));
- }
-
- /**
- * Register a new validation marker with the given issue code.
- * The issue is expected NOT to be found in the test file.
- *
- * @param issueCode
- * issue code (usually found as static constant of the JavaValidator class of the DSL being tested)
- * @return
- * unique marker that can be used in the input string to mark a position that should be validated
- */
- protected String noDiagnostic(final String issueCode) {
- return addAssertion(new XtextDiagnosticAssertion(issueCode, false));
- }
-
- @Override
- protected void beforeApplyAssertions(final XtextTestSource testSource) {
- super.beforeApplyAssertions(testSource);
- EObject root = testSource.getModel();
- // Get all diagnostics of the current testing file
- EcoreUtil2.resolveLazyCrossReferences(root.eResource(), CancelIndicator.NullImpl);
- fileDiagnostics = validate(root);
- getUnexpectedDiagnostics().addAll(fileDiagnostics.getChildren());
- getUnexpectedResourceDiagnostics().addAll(root.eResource().getErrors());
- getUnexpectedResourceDiagnostics().addAll(root.eResource().getWarnings());
- }
-
- @Override
- protected String getAdditionalErrorMessageInformation() {
- return diagnosticsToString(fileDiagnostics, true);
- }
-
- @Override
- protected void afterValidate() {
- super.afterValidate();
- // Garbage collection
- getUnexpectedDiagnostics().clear();
- getUnexpectedResourceDiagnostics().clear();
- }
-
- /**
- * Assert that diagnosticList contains a diagnostic of the given issueCode.
- *
- * @param issueCode
- * the code of the issue to look for
- */
- protected void assertDiagnostic(final String issueCode) {
- assertDiagnostic(getPrimaryDiagnostics(), issueCode);
- }
-
- /**
- * Assert that the given EObject model contains a diagnostic of the given issueCode.
- *
- * @param model
- * the model in which to look for issues, may be {@code null}
- * @param issueCode
- * the code of the issue to look for
- */
- protected void assertDiagnostic(final EObject model, final String issueCode) {
- assertNotNull("Issue with code '" + issueCode + "' cannot be found because the model is null", model);
- assertDiagnostic(getXtextTestUtil().getDiagnostician().validate(model), issueCode);
- }
-
- /**
- * Assert that diagnosticList does not contain a diagnostic of the given issueCode.
- *
- * @param issueCode
- * the code of the issue to look for
- */
- protected void assertNoDiagnostic(final String issueCode) {
- assertNoDiagnostic(getPrimaryDiagnostics(), issueCode);
- }
-
- /**
- * Assert that the given EObject model does not contain a diagnostic of the given issueCode.
- *
- * @param model
- * the model in which to look for issues, may be {@code null}
- * @param issueCode
- * the code of the issue to look for
- */
- protected void assertNoDiagnostic(final EObject model, final String issueCode) {
- assertNotNull("Issue with code '" + issueCode + "' cannot be found because the model is null", model);
- assertNoDiagnostic(getXtextTestUtil().getDiagnostician().validate(model), issueCode);
- }
-
- /**
- * Assert that diagnosticList does not contain any diagnostic.
- */
- protected void assertNoDiagnostics() {
- assertNoDiagnostics(getPrimaryDiagnostics());
- }
-
- /**
- * Assert that the given EObject model does not contain any diagnostic.
- *
- * @param model
- * the model in which to look for issues, may be {@code null}
- */
- protected void assertNoDiagnostics(final EObject model) {
- assertNotNull("Assertion cannot be checked because the model is null", model);
- assertNoDiagnostics(getXtextTestUtil().getDiagnostician().validate(model));
- }
-
- /**
- * Assert that diagnosticList contains a diagnostic with the given message.
- *
- * @param message
- * the message of the issue to look for
- */
- protected void assertDiagnosticMessage(final String message) {
- assertDiagnosticMessage(getPrimaryDiagnostics(), message);
- }
-
- /**
- * Assert that the given EObject model contains a diagnostic with the given message.
- *
- * @param model
- * the model in which to look for issues, may be {@code null}
- * @param message
- * the message of the issue to look for
- */
- protected void assertDiagnosticMessage(final EObject model, final String message) {
- assertNotNull("Message '" + message + "' cannot be found because the model is null", model);
- assertDiagnosticMessage(getXtextTestUtil().getDiagnostician().validate(model), message);
- }
-
- /**
- * Assert that diagnosticList contains a diagnostic with the given message.
- *
- * @param diagnostics
- * the diagnostic to check for issues
- * @param message
- * the message of the issue to look for
- */
- private static void assertDiagnosticMessage(final Diagnostic diagnostics, final String message) {
- for (Diagnostic diagnostic : diagnostics.getChildren()) {
- if (diagnostic.getMessage().equals(message)) {
- return;
- }
- }
- fail("Issue with message ' " + message + "' not found");
- }
-
- /**
- * Assert that diagnosticList contains a diagnostic of the given issueCode.
- *
- * @param diagnostics
- * the diagnostic to check for issues
- * @param issueCode
- * the code of the issue to look for
- */
- private void assertDiagnostic(final Diagnostic diagnostics, final String issueCode) {
- for (Diagnostic diagnostic : diagnostics.getChildren()) {
- if (diagnostic instanceof AbstractValidationDiagnostic && ((AbstractValidationDiagnostic) diagnostic).getIssueCode().equals(issueCode)) {
- return;
- }
- }
- fail("Issue with code '" + issueCode + "' not found");
- }
-
- /**
- * Assert that diagnosticList contains a diagnostic of the given issueCode on a given EObject.
- * For performance reasons one can validate the root object and afterwards use this method
- * to check that a particular diagnostic exists on one of the child objects of the validated model.
- *
- * @param diagnostics
- * the diagnostic to check for issues
- * @param targetObject
- * the object that should have a diagnostic with the given issueCode
- * @param issueCode
- * the code of the issue to look for
- */
- protected void assertDiagnosticOnObject(final Diagnostic diagnostics, final EObject targetObject, final String issueCode) {
- for (Diagnostic diagnostic : diagnostics.getChildren()) {
- if (diagnostic instanceof AbstractValidationDiagnostic) {
- AbstractValidationDiagnostic avd = (AbstractValidationDiagnostic) diagnostic;
- if (avd.getSourceEObject() == targetObject && avd.getIssueCode().equals(issueCode)) {
- return;
- }
- }
- }
- fail("Issue with code '" + issueCode + "' not found");
- }
-
- /**
- * Assert that diagnosticList does not contain a diagnostic of the given issueCode.
- *
- * @param diagnostics
- * the diagnostic to check for issues
- * @param issueCode
- * the code of the issue to look for
- */
- private void assertNoDiagnostic(final Diagnostic diagnostics, final String issueCode) {
- for (Diagnostic diagnostic : diagnostics.getChildren()) {
- if (((AbstractValidationDiagnostic) diagnostic).getIssueCode().equals(issueCode)) {
- fail("Issue with code '" + issueCode + "' found");
- return;
- }
- }
- }
-
- /**
- * Assert that diagnosticList does not contain any diagnostic.
- *
- * @param diagnostics
- * the diagnostic to check for issues
- */
- private void assertNoDiagnostics(final Diagnostic diagnostics) {
- assertEquals("Diagnostics should be in OK state.", diagnostics.getCode(), Diagnostic.OK);
- assertTrue("There should be no diagnostics. Instead found " + diagnostics.getChildren().size(), diagnostics.getChildren().isEmpty());
- }
-
- /**
- * Assert no errors on resource exist.
- *
- * @param object
- * the object
- */
- public static void assertNoErrorsOnResource(final EObject object) {
- final EList errors = object.eResource().getErrors();
- if (!errors.isEmpty()) {
- fail(AbstractValidationTest.NO_ERRORS_FOUND_ON_RESOURCE_MESSAGE + "; found " + Lists.transform(errors, Resource.Diagnostic::getMessage)); //$NON-NLS-1$
- }
- }
-
- /**
- * Assert no errors on resource with the given message exist.
- *
- * @param object
- * the object
- * @param messages
- * the messages
- */
- public static void assertNoErrorsOnResource(final EObject object, final String... messages) {
- List messageList = Arrays.asList(messages);
- final EList errors = object.eResource().getErrors();
- for (String errorMessage : Lists.transform(errors, Resource.Diagnostic::getMessage)) {
- assertFalse(NO_ERRORS_FOUND_ON_RESOURCE_MESSAGE + " with message '" + errorMessage + "'.", messageList.contains(errorMessage));
- }
- }
-
- /**
- * Assert no linking errors on resource with the given message exist.
- *
- * @param object
- * the object
- * @param referenceType
- * the type of the referenced elements
- * @param referenceNames
- * the names of the referenced elements
- */
- @SuppressWarnings("PMD.UnusedFormalParameter")
- public static void assertNoLinkingErrorsOnResource(final EObject object, final String referenceType, final String... referenceNames) {
- final List linkingErrors = object.eResource().getErrors().stream().filter(error -> error instanceof XtextLinkingDiagnostic).collect(Collectors.toList());
- final List errorMessages = Lists.transform(linkingErrors, Resource.Diagnostic::getMessage);
- for (final String referenceName : referenceNames) {
- boolean found = false;
- for (final String errMessage : errorMessages) {
- if (errMessage.startsWith(referenceName)) {
- found = true;
- break;
- }
- }
- assertFalse(NLS.bind("Expecting no linking errors on resource for \"{0}\".", referenceName), found);
- }
- }
-
- /**
- * Assert linking errors on resource with the given message exist.
- *
- * @param object
- * the object
- * @param referenceType
- * the type of the referenced elements
- * @param referenceNames
- * the names of the referenced elements
- */
- @SuppressWarnings("PMD.UnusedFormalParameter")
- public static void assertLinkingErrorsOnResourceExist(final EObject object, final String referenceType, final String... referenceNames) {
- final List linkingErrors = object.eResource().getErrors().stream().filter(error -> error instanceof XtextLinkingDiagnostic).collect(Collectors.toList());
- final List errorMessages = Lists.transform(linkingErrors, Resource.Diagnostic::getMessage);
- for (final String referenceName : referenceNames) {
- boolean found = false;
- for (final String errMessage : errorMessages) {
- if (errMessage.contains(referenceName)) {
- found = true;
- break;
- }
- }
- assertTrue(NLS.bind("Expected linking error on \"{0}\" but could not find it", referenceName), found);
- }
- }
-
- /**
- * Expect the given linking error messages on the resource of the given model.
- *
- * @param object
- * the object, must not be {@code null}
- * @param errorStrings
- * the expected linking error error messages, must not be {@code null}
- */
- public static void assertLinkingErrorsWithCustomMessageOnResourceExist(final EObject object, final String... errorStrings) {
- final List linkingErrors = object.eResource().getErrors().stream().filter(error -> error instanceof XtextLinkingDiagnostic).collect(Collectors.toList());
- final List errorMessages = Lists.transform(linkingErrors, Resource.Diagnostic::getMessage);
- for (final String s : errorStrings) {
- assertTrue(NLS.bind("Expected linking error \"{0}\" but could not find it", s), errorMessages.contains(s));
- }
- }
-
- /**
- * Assert no linking errors on resource with the given message exist.
- *
- * @param object
- * the object, must not be {@code null}
- * @param messages
- * the linking error messages, must not be {@code null}
- */
- public static void assertNoLinkingErrorsWithCustomMessageOnResource(final EObject object, final String... messages) {
- List messageList = Arrays.asList(messages);
- final List linkingErrors = object.eResource().getErrors().stream().filter(error -> error instanceof XtextLinkingDiagnostic).collect(Collectors.toList());
- for (String errorMessage : Lists.transform(linkingErrors, Resource.Diagnostic::getMessage)) {
- assertFalse(NLS.bind("Expecting no linking errors on resource with message \"{0}\".", errorMessage), messageList.contains(errorMessage));
- }
- }
-
- /**
- * Expect given error messages on the resource of given model.
- *
- * @param object
- * the object
- * @param errorStrings
- * the error strings
- */
- public static void assertErrorsOnResourceExist(final EObject object, final String... errorStrings) {
- final EList errors = object.eResource().getErrors();
- final List errorMessages = Lists.transform(errors, Resource.Diagnostic::getMessage);
- for (final String s : errorStrings) {
- assertTrue(NLS.bind("Expected error \"{0}\" but could not find it", s), errorMessages.contains(s));
- }
- }
-
- /**
- * Validates if there is a syntax error present in the source content.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- */
- protected void assertNoSyntaxErrorsOnResource(final String sourceFileName, final CharSequence sourceContent) {
- final XtextTestSource testSource = createTestSource(sourceFileName, sourceContent.toString());
- final List errors = testSource.getModel().eResource().getErrors().stream().filter(error -> error instanceof XtextSyntaxDiagnostic).collect(Collectors.toList());
- if (!errors.isEmpty()) {
- StringBuilder sb = new StringBuilder("Syntax error is present in the test source.\nList of all found syntax errors:");
- errors.forEach(err -> sb.append("\n\t ").append(err.getMessage()));
- throw new AssertionError(sb.toString());
- }
- }
-
- /**
- * Memorize the position and issue code of each resource error that appears in the file.
- *
- * @param root
- * root node of the model to be analyzed
- */
- protected void memorizeUnexpectedResourceErrors() {
- for (Resource.Diagnostic diagnostic : getUnexpectedResourceDiagnostics()) {
- if (diagnostic instanceof AbstractDiagnostic) {
- AbstractDiagnostic diag = (AbstractDiagnostic) diagnostic;
- // Create error message
- StringBuilder sb = new StringBuilder(50);
- sb.append("Unexpected diagnostic found. Code '");
- sb.append(diag.getCode());
- sb.append(DOT_AND_LINEBREAK);
- // Retrieve the position and add the error
- memorizeErrorOnPosition(diag.getOffset(), sb.toString());
- } else {
- // Create error message
- StringBuilder sb = new StringBuilder(50);
- sb.append("Unexpected diagnostic found. '");
- sb.append(diagnostic.toString());
- sb.append(DOT_AND_LINEBREAK);
- // Add error message
- memorizeErrorOnPosition(0, sb.toString());
- }
- }
- }
-
- /**
- * Memorize the position and issue code of each unexpected diagnostic that appears in the file.
- * A diagnostic is considered as expected if a marker with the issue code in the test file was set.
- */
- protected void memorizeUnexpectedErrors() {
- for (Diagnostic diagnostic : getUnexpectedDiagnostics()) {
- if (diagnostic instanceof AbstractValidationDiagnostic) {
- AbstractValidationDiagnostic avd = (AbstractValidationDiagnostic) diagnostic;
- // Create error message
- StringBuilder sb = new StringBuilder(50);
- sb.append("Unexpected issue found. Code '");
- sb.append(avd.getIssueCode());
- sb.append(DOT_AND_LINEBREAK);
- // Retrieve the position and add the error
- if (avd instanceof FeatureBasedDiagnostic && ((FeatureBasedDiagnostic) avd).getFeature() != null) {
- List nodes = NodeModelUtils.findNodesForFeature(avd.getSourceEObject(), ((FeatureBasedDiagnostic) avd).getFeature());
- if (nodes.isEmpty()) {
- INode node = NodeModelUtils.getNode(avd.getSourceEObject());
- memorizeErrorOnPosition(getXtextTestUtil().findFirstNonHiddenLeafNode(node).getTotalOffset(), sb.toString());
- } else {
- for (INode node : nodes) {
- memorizeErrorOnPosition(getXtextTestUtil().findFirstNonHiddenLeafNode(node).getTotalOffset(), sb.toString());
- }
- }
- } else if (avd instanceof RangeBasedDiagnostic) {
- memorizeErrorOnPosition(((RangeBasedDiagnostic) avd).getOffset(), sb.toString());
- } else {
- memorizeErrorOnPosition(NodeModelUtils.getNode(avd.getSourceEObject()).getTotalOffset(), sb.toString());
- }
- } else {
- // Create error message
- StringBuilder sb = new StringBuilder(50);
- sb.append("Unexpected diagnostic found. '");
- sb.append(diagnostic.toString());
- sb.append(DOT_AND_LINEBREAK);
- // Add error message
- memorizeErrorOnPosition(0, sb.toString());
- }
- }
- }
-
- /**
- * Strictly validates a source given by a file name and content.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceType
- * defines if the source is a kernel or customer source, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- */
- protected void validateStrictly(final String sourceFileName, final TestSourceType sourceType, final CharSequence sourceContent) {
- XtextTestSource testSource = processMarkers(sourceFileName, sourceType, sourceContent);
- memorizeUnexpectedErrors();
- memorizeUnexpectedResourceErrors();
- processErrorsFound(testSource.getContent());
- afterValidate();
- }
-
- /**
- * Strictly validate a kernel source given by a {@link Pair} of file name and content.
- * All not expected diagnostics are considered as an error.
- *
- * @param sourceFileNameAndContent
- * the file name and content, given as the key and value of the pair, respectively, must not be {@code null}
- */
- protected void validateKernelSourceStrictly(final Pair sourceFileNameAndContent) {
- validateKernelSourceStrictly(sourceFileNameAndContent.getKey(), sourceFileNameAndContent.getValue());
- }
-
- /**
- * Strictly validate a customer source given by a {@link Pair} of file name and content.
- * All not expected diagnostics are considered as an error.
- *
- * @param sourceFileNameAndContent
- * the file name and content, given as the key and value of the pair, respectively, must not be {@code null}
- */
- protected void validateCustomerSourceStrictly(final Pair sourceFileNameAndContent) {
- validateCustomerSourceStrictly(sourceFileNameAndContent.getKey(), sourceFileNameAndContent.getValue());
- }
-
- /**
- * Strictly validate a kernel source given by a file name and content.
- * All not expected diagnostics are considered as an error.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- */
- protected void validateKernelSourceStrictly(final String sourceFileName, final CharSequence sourceContent) {
- validateStrictly(sourceFileName, TestSourceType.CLIENT_ALL, sourceContent);
- }
-
- /**
- * Strictly validate a customer source given by a file name and content.
- * All not expected diagnostics are considered as an error.
- *
- * @param sourceFileName
- * the file name that should be associated with the parsed content, must not be {@code null}
- * @param sourceContent
- * source, must not be {@code null}
- */
- protected void validateCustomerSourceStrictly(final String sourceFileName, final CharSequence sourceContent) {
- validateStrictly(sourceFileName, TestSourceType.CLIENT_CUSTOMER, sourceContent);
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/ValidationHelper.java b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/ValidationHelper.java
index 3acda5d55..3000474bb 100644
--- a/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/ValidationHelper.java
+++ b/com.avaloq.tools.ddk.xtext.test.core/src/com/avaloq/tools/ddk/xtext/test/validation/ValidationHelper.java
@@ -10,20 +10,28 @@
*******************************************************************************/
package com.avaloq.tools.ddk.xtext.test.validation;
+import static org.junit.jupiter.api.Assertions.fail;
+
import java.util.List;
+import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.testing.validation.ValidationTestHelper;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.Issue;
+import com.google.common.collect.Lists;
+
/**
* Helper methods relating to model validation.
*/
public class ValidationHelper extends ValidationTestHelper {
+ private static final String NO_ERRORS_FOUND_ON_RESOURCE_MESSAGE = "Expected no errors on resource"; //$NON-NLS-1$
+
/**
* Validates the provided document and returns a list of issues found.
*
@@ -42,7 +50,10 @@ public List getIssues(final IXtextDocument document) {
* the object to test for errors
*/
public void assertNoSyntaxOrLinkingErrors(final EObject obj) {
- AbstractValidationTest.assertNoErrorsOnResource(obj);
+ final EList errors = obj.eResource().getErrors();
+ if (!errors.isEmpty()) {
+ fail(NO_ERRORS_FOUND_ON_RESOURCE_MESSAGE + "; found " + Lists.transform(errors, Resource.Diagnostic::getMessage)); //$NON-NLS-1$
+ }
}
}
diff --git a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/AbstractFormatterTest.java b/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/AbstractFormatterTest.java
deleted file mode 100644
index e1e12db5b..000000000
--- a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/AbstractFormatterTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.formatter;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.formatting.INodeModelFormatter;
-import org.eclipse.xtext.formatting.INodeModelFormatter.IFormattedRegion;
-import org.eclipse.xtext.nodemodel.ICompositeNode;
-import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
-import org.eclipse.xtext.resource.SaveOptions;
-import org.eclipse.xtext.serializer.ISerializer;
-
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTest;
-
-
-/**
- * Base class for formatting tests.
- * The assertXyz methods are essentially copied from {@link com.avaloq.tools.ddk.xtext.test.formatting.AbstractAcfFormattingTest}.
- */
-@SuppressWarnings("nls")
-public abstract class AbstractFormatterTest extends AbstractXtextTest {
-
- /**
- * Loads a model from a string representation of a source.
- *
- * @param input
- * String representing a serialized model
- * @return Loaded model
- */
- private EObject getModel(final String input) throws IOException {
- return getXtextTestUtil().getModel("mytestmodel." + getXtextTestUtil().getFileExtension(), input);
- }
-
- /**
- * Gets the Guice injected serializer.
- *
- * @return Serializer the DI serializer
- */
- protected ISerializer getSerializer() {
- return getXtextTestUtil().getSerializer();
- }
-
- // test formatting based on the ParseTreeConstructorin
- protected void assertFormattedPTC(final String expected, final String model) throws IOException {
- EObject m = getModel(model);
- String res = getSerializer().serialize(m, SaveOptions.newBuilder().format().getOptions());
- assertEquals(expected, res, "Serialization not equal");
- }
-
- protected void assertPreserved(final String model) throws IOException {
- EObject m = getModel(model);
- String res = getSerializer().serialize(m, SaveOptions.newBuilder().getOptions());
- assertEquals(model, res, "Preserved node model");
- }
-
- // test formatting based on the NodeModel
- protected void assertFormattedNM(final String expected, final String model, final int offset, final int length) throws IOException {
- ICompositeNode node = NodeModelUtils.getNode(getModel(model)).getRootNode();
- IFormattedRegion r = getXtextTestUtil().get(INodeModelFormatter.class).format(node, offset, length);
- String actual = model.substring(0, r.getOffset()) + r.getFormattedText() + model.substring(r.getLength() + r.getOffset());
- assertEquals(expected, actual, "Formatting based on the NodeModel");
- }
-
-}
diff --git a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/FormatterTest.java b/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/FormatterTest.java
deleted file mode 100644
index b8e7b1041..000000000
--- a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/FormatterTest.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.formatter;
-
-import java.io.IOException;
-
-import org.eclipse.xtext.resource.SaveOptions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import com.avaloq.tools.ddk.xtext.formatter.formatterTestLanguage.Decl;
-import com.avaloq.tools.ddk.xtext.formatter.formatterTestLanguage.FormatterTestLanguageFactory;
-import com.avaloq.tools.ddk.xtext.formatter.formatterTestLanguage.TestLinewrapMinMax;
-import com.avaloq.tools.ddk.xtext.formatter.util.FormatterTestUtil;
-
-
-/**
- * This class tests the Acs Formatter framework. The tests are basically a copy
- * of the Xtext Formatter tests.
- */
-@SuppressWarnings("nls")
-public class FormatterTest extends AbstractFormatterTest {
- @Override
- protected FormatterTestUtil getXtextTestUtil() {
- return FormatterTestUtil.getInstance();
- }
-
- /**
- * This test class does not have a test source file. {@inheritDoc}
- */
- @Override
- protected String getTestSourceFileName() {
- return null;
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrap() throws IOException {
- String model = "test linewrap float val; int x; double y;";
- String expected = "test linewrap\nfloat val;\nint x;\ndouble y;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void keepComments() throws IOException {
- // String model = "test linewrap float val; int x; double y;";
- String model = "// begincomment \ntest linewrap// comment1\n" + "float val;//comment2\n" + "int x;" + "double y; //yoyoyo!\n// endcomment.";
- final String exp = "// begincomment \ntest linewrap// comment1\n" + "float val;//comment2\n" + "int x;\n" + "double y; //yoyoyo!\n// endcomment.";
- assertFormattedPTC(exp, model);
- assertFormattedNM(exp, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test verifies that {@link com.avaloq.tools.ddk.xtext.formatter.formatterTestLanguage.Line} elements are aligned at the specified column.
- *
- * @throws IOException
- */
- @Test
- public void column() throws IOException {
- String model = "test column item int x;";
- String expected = "test\n column\n\titem int x;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test verifies that elements can be aligned at column 0 and also that
- * a minimum padding is always inserted.
- *
- * @throws IOException
- */
- @Test
- public void columnMinimumPadding() throws IOException {
- String model = " test column name item int x;";
- String expected = "test\n column name\n\n\titem int x;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model.trim());
- }
-
- /**
- * This test verifies that {@link com.avaloq.tools.ddk.xtext.formatter.formatterTestLanguage.Line} elements are aligned with the specified offset.
- *
- * @throws IOException
- */
- @Test
- public void offset() throws IOException {
- String model = "test offset value v pair p1 p2";
- String expected = "test\noffset\n\tvalue v\n\t\tpair p1 p2";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test verifies right padding does pad and that there is always minimum padding " ".
- *
- * @throws IOException
- */
- @Test
- public void rightPadding() throws IOException {
- String model = "test padding long_name n2;";
- String expected = "test\npadding long_name n2 ;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void indentation() throws IOException {
- String model = "test indentation { float val; double y; indentation { int x; } }";
- String expected = "test indentation {\n float val;\n double y;\n indentation {\n int x;\n }\n}";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void association() throws IOException {
- String model = "test indentation { var = [0,1,2,3,4]; }";
- String expected = "test indentation {\n var=[ 0, 1, 2, 3, 4 ];\n}";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void indentationAndComments() throws IOException {
- String model = "test /* xxx */ indentation { float val; // some float\n double /* oo */ y; indentation { // some block\n int x; // xxx\n } } // final comment";
- String expected = "test /* xxx */ indentation {\n float val; // some float\n double /* oo */ y;\n indentation { // some block\n int x; // xxx\n }\n} // final comment";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- * It has been adapted to
- *
- * @throws IOException
- */
- @Test
- public void indentationAndLineWrap() throws IOException {
- String model = "test indentation { void func(x:int,y:int,s:javalangString, foo:javasqlDate, blupp:mylongtype, msads:adshdjkhsakdasdkslajdlsask, x:x, a:b, c:d ); }";
- String expected = "test indentation {\n void func(x:int,y:int,\n\t\ts:javalangString,\n\t\tfoo:javasqlDate,\n\t\tblupp:mylongtype,\n\t\tmsads:adshdjkhsakdasdkslajdlsask,\n\t\tx:x,a:b,c:d);\n}";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void between1() throws IOException {
- String model = "test indentation { indentation { x x; }; }";
- String expected = "test indentation {\n indentation {\n x x;\n };\n}";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void between2() throws IOException {
- String model = "test indentation { indentation { x x; } }";
- String expected = "test indentation {\n indentation {\n x x;\n }\n}";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRule() throws IOException {
- String model = "test linewrap fqn ab; fqn xx.yy.zz;";
- String expected = "test linewrap\nfqn\nab;\nfqn\nxx.yy.zz;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRulePartial1() throws IOException {
- String model = "test linewrap fqn ab . xx .yy .zz;";
- String expected = "test linewrap fqn ab.xx.yy.zz;";
- assertFormattedNM(expected, model, 22, 2);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRulePartial2() throws IOException {
- String model = "test linewrap fqn ab . xx .yy .zz;fqn xxx;";
- String expected = "test linewrap fqn\nab.xx.yy.zz;fqn xxx;";
- assertFormattedNM(expected, model, 15, 10);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRulePartial3() throws IOException {
- String model = "test linewrap fqn ab . xx .yy .zz;fqn xxx;";
- String expected = "test linewrap fqn ab.xx.yy.zz;\nfqn xxx;";
- assertFormattedNM(expected, model, 25, 12);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void formatSegment1() throws IOException {
- String model = "test\nindentation {\n indentation { x x ; } }";
- String expected = "test\nindentation {\n indentation {\n x x;\n } }";
- assertFormattedNM(expected, model, 30, 18);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void formatSegment2() throws IOException {
- String model = "test indentation {\n indentation { x x ; } }";
- // String expected =
- // "test\nindentation {\n indentation {\n x x;\n } }";
- assertFormattedNM(model, model, 7, 10);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void formatSegment3() throws IOException {
- String model = " test indentation {\n indentation { x x ; } }";
- String expected = "test indentation {\n indentation {\n x x;\n }\n}";
- assertFormattedNM(expected, model, 0, model.length());
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRuleRef1() throws IOException {
- String model = "test linewrap fqn ab .cd .ef; fqnref ab. cd. ef;";
- String expected = "test linewrap\nfqn\nab.cd.ef;\nfqnref\nab.cd.ef;";
- // assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRuleRef2() throws IOException {
- String model = "test linewrap fqn ab.cd.ef; fqnref ab.cd.ef;";
- String expected = "test linewrap\nfqn\nab.cd.ef;\nfqnref\nab.cd.ef;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest but it is modified
- * because I think the expected behavior in the original test is wrong.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDatatypeRuleComments() throws IOException {
- String model = "test linewrap/* 1 */fqn/* 2 */ab.cd.ef/* 3 */;/* 4 */fqnref/* 5 */ab.cd.ef/* 6 */;/* 7 */";
- // The expected model string differs from Xtext's -
- // Xtext does not expect a line wrap after the keyword "linewrap"
- // Xtext does not expect a line wrap prior to fqnref assignment
- // etc...
- String expected = "test linewrap/* 1 */ fqn/* 2 */\nab.cd.ef/* 3 */;/* 4 */ fqnref\n/* 5 */ ab.cd.ef/* 6 */;/* 7 */";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void enumeration() throws IOException {
- String model = "test linewrap enum lit1,lit2,lit3,lit1;";
- String expected = "test linewrap\nenum lit1 ,\nlit2,\nlit3,\nlit1;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=312559
- @Test
- public void suppressedWhitespace() throws IOException {
- String model = "test linewrap `f%%a` post;";
- String expected = "test linewrap\n`f%< b >%a` post;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- // TODO: investigate whether to include test or not - currently this test
- // would fail
- @Disabled
- public void suppressedLinewrap() throws IOException {
- String model = "test linewrap\n`foo%abcd%foo%< b\n>%abcd%foo%abcd%foo%abcd%" + "foo%abcd%foo%abcd%foo%abcd%foo%abcd%foo%abcd%foo%xx%foo%abcd%foo%abcd%"
- + "foo%abcd%foo%<\nb >%foo%abcd` post;";
- assertFormattedPTC(model, model);
- assertFormattedNM(model, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapMin() throws IOException {
- String model = "test wrapminmax foo bar;";
- String expected = "test wrapminmax\n\nfoo bar;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapMax() throws IOException {
- String model = "test wrapminmax\n\n\n\n\n\n\n\n\n\n\n\n\nfoo bar;";
- String expected = "test wrapminmax\n\n\n\n\nfoo bar;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapKeep() throws IOException {
- String model = "test wrapminmax\n\n\n\nfoo bar;";
- assertFormattedPTC(model, model);
- assertFormattedNM(model, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void linewrapDefault() {
- FormatterTestLanguageFactory f = FormatterTestLanguageFactory.eINSTANCE;
- TestLinewrapMinMax m = f.createTestLinewrapMinMax();
- Decl d = f.createDecl();
- d.getType().add("xxx");
- d.getName().add("yyy");
- m.getItems().add(d);
- String actual = getSerializer().serialize(m, SaveOptions.newBuilder().format().getOptions());
- String expected = "test wrapminmax\n\n\nxxx yyy;";
- Assertions.assertEquals(expected, actual, "Default Linewrap");
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void space() throws IOException {
- String model = "test linewrap space foo;";
- String expected = "test linewrap\nspace foo;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-
- /**
- * This test is copied from
- * org.eclipse.xtext.nodemodel.impl.formatter.FormatterTest.
- *
- * @throws IOException
- */
- @Test
- public void datatypeRules() throws IOException {
- String model = "test linewrap datatypes abc kw1 bcd def kw3;";
- String expected = "test linewrap\ndatatypes abc\nkw1\nbcd\ndef\nkw3;";
- assertFormattedPTC(expected, model);
- assertFormattedNM(expected, model, 0, model.length());
- assertPreserved(model);
- }
-}
diff --git a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/util/FormatterTestUtil.java b/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/util/FormatterTestUtil.java
deleted file mode 100644
index 02b6937a8..000000000
--- a/com.avaloq.tools.ddk.xtext.test/src/com/avaloq/tools/ddk/xtext/formatter/util/FormatterTestUtil.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Avaloq Group AG and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Avaloq Group AG - initial API and implementation
- *******************************************************************************/
-package com.avaloq.tools.ddk.xtext.formatter.util;
-
-import com.avaloq.tools.ddk.xtext.formatter.FormatterTestLanguageStandaloneSetup;
-import com.avaloq.tools.ddk.xtext.test.AbstractXtextTestUtil;
-import com.google.inject.Injector;
-
-
-public final class FormatterTestUtil extends AbstractXtextTestUtil {
- private final Injector injector = new FormatterTestLanguageStandaloneSetup().createInjectorAndDoEMFRegistration();
-
- private FormatterTestUtil() {
- // private constructor
- }
-
- /**
- * The singleton instance.
- */
- private static final class InstanceHolder {
- // Initialize-on-demand holder pattern.
- private static final FormatterTestUtil INSTANCE = new FormatterTestUtil();
-
- static FormatterTestUtil get() {
- return INSTANCE;
- }
- }
-
- public static FormatterTestUtil getInstance() {
- return InstanceHolder.get();
- }
-
- @Override
- protected Injector getInjector() {
- return injector;
- }
-
-}