From 23833f697ea7599d86561f163724f9368bac2fc8 Mon Sep 17 00:00:00 2001 From: Colin Leitner Date: Wed, 15 Jul 2015 22:50:16 +0200 Subject: [PATCH] Bug 472767 - Add support for Test Anything Protocol test runner Change-Id: I3da84f0bdf46ca5082638ec7a6540df82f2cda63 Signed-off-by: Colin Leitner --- pom.xml | 1 + .../feature.xml | 7 + .../feature.xml | 7 + .../.classpath | 7 + .../org.eclipse.cdt.testsrunner.tap/.project | 34 +++ .../.settings/org.eclipse.jdt.core.prefs | 82 ++++++ .../META-INF/MANIFEST.MF | 13 + .../about.html | 24 ++ .../build.properties | 21 ++ .../plugin.properties | 16 ++ .../plugin.xml | 13 + .../org.eclipse.cdt.testsrunner.tap/pom.xml | 17 ++ .../internal/tap/TAPTestsRunnerMessages.java | 31 +++ .../tap/TAPTestsRunnerMessages.properties | 16 ++ .../internal/tap/TAPTestsRunnerPlugin.java | 67 +++++ .../internal/tap/TAPTestsRunnerProvider.java | 256 ++++++++++++++++++ .../META-INF/MANIFEST.MF | 3 +- .../testsrunner/testsrunners/TAPTestCase.java | 199 ++++++++++++++ 18 files changed, 813 insertions(+), 1 deletion(-) create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/.classpath create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/.project create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/.settings/org.eclipse.jdt.core.prefs create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/META-INF/MANIFEST.MF create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/about.html create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/build.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/pom.xml create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.properties create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerPlugin.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerProvider.java create mode 100644 testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/TAPTestCase.java diff --git a/pom.xml b/pom.xml index 309ed07f28a..4c12db93fe0 100644 --- a/pom.xml +++ b/pom.xml @@ -203,6 +203,7 @@ testsrunner/org.eclipse.cdt.testsrunner.boost testsrunner/org.eclipse.cdt.testsrunner.gtest testsrunner/org.eclipse.cdt.testsrunner.qttest + testsrunner/org.eclipse.cdt.testsrunner.tap testsrunner/org.eclipse.cdt.testsrunner.test testsrunner/org.eclipse.cdt.testsrunner.feature testsrunner/org.eclipse.cdt.testsrunner.source.feature diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml index efc04616bc5..edad02de756 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml +++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml @@ -47,4 +47,11 @@ version="0.0.0" unpack="false"/> + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml index c08519d8a8d..ab29de63e62 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml +++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml @@ -47,4 +47,11 @@ version="0.0.0" unpack="false"/> + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.tap/.classpath new file mode 100644 index 00000000000..b277a8ac870 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/.project b/testsrunner/org.eclipse.cdt.testsrunner.tap/.project new file mode 100644 index 00000000000..92a252fde38 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/.project @@ -0,0 +1,34 @@ + + + org.eclipse.cdt.testsrunner.tap + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.tap/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..f00153f89a6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,82 @@ +#Mon Apr 16 13:01:24 EEST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.tap/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..cef3d2e0797 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.cdt.testsrunner.tap;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.cdt.testsrunner.internal.tap.TAPTestsRunnerPlugin +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0", + org.eclipse.cdt.testsrunner;bundle-version="3.5.0" +Export-Package: org.eclipse.cdt.testsrunner.internal.tap;x-friends:="org.eclipse.cdt.testsrunner.test" diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/about.html b/testsrunner/org.eclipse.cdt.testsrunner.tap/about.html new file mode 100644 index 00000000000..d7c511887d6 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/about.html @@ -0,0 +1,24 @@ + + +About + + +

About This Content

+ +

June 22, 2007

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + \ No newline at end of file diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.tap/build.properties new file mode 100644 index 00000000000..55d9be83320 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/build.properties @@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# 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: +# Anton Gorenkov - Initial implementation +############################################################################### + +bin.includes = plugin.xml,\ + plugin.properties,\ + about.html,\ + .,\ + META-INF/ +javadoc.packages = org.eclipse.cdt.launch.ui.*,\ + org.eclipse.cdt.launch.sourcelookup*,\ + org.eclipse.cdt.launch.* +source.. = src/ +src.includes = about.html diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.properties new file mode 100644 index 00000000000..d4b77c6a80d --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.properties @@ -0,0 +1,16 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# 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: +# Anton Gorenkov - Initial implementation +# Colin Leitner - Changed to TAP +############################################################################### +pluginName=C/C++ Development Tools Test Anything Protocol (TAP) Tests Runner Support +providerName=Eclipse CDT + +TAPTestsRunner.name=TAP Tests Runner +TAPTestsRunner.description=Tests runner for a test module based on the Test Anything Protocol diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.xml new file mode 100644 index 00000000000..384e9708aa7 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/plugin.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.tap/pom.xml new file mode 100644 index 00000000000..5d27798ab26 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 8.8.0-SNAPSHOT + ../../pom.xml + + + 1.0.0-SNAPSHOT + org.eclipse.cdt.testsrunner.tap + eclipse-plugin + diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.java new file mode 100644 index 00000000000..5aba876b65e --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov. + * 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: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.tap; + +import org.eclipse.osgi.util.NLS; + +public class TAPTestsRunnerMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.tap.TAPTestsRunnerMessages"; //$NON-NLS-1$ + public static String TAPTestsRunner_error_format; + public static String TAPTestsRunner_io_error_prefix; + public static String TAPTestsRunner_tap_error_prefix; + public static String TAPTestsRunner_invalid_version_line; + public static String TAPTestsRunner_multiple_plans; + public static String TAPTestsRunner_invalid_test_number; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, TAPTestsRunnerMessages.class); + } + + private TAPTestsRunnerMessages() { + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.properties new file mode 100644 index 00000000000..cd9e28e420f --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerMessages.properties @@ -0,0 +1,16 @@ +############################################################################### +# Copyright (c) 2011 Anton Gorenkov +# 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: +# Anton Gorenkov - Initial implementation +############################################################################### +TAPTestsRunner_error_format={0}: {1} +TAPTestsRunner_io_error_prefix=I/O Error +TAPTestsRunner_tap_error_prefix=TAP Error +TAPTestsRunner_invalid_version_line=Version information not on first line +TAPTestsRunner_multiple_plans=More than one test plan +TAPTestsRunner_invalid_test_number=Invalid test number diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerPlugin.java new file mode 100644 index 00000000000..ce02e1ef8bf --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerPlugin.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * 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: + * Anton Gorenkov - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.tap; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; + + +/** + * The activator class controls the plug-in life cycle + */ +public class TAPTestsRunnerPlugin extends Plugin { + + /** The plug-in ID .*/ + public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.tap"; //$NON-NLS-1$ + + /** Plug-in instance. */ + private static TAPTestsRunnerPlugin plugin; + + + public TAPTestsRunnerPlugin() { + super(); + plugin = this; + } + + /** + * Returns the TAP Tests Runner provider plug-in instance. + * + * @return the plug-in instance + */ + public static TAPTestsRunnerPlugin getDefault() { + return plugin; + } + + /** Convenience method which returns the unique identifier of this plugin. */ + public static String getUniqueIdentifier() { + return PLUGIN_ID; + } + + /** + * Logs the specified status with this plug-in's log. + * + * @param status status to log + */ + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + /** + * Logs an internal error with the specified throwable + * + * @param e the exception to be logged + */ + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e)); + } + +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerProvider.java new file mode 100644 index 00000000000..a81db57842c --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.tap/src/org/eclipse/cdt/testsrunner/internal/tap/TAPTestsRunnerProvider.java @@ -0,0 +1,256 @@ +/******************************************************************************* + * Copyright (c) 2011 Anton Gorenkov + * 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: + * Anton Gorenkov - initial API and implementation + * Colin Leitner - adapted to TAP support + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.internal.tap; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.MessageFormat; +import java.util.LinkedList; +import java.util.Queue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestItem.Status; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; +import org.eclipse.cdt.testsrunner.model.ITestModelUpdater; +import org.eclipse.cdt.testsrunner.model.TestingException; + +/** + * The Tests Runner provider plug-in to run tests with the Test Anything + * Protocol. + * + *

+ * Parses the standard output of an application for TAP conforming output. + * + *

+ * The YAML output isn't parsed, but logged like any unknown output. As an + * unofficial extension, any lines with gcc compatible diagnostic output of the + * kind + * + *

+ * <filename>: (error|warning|info): ...
+ * <filename>:<line>: (error|warning|info): ...
+ * + *

+ * will be reported with the correct level and location. + * + *

+ * As with the Boost test runner, the stdout buffering might delay + * test output if not disabled by + * + *

+ * setvbuf(stdout, NULL, _IONBF, 0);
+ */ +public class TAPTestsRunnerProvider implements ITestsRunnerProvider { + + private final Pattern VERSION_PATTERN = Pattern.compile("^TAP version \\d+$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + private final Pattern PLAN_PATTERN = Pattern.compile("^1..(?\\d+)(\\s*#\\s*(?(?skip).*|.*))?$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + private final Pattern BAIL_OUT_PATTERN = Pattern.compile("^Bail out!(\\s*(?.+))?$", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + private final Pattern TEST_RESULT_PATTERN = Pattern.compile("^(?not )?ok( (?\\d+))?(\\s*(?[^#]+))?(\\s*#\\s*(?((?SKIP)|(?TODO)).*|.*))?", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + private final Pattern GCC_DIAGNOSTIC_PATTERN = Pattern.compile("^(?[^:]+):((?\\d+):)? (?(error|warning|info)):\\s*(?.*)"); //$NON-NLS-1$ + + @Override + public String[] getAdditionalLaunchParameters(String[][] testPaths) throws TestingException { + // No arguments specified by TAP + return new String[0]; + } + + /** + * Construct the error message from prefix and detailed description. + * + * @param prefix prefix + * @param description detailed description + * @return the full message + */ + private String getErrorText(String prefix, String description) { + return MessageFormat.format(TAPTestsRunnerMessages.TAPTestsRunner_error_format, prefix, description); + } + + @Override + public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException { + // The TAP is really has lots of optional data and supports the most + // bare minimum possible for test output + + try { + // The TAP version may only be specified on the first line + boolean firstLine = true; + // The test plan is optional, but may be specified at most once + boolean hasPlan = false; + int plannedCount = -1; + int currentTestNumber = 1; + + Queue output = new LinkedList<>(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + while ((line = reader.readLine()) != null) { + Matcher m; + if ((m = VERSION_PATTERN.matcher(line)).matches()) { + // Version must be on the first line, or missing + if (!firstLine) { + throw new TestingException(getErrorText(TAPTestsRunnerMessages.TAPTestsRunner_tap_error_prefix, TAPTestsRunnerMessages.TAPTestsRunner_invalid_version_line)); + } + + // We actually don't care about the version itself + + } else if ((m = PLAN_PATTERN.matcher(line)).matches()) { + // Only one plan is allowed (after the optional version or at the end of the test run) + if (hasPlan) { + throw new TestingException(getErrorText(TAPTestsRunnerMessages.TAPTestsRunner_tap_error_prefix, TAPTestsRunnerMessages.TAPTestsRunner_multiple_plans)); + } + hasPlan = true; + + plannedCount = Integer.parseInt(m.group("count")); //$NON-NLS-1$ + + // The plan might decide to skip all tests. We fill up + // remaining tests if the count doesn't add up. + // + // This loop is almost identical to the final filler loop, + // but we may have a message as to why we had to skip these + // tests, which we don't have if the test has completed + // without a matching number of test results to the + // planned number of tests + if (m.group("skip") != null) { //$NON-NLS-1$ + String message = m.group("message"); //$NON-NLS-1$ + for (; currentTestNumber <= plannedCount; currentTestNumber += 1) { + modelUpdater.enterTestCase(Integer.toString(currentTestNumber)); + if (message != null) { + modelUpdater.addTestMessage(null, 0, Level.Message, message); + } + modelUpdater.setTestStatus(Status.Skipped); + modelUpdater.exitTestCase(); + } + + // Exit early + break; + } + + } else if ((m = BAIL_OUT_PATTERN.matcher(line)).matches()) { + // The test has been aborted by the module. Mark any + // planned tests accordingly + + String message = m.group("message"); //$NON-NLS-1$ + for (; currentTestNumber <= plannedCount; currentTestNumber += 1) { + modelUpdater.enterTestCase(Integer.toString(currentTestNumber)); + if (message != null) { + modelUpdater.addTestMessage(null, 0, Level.Message, message); + } + modelUpdater.setTestStatus(Status.Aborted); + modelUpdater.exitTestCase(); + } + + } else if ((m = TEST_RESULT_PATTERN.matcher(line)).matches()) { + // The index number optional. It may indicate skipped tests + // if it jumps ahead + String number = m.group("number"); //$NON-NLS-1$ + if (number != null) { + int newNumber = Integer.parseInt(number); + + // Negative jumps however, are not allowed + if (newNumber < currentTestNumber) { + throw new TestingException(getErrorText(TAPTestsRunnerMessages.TAPTestsRunner_tap_error_prefix, TAPTestsRunnerMessages.TAPTestsRunner_invalid_test_number)); + } + + // Skip tests for all numbers that have been skipped by + // the new test number + for (; currentTestNumber < newNumber; currentTestNumber += 1) { + modelUpdater.enterTestCase(Integer.toString(currentTestNumber)); + modelUpdater.setTestStatus(Status.Skipped); + modelUpdater.exitTestCase(); + } + + assert currentTestNumber == newNumber; + } + + // The test name is of course also optional + String name = m.group("name"); //$NON-NLS-1$ + if (name == null || name.trim().isEmpty()) { + name = Integer.toString(currentTestNumber); + } else { + name = name.trim(); + } + + modelUpdater.enterTestCase(name); + + // Add the optional test result message of skip and todo + // results + String message = m.group("message"); //$NON-NLS-1$ + if (message != null) { + modelUpdater.addTestMessage(null, 0, Level.Message, message); + } + + for (String o : output) { + Matcher diagnosticMatch = GCC_DIAGNOSTIC_PATTERN.matcher(o); + if (diagnosticMatch.matches()) { + int lineNumber = 0; + Level level = Level.Message; + + String diagLine = diagnosticMatch.group("line"); //$NON-NLS-1$ + if (diagLine != null) { + lineNumber = Integer.parseInt(diagLine); + } + + String diagLevel = diagnosticMatch.group("level"); //$NON-NLS-1$ + if (diagLevel.equals("error")) { //$NON-NLS-1$ + level = Level.Error; + } else if (diagLevel.equals("warning")) { //$NON-NLS-1$ + level = Level.Warning; + } else if (diagLevel.equals("info")) { //$NON-NLS-1$ + level = Level.Info; + } + + modelUpdater.addTestMessage(diagnosticMatch.group("filename"), lineNumber, level, diagnosticMatch.group("message")); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + modelUpdater.addTestMessage(null, 0, Level.Message, o); + } + } + output.clear(); + + if (m.group("skip") != null) { //$NON-NLS-1$ + modelUpdater.setTestStatus(Status.Skipped); + } else if (m.group("todo") != null) { //$NON-NLS-1$ + modelUpdater.setTestStatus(Status.NotRun); + } else if (m.group("not") != null) { //$NON-NLS-1$ + modelUpdater.setTestStatus(Status.Failed); + } else { + modelUpdater.setTestStatus(Status.Passed); + } + + modelUpdater.exitTestCase(); + + currentTestNumber += 1; + + } else { + // Add unknown output to the test case. We associate that + // data as soon as we see the "ok/not ok" line + output.add(line); + } + + firstLine = false; + } + + // The test plan may contain more tests than we have test results + // for. Skip the remaining tests. + for (; currentTestNumber <= plannedCount; currentTestNumber += 1) { + modelUpdater.enterTestCase(Integer.toString(currentTestNumber)); + modelUpdater.setTestStatus(Status.Skipped); + modelUpdater.exitTestCase(); + } + + } catch (IOException e) { + throw new TestingException(getErrorText(TAPTestsRunnerMessages.TAPTestsRunner_io_error_prefix, e.getLocalizedMessage())); + } + } +} diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF index 95611d2fedf..cbb8832849e 100644 --- a/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF @@ -10,7 +10,8 @@ Require-Bundle: org.junit, org.eclipse.cdt.testsrunner;bundle-version="7.0.0", org.eclipse.cdt.testsrunner.boost;bundle-version="7.0.0", org.eclipse.cdt.testsrunner.qttest;bundle-version="7.0.0", - org.eclipse.cdt.testsrunner.gtest;bundle-version="7.0.0" + org.eclipse.cdt.testsrunner.gtest;bundle-version="7.0.0", + org.eclipse.cdt.testsrunner.tap;bundle-version="1.0.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-Vendor: %Bundle-Vendor diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/TAPTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/TAPTestCase.java new file mode 100644 index 00000000000..d977b378000 --- /dev/null +++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/TAPTestCase.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2015 Colin Leitner + * 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: + * Colin Leitner - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.testsrunner.testsrunners; + +import org.eclipse.cdt.testsrunner.internal.tap.TAPTestsRunnerProvider; +import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider; +import org.eclipse.cdt.testsrunner.model.ITestItem.Status; +import org.eclipse.cdt.testsrunner.model.ITestMessage.Level; + +@SuppressWarnings("nls") +public class TAPTestCase extends BaseTestCase { + + @Override + protected ITestsRunnerProvider createTestsRunner() { + return new TAPTestsRunnerProvider(); + } + + // + public void testNoTestCases() { + } + + //TAP version 1 + public void testIgnoreVersion() { + } + + // + //TAP version 1 + public void testVersionMustBeOnFirstLine() { + expectTestingException(); + } + + //ok + //not ok + //ok # skip + //not ok # SKiPped + //ok # todo + //not ok # toDO + public void testBasicTestCases() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.setTestStatus(Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("3"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "skip"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("4"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "SKiPped"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("5"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "todo"); + mockModelUpdater.setTestStatus(Status.NotRun); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("6"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "toDO"); + mockModelUpdater.setTestStatus(Status.NotRun); + mockModelUpdater.exitTestCase(); + } + + //1..3 + //ok + //not ok + public void testMorePlannedThanExecutedTestCases() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.setTestStatus(Status.Failed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("3"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + } + + //ok + //ok 4 + public void testForwardJump() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("3"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("4"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + } + + //ok + //ok 1 + public void testNoBackwardJump() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + expectTestingException(); + } + + //ok some test name + //not ok 3 other test name + public void testTestCaseName() { + mockModelUpdater.enterTestCase("some test name"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("other test name"); + mockModelUpdater.setTestStatus(Status.Failed); + mockModelUpdater.exitTestCase(); + } + + //1..3 + //ok 1 + //Bail out! because I'm done with this testing + //Ignored trailing data + public void testBailOut() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "because I'm done with this testing"); + mockModelUpdater.setTestStatus(Status.Aborted); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("3"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "because I'm done with this testing"); + mockModelUpdater.setTestStatus(Status.Aborted); + mockModelUpdater.exitTestCase(); + } + + //1..3 + //ok + //1..2 + public void testAtMostOnePlan() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + expectTestingException(); + } + + //1..2 # skipped for some reason + public void testSkippedAllTestsWithReason() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "skipped for some reason"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("2"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "skipped for some reason"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + } + + //output for 1 (1) + //output for 1 (2) + //ok + //output for 2 (1) + //output for 2 (2) + //not ok second test # skipped for some reason + //ignored output + public void testOutput() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "output for 1 (1)"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "output for 1 (2)"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + mockModelUpdater.enterTestCase("second test"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "skipped for some reason"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "output for 2 (1)"); + mockModelUpdater.addTestMessage(null, 0, Level.Message, "output for 2 (2)"); + mockModelUpdater.setTestStatus(Status.Skipped); + mockModelUpdater.exitTestCase(); + } + + //filenameA: info: info text + //filenameB: warning: warning text + //filenameC:17: error: error text + //ok + public void testGCCDiagnosticOutput() { + mockModelUpdater.enterTestCase("1"); + mockModelUpdater.addTestMessage("filenameA", 0, Level.Info, "info text"); + mockModelUpdater.addTestMessage("filenameB", 0, Level.Warning, "warning text"); + mockModelUpdater.addTestMessage("filenameC", 17, Level.Error, "error text"); + mockModelUpdater.setTestStatus(Status.Passed); + mockModelUpdater.exitTestCase(); + } +}