Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'testsrunner/org.eclipse.cdt.testsrunner.gtest')
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.project34
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties15
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java35
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java67
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java97
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java645
14 files changed, 1094 insertions, 0 deletions
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath
new file mode 100644
index 0000000000..deb673668e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project
new file mode 100644
index 0000000000..174ece0c72
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.gtest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..0e860bfc27
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.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.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+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.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..6138224787
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner.gtest;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+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.gtest;x-friends:="org.eclipse.cdt.testsrunner.test"
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html
new file mode 100644
index 0000000000..d7c511887d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>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 <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties
new file mode 100644
index 0000000000..55d9be8332
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/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.gtest/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties
new file mode 100644
index 0000000000..f96761da73
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# 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
+###############################################################################
+pluginName=C/C++ Development Tools Google Tests Runner Support
+providerName=Eclipse CDT
+
+GoogleTestsRunner.name=Google Tests Runner
+GoogleTestsRunner.description=Tests runner for a test module based on Google C++ Testing Framework
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml
new file mode 100644
index 0000000000..152f28a03e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.cdt.testsrunner.TestsRunner">
+ <runner
+ class="org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerProvider"
+ description="%GoogleTestsRunner.description"
+ id="org.eclipse.cdt.testsrunner.gtest"
+ name="%GoogleTestsRunner.name">
+ <features
+ multipleTestFilter="true">
+ </features>
+ </runner>
+ </extension>
+</plugin>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml
new file mode 100644
index 0000000000..50dd36fb31
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.gtest</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java
new file mode 100644
index 0000000000..6aa1056514
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.gtest;
+
+import org.eclipse.osgi.util.NLS;
+
+public class GoogleTestsRunnerMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerMessages"; //$NON-NLS-1$
+ public static String GoogleTestsRunner_error_format;
+ public static String GoogleTestsRunner_io_error_prefix;
+ public static String OutputHandler_getparam_message;
+ public static String OutputHandler_unexpected_case_end;
+ public static String OutputHandler_unexpected_output;
+ public static String OutputHandler_unexpected_suite_end;
+ public static String OutputHandler_unknown_error_prefix;
+ public static String OutputHandler_unknown_location_format;
+ public static String OutputHandler_unknown_test_status;
+ public static String OutputHandler_wrong_groups_count;
+ public static String OutputHandler_wrong_suite_name;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, GoogleTestsRunnerMessages.class);
+ }
+
+ private GoogleTestsRunnerMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties
new file mode 100644
index 0000000000..e329ed2d6e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.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
+###############################################################################
+GoogleTestsRunner_error_format={0}: {1}
+GoogleTestsRunner_io_error_prefix=I/O Error:
+OutputHandler_getparam_message=Instantiated with GetParam() = {0}
+OutputHandler_unexpected_case_end=End of test case "{0}" is not expected, because the last started case is "{1}".
+OutputHandler_unexpected_output=Unexpected test module output.
+OutputHandler_unexpected_suite_end=End of test suite "{0}" is not expected, because the last started suite is "{1}".
+OutputHandler_unknown_error_prefix=Unknown error during parsing Google Test module output:
+OutputHandler_unknown_location_format=Unknown location format.
+OutputHandler_unknown_test_status=Test status value "{0}" is unknown.
+OutputHandler_wrong_groups_count=State with pattern "{0}" should has {1} groups but has {2}.
+OutputHandler_wrong_suite_name=A test case "{0}" belongs to test suite "{1}", but the last started suite is "{2}".
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java
new file mode 100644
index 0000000000..1ddb7430e8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.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.gtest;
+
+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 GoogleTestsRunnerPlugin extends Plugin {
+
+ /** The plug-in ID .*/
+ public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.gtest"; //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static GoogleTestsRunnerPlugin plugin;
+
+
+ public GoogleTestsRunnerPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * Returns the Boost Tests Runner provider plug-in instance.
+ *
+ * @return the plug-in instance
+ */
+ public static GoogleTestsRunnerPlugin 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.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java
new file mode 100644
index 0000000000..17ca3bd321
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.gtest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+
+
+/**
+ * The Tests Runner provider plug-in to run tests with Google Testing framework.
+ *
+ * Parses the text test module to output and provides the data for the Tests
+ * Runner Plug-In.
+ */
+public class GoogleTestsRunnerProvider implements ITestsRunnerProvider {
+
+ private static final String TEST_PATHS_DELIMITED = ":"; //$NON-NLS-1$
+ private static final String TEST_PATH_PARTS_DELIMITED = "."; //$NON-NLS-1$
+ private static final String ALL_TESTS= ".*"; //$NON-NLS-1$
+
+
+ @Override
+ public String[] getAdditionalLaunchParameters(String[][] testPaths) {
+ final String[] gtestParameters = {
+ "--gtest_repeat=1", //$NON-NLS-1$
+ "--gtest_print_time=1", //$NON-NLS-1$
+ "--gtest_color=no", //$NON-NLS-1$
+ };
+ String[] result = gtestParameters;
+
+ // Build tests filter
+ if (testPaths != null && testPaths.length >= 1) {
+ StringBuilder sb = new StringBuilder("--gtest_filter="); //$NON-NLS-1$
+ boolean needTestPathDelimiter = false;
+ for (String[] testPath : testPaths) {
+ if (needTestPathDelimiter) {
+ sb.append(TEST_PATHS_DELIMITED);
+ } else {
+ needTestPathDelimiter = true;
+ }
+ boolean needTestPathPartDelimiter = false;
+ for (String testPathPart : testPath) {
+ if (needTestPathPartDelimiter) {
+ sb.append(TEST_PATH_PARTS_DELIMITED);
+ } else {
+ needTestPathPartDelimiter = true;
+ }
+ sb.append(testPathPart);
+ }
+ // If it is a test suite
+ if (testPath.length <= 1) {
+ sb.append(ALL_TESTS);
+ }
+ }
+ result = new String[gtestParameters.length + 1];
+ System.arraycopy(gtestParameters, 0, result, 0, gtestParameters.length);
+ result[gtestParameters.length] = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * 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(GoogleTestsRunnerMessages.GoogleTestsRunner_error_format, prefix, description);
+ }
+
+ @Override
+ public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException {
+
+ try {
+ OutputHandler ouputHandler = new OutputHandler(modelUpdater);
+ ouputHandler.run(inputStream);
+ } catch (IOException e) {
+ throw new TestingException(getErrorText(GoogleTestsRunnerMessages.GoogleTestsRunner_io_error_prefix, e.getLocalizedMessage()));
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java
new file mode 100644
index 0000000000..3a58563d5b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java
@@ -0,0 +1,645 @@
+/*******************************************************************************
+ * 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.gtest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.xml.sax.SAXException;
+
+
+/**
+ * <p>
+ * Parses the output of Google Testing Framework and notifies the Tests Runner
+ * Core about how the testing process is going.
+ * </p>
+ * <p>
+ * Unfortunately, gtest does not provide a realtime XML output (yes, it has XML
+ * output, but it is generated after testing process is done), so we have to
+ * parse its output that is less reliable.
+ * </p>
+ * <p>
+ * The parsing is done with a simple FSM (Final State Machine). There is an
+ * internal state that changes when input tokens (gtest output lines) come.
+ * There is a transitions table that is used to determine what is the next state
+ * depending on the current one and the input token. The state may define
+ * onEnter and onExit actions to do the useful job.
+ * </p>
+ */
+public class OutputHandler {
+
+ /**
+ * Base class for the FSM internal state.
+ */
+ class State {
+
+ /** Stores the regular expression by which the state should be entered. */
+ private Pattern enterPattern;
+
+ /** The regular expression matcher. */
+ private Matcher matcher;
+
+ /** Groups count in a regular expression. */
+ private int groupCount;
+
+ /**
+ * The constructor.
+ *
+ * @param enterRegex the regular expression by which the state should be
+ * entered
+ */
+ State(String enterRegex) {
+ this(enterRegex, -1);
+ }
+
+ /**
+ * The constructor.
+ *
+ * @param enterRegex the regular expression by which the state should be
+ * entered
+ * @param groupCount groups count in a regular expression. It is used
+ * just to make debug easier and the parser more reliable.
+ */
+ State(String enterRegex, int groupCount) {
+ enterPattern = Pattern.compile(enterRegex);
+ this.groupCount = groupCount;
+ }
+
+ /**
+ * Checks whether the specified string matches the enter pattern
+ * (regular expression). If it is so the state should be entered.
+ *
+ * @param line input line (token)
+ * @return true if matches and false otherwise
+ * @throws TestingException if groups count does not match the defined
+ * in constructor number.
+ */
+ public boolean match(String line) throws TestingException {
+ matcher = enterPattern.matcher(line);
+ boolean groupsCountOk = groupCount == -1 || matcher.groupCount() == groupCount;
+ if (!groupsCountOk) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_groups_count,
+ enterPattern.pattern(), matcher.groupCount(), groupCount
+ )
+ );
+ }
+ boolean matches = matcher.matches();
+ if (!matches || !groupsCountOk) {
+ // Do not keep the reference - it will be unnecessary anyway
+ matcher = null;
+ }
+ return matches;
+ }
+
+ /**
+ * Returns the matched group value by index.
+ *
+ * @param groupNumber group index
+ * @return group value
+ */
+ protected String group(int groupNumber) {
+ return matcher.group(groupNumber);
+ }
+
+ /**
+ * Action that triggers on state enter.
+ *
+ * @param previousState previous state
+ * @throws TestingException if testing error is detected
+ */
+ public void onEnter(State previousState) throws TestingException {}
+
+ /**
+ * Action that triggers on state exit.
+ *
+ * @param previousState next state
+ * @throws TestingException if testing error is detected
+ */
+ public void onExit(State nextState) {}
+
+ /**
+ * Common routine that constructs full test suite name by name and type
+ * parameter.
+ *
+ * @param name test suite name
+ * @param typeParameter type parameter
+ * @return full test suite name
+ */
+ protected String getTestSuiteName(String name, String typeParameter) {
+ return (typeParameter != null) ? MessageFormat.format("{0}({1})", name, typeParameter.trim()) : name; //$NON-NLS-1$
+ }
+ }
+
+
+ /**
+ * The state is activated when a new test suite is started.
+ */
+ class TestSuiteStart extends State {
+
+ /** Stores the matched type parameter. */
+ private String typeParameter;
+
+ TestSuiteStart(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Stores type parameter and notify Tests Runner Core about test suite
+ * start.
+ */
+ @Override
+ public void onEnter(State previousState) {
+ typeParameter = group(3);
+ modelUpdater.enterTestSuite(getTestSuiteName(group(1), typeParameter));
+ }
+
+ /**
+ * Provides access to the matched type parameter.
+ *
+ * @return type parameter value
+ */
+ public String getTypeParameter() {
+ return typeParameter;
+ }
+ }
+
+
+ /**
+ * The state is activated when a new test case is started.
+ */
+ class TestCaseStart extends State {
+
+ TestCaseStart(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Extract current test case and test suite names and notify Tests
+ * Runner Core about test case start.
+ *
+ * @throws TestingException if extracted test suite name does not match
+ * last entered test suite name.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String testCaseName = group(2);
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter());
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name,
+ testCaseName, currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ modelUpdater.enterTestCase(testCaseName);
+ }
+ }
+
+
+ /**
+ * The state is activated when an error message's location is started.
+ */
+ class ErrorMessageLocation extends State {
+
+ /** Stores the message location file name. */
+ private String messageFileName;
+
+ /** Stores the message location line number. */
+ private int messageLineNumber;
+
+ /** Stores the first part of the message. */
+ private String messagePart;
+
+ ErrorMessageLocation(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Extract the data for the message location (file name, line number).
+ * The data may be provided in a common style ("/path/file:line" with
+ * the message text starting on the next line) or Visual Studio style
+ * ("/path/file(line):" with the message text continuing on the same
+ * line). It is also possible not to specify line number at all
+ * ("/path/file:").
+ *
+ * @throws TestingException if location format cannot be recognized.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String fileNameIfLinePresent = group(2);
+ String fileNameIfLineAbsent = group(6);
+ String lineNumberCommon = group(4);
+ String lineNumberVS = group(5);
+ if (fileNameIfLinePresent != null) {
+ if (lineNumberCommon != null) {
+ messageFileName = fileNameIfLinePresent;
+ messageLineNumber = Integer.parseInt(lineNumberCommon.trim());
+ } else if (lineNumberVS != null) {
+ messageFileName = fileNameIfLinePresent;
+ messageLineNumber = Integer.parseInt(lineNumberVS.trim());
+ } else {
+ if (!modelUpdater.currentTestSuite().getName().equals(group(1))) {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format);
+ }
+ }
+ } else if (fileNameIfLineAbsent != null) {
+ if (lineNumberCommon == null && lineNumberVS == null) {
+ messageFileName = fileNameIfLineAbsent;
+ messageLineNumber = DEFAULT_LOCATION_LINE;
+ } else {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format);
+ }
+ }
+ // Check special case when file is not known - reset location
+ if (messageFileName.equals("unknown file")) { //$NON-NLS-1$
+ messageFileName = DEFAULT_LOCATION_FILE;
+ }
+ // NOTE: For Visual Studio style there is also first part of the message at this line
+ messagePart = group(8);
+ }
+
+ /**
+ * Provides access to the message location file name.
+ *
+ * @return file name
+ */
+ public String getMessageFileName() {
+ return messageFileName;
+ }
+
+ /**
+ * Provides access to the message location line number.
+ *
+ * @return line number
+ */
+ public int getMessageLineNumber() {
+ return messageLineNumber;
+ }
+
+ /**
+ * Provides access to the first part of the message.
+ *
+ * @return message part
+ */
+ public String getMessagePart() {
+ return messagePart;
+ }
+ }
+
+
+ /**
+ * The state is activated when an error message text is started or continued.
+ */
+ class ErrorMessage extends State {
+
+ /** Stores the error message text that was already read. */
+ private StringBuilder messagePart = new StringBuilder();
+
+ ErrorMessage(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Collects the error message parts into internal buffer. If the
+ * previous state is not the same (it should be
+ * stateErrorMessageLocation) - get the message part from it.
+ */
+ @Override
+ public void onEnter(State previousState) {
+ boolean needEndOfLine = (this == previousState);
+ if (this != previousState) {
+ String firstMessagePart = stateErrorMessageLocation.getMessagePart();
+ if (firstMessagePart != null) {
+ messagePart.append(firstMessagePart);
+ needEndOfLine = true;
+ }
+ }
+ if (needEndOfLine) {
+ messagePart.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ }
+ messagePart.append(group(1));
+ }
+
+ /**
+ * Notifies the Tests Runner Core about new test message.
+ */
+ @Override
+ public void onExit(State nextState) {
+ if (this != nextState) {
+ modelUpdater.addTestMessage(
+ stateErrorMessageLocation.getMessageFileName(),
+ stateErrorMessageLocation.getMessageLineNumber(),
+ ITestMessage.Level.Error,
+ messagePart.toString()
+ );
+ messagePart.setLength(0);
+ }
+ }
+ }
+
+
+ /**
+ * The state is activated when a test trace is started or continued.
+ */
+ class TestTrace extends ErrorMessageLocation {
+
+ TestTrace(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Notifies the Tests Runner Core about new test message with test trace
+ * info.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ super.onEnter(previousState);
+ modelUpdater.addTestMessage(
+ getMessageFileName(),
+ getMessageLineNumber(),
+ ITestMessage.Level.Info,
+ getMessagePart()
+ );
+ }
+ }
+
+
+ /**
+ * The state is activated when a test case is finished.
+ */
+ class TestCaseEnd extends State {
+
+ TestCaseEnd(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Sets the test case execution time, status and notify Tests Runner
+ * Core about test case end.
+ *
+ * @throws TestingException if current test suite or case name does not
+ * match last entered test suite or case name or if test status is not
+ * known.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String explicitTypeParameter = group(5);
+ String typeParameter = explicitTypeParameter != null ? explicitTypeParameter : stateTestSuiteStart.getTypeParameter();
+ String currTestSuiteName = getTestSuiteName(group(2), typeParameter);
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name,
+ group(2), currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ String lastTestCaseName = modelUpdater.currentTestCase().getName();
+ if (!lastTestCaseName.equals(group(3))) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_unexpected_case_end,
+ group(3), lastTestCaseName
+ )
+ );
+ }
+ String testStatusStr = group(1);
+ ITestItem.Status testStatus = ITestItem.Status.Skipped;
+ if (testStatusStr.equals(testStatusOk)) {
+ testStatus = ITestItem.Status.Passed;
+ } else if (testStatusStr.equals(testStatusFailed)) {
+ testStatus = ITestItem.Status.Failed;
+ } else {
+ generateInternalError(MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_unknown_test_status, testStatusStr));
+ }
+ String getParamValue = group(7);
+ if (getParamValue != null) {
+ modelUpdater.addTestMessage(
+ DEFAULT_LOCATION_FILE,
+ DEFAULT_LOCATION_LINE,
+ ITestMessage.Level.Info,
+ MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_getparam_message, getParamValue)
+ );
+
+ }
+ modelUpdater.setTestingTime(Integer.parseInt(group(8)));
+ modelUpdater.setTestStatus(testStatus);
+ modelUpdater.exitTestCase();
+ }
+ }
+
+
+ /**
+ * The state is activated when a test suite is finished.
+ */
+ class TestSuiteEnd extends State {
+
+ TestSuiteEnd(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Notify Tests Runner Core about test suite end.
+ *
+ * @throws TestingException if current test suite name does not match
+ * last entered test suite name.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter());
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_unexpected_suite_end,
+ currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ modelUpdater.exitTestSuite();
+ }
+ }
+
+
+ /** The default file name for test message location. */
+ private static final String DEFAULT_LOCATION_FILE = null;
+
+ /** The default line number for test message location. */
+ private static final int DEFAULT_LOCATION_LINE = 1;
+
+ // Common regular expression parts
+ static private String regexTestSuiteName = "([^,]+)"; //$NON-NLS-1$
+ static private String regexParameterInstantiation = "(\\s*,\\s+where\\s+TypeParam\\s*=([^,(]+))?"; //$NON-NLS-1$
+ static private String regexTestName = regexTestSuiteName+"\\.([^,]+)"; //$NON-NLS-1$
+ static private String regexTestCount = "\\d+\\s+tests?"; //$NON-NLS-1$
+ static private String regexTestTime = "(\\d+)\\s+ms"; //$NON-NLS-1$
+ /* Matches location in the following formats:
+ * - /file:line:
+ * - /file(line):
+ * - /file: (with no line number specified)
+ * Groups:
+ * 1 - all except ":"
+ * 2 - file name (if line present) *
+ * 3 - line number with delimiters
+ * 4 - line number (common style) *
+ * 5 - line number (Visual Studio style) *
+ * 6 - file name (if no line number specified) *
+ * Using:
+ * - group 2 with 4 or 5 (if line number was specified)
+ * - group 6 (if filename only was specified)
+ */
+ static private String regexLocation = "((.*)(:(\\d+)|\\((\\d+)\\))|(.*[^):])):"; //$NON-NLS-1$
+
+ // Test statuses representation
+ static private String testStatusOk = "OK"; //$NON-NLS-1$
+ static private String testStatusFailed = "FAILED"; //$NON-NLS-1$
+
+
+ // All available states in FSM
+ private State stateInitial = new State(""); //$NON-NLS-1$
+ private State stateInitialized = new State(".*Global test environment set-up.*"); //$NON-NLS-1$
+ private TestSuiteStart stateTestSuiteStart = new TestSuiteStart("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+regexParameterInstantiation, 3); //$NON-NLS-1$ //$NON-NLS-2$
+ private State stateTestCaseStart = new TestCaseStart("\\[\\s*RUN\\s*\\]\\s+"+regexTestName, 2); //$NON-NLS-1$
+ private ErrorMessageLocation stateErrorMessageLocation = new ErrorMessageLocation(regexLocation+"\\s+(Failure|error: (.*))", 8); //$NON-NLS-1$
+ private State stateErrorMessage = new ErrorMessage("(.*)", 1); //$NON-NLS-1$
+ private State stateTestTraceStart = new State(".*Google Test trace.*"); //$NON-NLS-1$
+ // NOTE: Use 8 groups instead of 7 cause we need to be consistent with ErrorMessageLocation (as we subclass it)
+ private State stateTestTrace = new TestTrace(regexLocation+"\\s+((.*))", 8); //$NON-NLS-1$
+ private State stateTestCaseEnd = new TestCaseEnd("\\[\\s*("+testStatusOk+"|"+testStatusFailed+")\\s*\\]\\s+"+regexTestName+regexParameterInstantiation+"(\\s*,\\s+where\\s+GetParam\\s*\\(\\s*\\)\\s*=\\s*(.+))?\\s+\\("+regexTestTime+"\\)", 8); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ private State stateTestSuiteEnd = new TestSuiteEnd("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+"\\s+\\("+regexTestTime+"\\s+total\\)", 2); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ private State stateFinal = new State(".*Global test environment tear-down.*"); //$NON-NLS-1$
+ // NOTE: This state is a special workaround for empty test modules (they haven't got global test environment set-up/tear-down). They should be always passed.
+ private State stateEmptyTestModuleFinal = new State(".*\\[\\s*PASSED\\s*\\]\\s+0\\s+tests.*"); //$NON-NLS-1$
+
+ // Transitions table
+ private Map<State, State[] > transitions = new HashMap<State, State[]>();
+ {
+ // NOTE: Next states order is important!
+ transitions.put( from(stateInitial), to(stateInitialized, stateEmptyTestModuleFinal) );
+ transitions.put( from(stateInitialized), to(stateTestSuiteStart) );
+ transitions.put( from(stateTestSuiteStart), to(stateTestCaseStart) );
+ transitions.put( from(stateTestCaseStart), to(stateTestCaseEnd, stateErrorMessageLocation) );
+ transitions.put( from(stateErrorMessageLocation), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) );
+ transitions.put( from(stateErrorMessage), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) );
+ transitions.put( from(stateTestTraceStart), to(stateTestTrace) );
+ transitions.put( from(stateTestTrace), to(stateTestCaseEnd, stateErrorMessageLocation, stateTestTrace) );
+ transitions.put( from(stateTestCaseEnd), to(stateTestCaseStart, stateTestSuiteEnd) );
+ transitions.put( from(stateTestSuiteEnd), to(stateTestSuiteStart, stateFinal) );
+ }
+
+ /** Current FSM state. */
+ private State currentState;
+
+ /** The interface to notify the Tests Runner Core */
+ private ITestModelUpdater modelUpdater;
+
+
+ OutputHandler(ITestModelUpdater modelUpdater) {
+ this.modelUpdater = modelUpdater;
+ }
+
+ /**
+ * Runs the parsing process. Initializes the FSM, selects new states with
+ * transitions table and checks whether the parsing completes successfully.
+ *
+ * @param inputStream gtest test module output stream
+ * @throws IOException if stream reading error happens
+ * @throws TestingException if testing error happens
+ */
+ public void run(InputStream inputStream) throws IOException, TestingException {
+ // Initialize input stream reader
+ InputStreamReader streamReader = new InputStreamReader(inputStream);
+ BufferedReader reader = new BufferedReader(streamReader);
+ String line;
+ boolean finalizedProperly = false;
+
+ // Initialize internal state
+ currentState = stateInitial;
+ while ( ( line = reader.readLine() ) != null ) {
+ // Search for the next possible state
+ State[] possibleNextStates = transitions.get(currentState);
+ if (possibleNextStates == null) {
+ // Final state, stop running
+ finalizedProperly = true;
+ break;
+ }
+ for (State nextState : possibleNextStates) {
+ if (nextState.match(line)) {
+ // Next state found - send notifications to the states
+ currentState.onExit(nextState);
+ State previousState = currentState;
+ currentState = nextState;
+ nextState.onEnter(previousState);
+ break;
+ }
+ }
+ // NOTE: We cannot be sure that we cover all the output of gtest with our regular expressions
+ // (e.g. some framework notes or warnings may be uncovered etc.), so we just skip unmatched
+ // lines without an error
+ }
+ // Check whether the last line leads to the final state
+ if (transitions.get(currentState) == null) {
+ finalizedProperly = true;
+ }
+ if (!finalizedProperly) {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unexpected_output);
+ }
+ }
+
+ /**
+ * Throws the testing exception with unknown internal error prefix and the specified description.
+ *
+ * @param additionalInfo additional description of what happens
+ * @throws SAXException the exception that will be thrown
+ */
+ private void generateInternalError(String additionalInfo) throws TestingException {
+ TestingException e = new TestingException(GoogleTestsRunnerMessages.OutputHandler_unknown_error_prefix+additionalInfo);
+ GoogleTestsRunnerPlugin.log(e);
+ throw e;
+ }
+
+ /**
+ * Helper functions to make code more readable.
+ *
+ * @param fromState state to return
+ * @return passed state
+ */
+ private State from(State fromState) {
+ return fromState;
+ }
+
+ /**
+ * Helper functions to make code more readable.
+ *
+ * @param toStates states array to return
+ * @return passed states array
+ */
+ private State[] to(State... toStates) {
+ return toStates;
+ }
+
+}

Back to the top