junit: try smRunner (initial)

This commit is contained in:
anna
2013-05-16 20:02:42 +02:00
parent 35e7acc394
commit b3a6c1731f
9 changed files with 297 additions and 18 deletions
@@ -0,0 +1,109 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.rt.execution.junit;
import junit.framework.ComparisonFailure;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class ComparisonFailureData {
private final String myExpected;
private final String myActual;
private final String myFilePath;
private static Map EXPECTED = new HashMap();
private static Map ACTUAL = new HashMap();
static {
try {
init(ComparisonFailure.class);
init(org.junit.ComparisonFailure.class);
}
catch (Throwable e) {
}
}
private static void init(Class exceptionClass) throws NoSuchFieldException {
final Field expectedField = exceptionClass.getDeclaredField("fExpected");
expectedField.setAccessible(true);
EXPECTED.put(exceptionClass, expectedField);
final Field actualField = exceptionClass.getDeclaredField("fActual");
actualField.setAccessible(true);
ACTUAL.put(exceptionClass, actualField);
}
public ComparisonFailureData(String expected, String actual) {
this(expected, actual, null);
}
public ComparisonFailureData(String expected, String actual, String filePath) {
myExpected = expected;
myActual = actual;
myFilePath = filePath;
}
public String getFilePath() {
return myFilePath;
}
public String getExpected() {
return myExpected;
}
public String getActual() {
return myActual;
}
public static ComparisonFailureData create(Throwable assertion) {
if (assertion instanceof FileComparisonFailure) {
final FileComparisonFailure comparisonFailure = (FileComparisonFailure)assertion;
return new ComparisonFailureData(comparisonFailure.getExpected(), comparisonFailure.getActual(), comparisonFailure.getFilePath());
}
try {
return new ComparisonFailureData(getExpected(assertion), getActual(assertion));
}
catch (Throwable e) {
return null;
}
}
public static String getActual(Throwable assertion) throws IllegalAccessException, NoSuchFieldException {
return get(assertion, ACTUAL, "fActual");
}
public static String getExpected(Throwable assertion) throws IllegalAccessException, NoSuchFieldException {
return get(assertion, EXPECTED, "fExpected");
}
private static String get(final Throwable assertion, final Map staticMap, final String fieldName) throws IllegalAccessException, NoSuchFieldException {
String actual;
if (assertion instanceof ComparisonFailure) {
actual = (String)((Field)staticMap.get(ComparisonFailure.class)).get(assertion);
}
else if (assertion instanceof org.junit.ComparisonFailure) {
actual = (String)((Field)staticMap.get(org.junit.ComparisonFailure.class)).get(assertion);
}
else {
Field field = assertion.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
actual = (String)field.get(assertion);
}
return actual;
}
}
@@ -31,6 +31,18 @@ public class FileComparisonFailure extends ComparisonFailure implements KnownExc
myFilePath = filePath;
}
public String getFilePath() {
return myFilePath;
}
public String getExpected() {
return myExpected;
}
public String getActual() {
return myActual;
}
public PacketFactory getPacketFactory() {
return new MyPacketFactory(this, myExpected, myActual, myFilePath);
}
@@ -290,3 +290,4 @@ disable.graph.inference=false
comment.by.line.bulk.lines.trigger=100
scene.builder.start.executable=true
junit_sm_runner=false
+1
View File
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="compiler-openapi" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="java-indexing-api" />
<orderEntry type="module" module-name="smRunner" />
</component>
<component name="copyright">
<Base>
@@ -35,6 +35,11 @@ import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.testframework.*;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.execution.util.ProgramParametersUtil;
@@ -53,6 +58,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
@@ -62,6 +68,7 @@ import com.intellij.rt.execution.junit.IDEAJUnitListener;
import com.intellij.rt.execution.junit.JUnitStarter;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -76,6 +83,7 @@ public abstract class TestObject implements JavaCommandLine {
protected static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit.TestObject");
private static final String MESSAGE = ExecutionBundle.message("configuration.not.speficied.message");
private static final String JUNIT_TEST_FRAMEWORK_NAME = "JUnit";
protected JavaParameters myJavaParameters;
private final Project myProject;
@@ -198,6 +206,7 @@ public abstract class TestObject implements JavaCommandLine {
myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath());
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class));
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(ServiceMessageTypes.class));
myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
ext.updateJavaParameters(myConfiguration, myJavaParameters, getRunnerSettings());
@@ -248,9 +257,16 @@ public abstract class TestObject implements JavaCommandLine {
@Override
public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
final boolean smRunner = Registry.is("junit_sm_runner", false);
if (smRunner) {
myJavaParameters.getVMParametersList().add("-Didea.junit.sm_runner");
}
final JUnitProcessHandler handler = createHandler(executor);
final RunnerSettings runnerSettings = getRunnerSettings();
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
if (smRunner) {
return useSmRunner(executor, handler);
}
final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo());
final JUnitConsoleProperties consoleProperties = new JUnitConsoleProperties(myConfiguration, executor);
final JUnitTreeConsoleView consoleView = new JUnitTreeConsoleView(consoleProperties, runnerSettings, getConfigurationSettings(), unboundOutputRoot);
@@ -349,6 +365,42 @@ public abstract class TestObject implements JavaCommandLine {
return result;
}
private ExecutionResult useSmRunner(Executor executor, JUnitProcessHandler handler) {
TestConsoleProperties testConsoleProperties = new SMTRunnerConsoleProperties(
new RuntimeConfigurationProducer.DelegatingRuntimeConfiguration<JUnitConfiguration>(
(JUnitConfiguration)myEnvironment.getRunProfile()),
JUNIT_TEST_FRAMEWORK_NAME,
executor
);
testConsoleProperties.setIfUndefined(TestConsoleProperties.HIDE_PASSED_TESTS, false);
BaseTestsOutputConsoleView smtConsoleView = SMTestRunnerConnectionUtil.createConsoleWithCustomLocator(
JUNIT_TEST_FRAMEWORK_NAME,
testConsoleProperties,
myEnvironment.getRunnerSettings(),
myEnvironment.getConfigurationSettings(), null);
Disposer.register(myProject, smtConsoleView);
final ConsoleView consoleView = smtConsoleView;
consoleView.attachToProcess(handler);
final RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView);
rerunFailedTestsAction.init(testConsoleProperties, myEnvironment);
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
@Override
public TestFrameworkRunningModel get() {
return ((SMTRunnerConsoleView)consoleView).getResultsViewer();
}
});
final DefaultExecutionResult result = new DefaultExecutionResult(consoleView, handler);
result.setRestartActions(rerunFailedTestsAction);
return result;
}
protected void notifyByBalloon(JUnitRunningModel model, boolean started, JUnitConsoleProperties consoleProperties) {
TestsUIUtil.notifyByBalloon(myProject, started, model != null ? model.getRoot() : null, consoleProperties);
}
+1
View File
@@ -9,6 +9,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="JUnit4" level="project" />
<orderEntry type="module" module-name="java-runtime" />
<orderEntry type="library" name="tcServiceMessages" level="project" />
</component>
</module>
@@ -15,10 +15,7 @@
*/
package com.intellij.junit4;
import com.intellij.rt.execution.junit.IDEAJUnitListener;
import com.intellij.rt.execution.junit.IdeaTestRunner;
import com.intellij.rt.execution.junit.TimeSender;
import com.intellij.rt.execution.junit.TreeSender;
import com.intellij.rt.execution.junit.*;
import com.intellij.rt.execution.junit.segments.OutputObjectRegistry;
import com.intellij.rt.execution.junit.segments.SegmentedOutputStream;
import org.junit.internal.requests.ClassRequest;
@@ -140,8 +137,12 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner {
public void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr, int lastIdx) {
myRegistry = new JUnit4OutputObjectRegistry(segmentedOut, lastIdx);
myTestsListener = new JUnit4TestResultsSender(myRegistry);
if (JUnitStarter.SM_RUNNER) {
myTestsListener = new SMTestSender();
} else {
myRegistry = new JUnit4OutputObjectRegistry(segmentedOut, lastIdx);
myTestsListener = new JUnit4TestResultsSender(myRegistry);
}
}
public Object getTestToStart(String[] args) {
@@ -20,16 +20,29 @@
*/
package com.intellij.junit4;
import com.intellij.rt.execution.junit.*;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessage;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes;
import junit.framework.ComparisonFailure;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class SMTestSender extends RunListener {
private static final String JUNIT_FRAMEWORK_COMPARISON_NAME = ComparisonFailure.class.getName();
private static final String ORG_JUNIT_COMPARISON_NAME = "org.junit.ComparisonFailure";
private String myCurrentClassName;
public void testRunStarted(Description description) throws Exception {
//System.out.println("##teamcity[testSuiteStarted name =\'" + description.toString() + "\']");
System.out.println("##teamcity[testSuiteStarted name =\'" + description.toString() + "\']");
}
public void testRunFinished(Result result) throws Exception {
@@ -55,20 +68,108 @@ class SMTestSender extends RunListener {
}
public void testFailure(Failure failure) throws Exception {
System.out.println("##teamcity[testFailed name=\'" +
JUnit4ReflectionUtil.getMethodName(failure.getDescription()) +
"\' message=\'" +
failure.getMessage() +
"\' details=\'" +
failure.getTrace().replaceAll("\n", "n").replaceAll("\r", "r") +
"\']");
final String failureMessage = failure.getMessage();
final String trace = failure.getTrace();
final Map attrs = new HashMap();
attrs.put("name", JUnit4ReflectionUtil.getMethodName(failure.getDescription()));
attrs.put("message", failureMessage);
final ComparisonFailureData notification = createExceptionNotification(failure.getException());
if (notification != null) {
attrs.put("expected", notification.getExpected());
attrs.put("actual", notification.getActual());
final int failureIdx = trace.indexOf(failureMessage);
attrs.put("details", failureIdx > -1 ? trace.substring(failureIdx + failureMessage.length()) : trace);
} else {
attrs.put("details", trace);
}
System.out.println(ServiceMessage.asString(ServiceMessageTypes.TEST_FAILED, attrs));
}
public void testAssumptionFailure(Failure failure) {
prepareIgnoreMessage(failure.getDescription(), false);
}
public void testIgnored(Description description) throws Exception {
System.out.println("##teamcity[testIgnored name=\'" + JUnit4ReflectionUtil.getMethodName(description) + "\']");
public synchronized void testIgnored(Description description) throws Exception {
prepareIgnoreMessage(description, true);
}
private static void prepareIgnoreMessage(Description description, boolean commentMessage) {
Map attrs = new HashMap();
if (commentMessage) {
try {
final Ignore ignoredAnnotation = (Ignore)description.getAnnotation(Ignore.class);
if (ignoredAnnotation != null) {
final String val = ignoredAnnotation.value();
if (val != null) {
attrs.put("message", val);
}
}
}
catch (NoSuchMethodError ignored) {
//junit < 4.4
}
}
attrs.put("name", JUnit4ReflectionUtil.getMethodName(description));
System.out.println(ServiceMessage.asString(ServiceMessageTypes.TEST_IGNORED, attrs));
}
private static boolean isComparisonFailure(Throwable throwable) {
if (throwable == null) return false;
return isComparisonFailure(throwable.getClass());
}
private static boolean isComparisonFailure(Class aClass) {
if (aClass == null) return false;
final String throwableClassName = aClass.getName();
if (throwableClassName.equals(JUNIT_FRAMEWORK_COMPARISON_NAME) || throwableClassName.equals(ORG_JUNIT_COMPARISON_NAME)) return true;
return isComparisonFailure(aClass.getSuperclass());
}
private static ComparisonFailureData createExceptionNotification(Throwable assertion) {
if (isComparisonFailure(assertion)) {
return ComparisonFailureData.create(assertion);
}
final Throwable cause = assertion.getCause();
if (isComparisonFailure(cause)) {
try {
return ComparisonFailureData.create(assertion);
}
catch (Throwable ignore) {
}
}
final String message = assertion.getMessage();
if (message != null) {
ComparisonFailureData notification = createExceptionNotification(message, "\nExpected: is \"(.*)\"\n\\s*got: \"(.*)\"\n");
if (notification == null) {
notification = createExceptionNotification(message, "\nExpected: is \"(.*)\"\n\\s*but: was \"(.*)\"");
}
if (notification == null) {
notification = createExceptionNotification(message, "\nExpected: (.*)\n\\s*got: (.*)");
}
if (notification == null) {
notification = createExceptionNotification(message, "\\s*expected same:<(.*)> was not:<(.*)>");
}
if (notification == null) {
notification = createExceptionNotification(message, "\\s*expected:<(.*)> but was:<(.*)>");
}
if (notification == null) {
notification = createExceptionNotification(message, "\nExpected: \"(.*)\"\n\\s*but: was \"(.*)\"");
}
if (notification != null) {
return notification;
}
}
return null;
}
private static ComparisonFailureData createExceptionNotification(String message, final String regex) {
final Matcher matcher = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE).matcher(message);
if (matcher.matches()) {
return new ComparisonFailureData(matcher.group(1).replaceAll("\\\\n", "\n"), matcher.group(2).replaceAll("\\\\n", "\n"));
}
return null;
}
}
@@ -36,6 +36,7 @@ public class JUnitStarter {
private static final String SOCKET = "-socket";
private static String ourForkMode;
private static String ourCommandFileName;
public static boolean SM_RUNNER = System.getProperty("idea.junit.sm_runner") != null;
public static void main(String[] args) throws IOException {
SegmentedOutputStream out = new SegmentedOutputStream(System.out);
@@ -192,7 +193,7 @@ public class JUnitStarter {
}
IdeaTestRunner testRunner = (IdeaTestRunner)getAgentClass(isJUnit4).newInstance();
testRunner.setStreams(out, err, 0);
return testRunner.startRunnerWithArgs(args, listeners, true);
return testRunner.startRunnerWithArgs(args, listeners, !SM_RUNNER);
}
catch (Exception e) {
e.printStackTrace(System.err);