/*
* Copyright (c) 2015 the original author or authors.
* 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:
* Donát Csikós (Gradle Inc.) - initial API and implementation and initial documentation
*/
package eclipsebuild.testing;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.gradle.api.internal.tasks.testing.DefaultTestClassDescriptor;
import org.gradle.api.internal.tasks.testing.DefaultTestMethodDescriptor;
import org.gradle.api.internal.tasks.testing.DefaultTestOutputEvent;
import org.gradle.api.internal.tasks.testing.DefaultTestSuiteDescriptor;
import org.gradle.api.internal.tasks.testing.TestCompleteEvent;
import org.gradle.api.internal.tasks.testing.TestDescriptorInternal;
import org.gradle.api.internal.tasks.testing.TestResultProcessor;
import org.gradle.api.internal.tasks.testing.TestStartEvent;
import org.gradle.api.internal.tasks.testing.results.AttachParentTestResultProcessor;
import org.gradle.api.tasks.testing.Test;
import org.gradle.api.tasks.testing.TestOutputEvent;
import org.gradle.api.tasks.testing.TestResult.ResultType;
import org.gradle.internal.progress.OperationIdGenerator;
import org.eclipse.jdt.internal.junit.model.ITestRunListener2;
public final class EclipseTestListener implements ITestRunListener2 {
private static final Pattern ECLIPSE_TEST_NAME = Pattern.compile("(.*)\\((.*)\\)");
private final TestResultProcessor resultProcessor;
private final Test testTask;
private final String suiteName;
private final Object waitMonitor;
private TestDescriptorInternal currentTestSuite;
private TestDescriptorInternal currentTestClass;
private TestDescriptorInternal currentTestMethod;
public EclipseTestListener(TestResultProcessor testResultProcessor, Test testTask, String suite, Object waitMonitor) {
this.resultProcessor = new AttachParentTestResultProcessor(testResultProcessor);
this.testTask = testTask;
this.waitMonitor = waitMonitor;
this.suiteName = suite;
}
@Override
public synchronized void testRunStarted(int testCount) {
this.currentTestSuite = testSuite(this.suiteName, this.testTask);
this.resultProcessor.started(this.currentTestSuite, startEvent());
}
@Override
public synchronized void testRunEnded(long elapsedTime) {
if (this.currentTestClass != null) {
this.resultProcessor.completed(this.currentTestClass.getId(), completeEvent(ResultType.SUCCESS));
}
this.resultProcessor.completed(this.currentTestSuite.getId(), completeEvent(ResultType.SUCCESS));
synchronized (this.waitMonitor) {
this.waitMonitor.notifyAll();
}
}
@Override
public synchronized void testRunStopped(long elapsedTime) {
// System.out.println("Test Run Stopped");
// TODO report failure when stopped?
testRunEnded(elapsedTime);
}
@Override
public synchronized void testRunTerminated() {
// System.out.println("Test Run Terminated");
// TODO report failure when terminated?
testRunEnded(0);
}
@Override
public synchronized void testStarted(String testId, String testName) {
// TODO need idGenerator
String testClass = testName;
String testMethod = testName;
Matcher matcher = ECLIPSE_TEST_NAME.matcher(testName);
if (matcher.matches()) {
testClass = matcher.group(2);
testMethod = matcher.group(1);
}
String classId = testId + " class";
if (this.currentTestClass == null) {
this.currentTestClass = testClass(classId, testClass, this.currentTestSuite);
this.resultProcessor.started(this.currentTestClass, startEvent(this.currentTestSuite));
} else if (!this.currentTestClass.getId().equals(classId)) {
this.resultProcessor.completed(this.currentTestClass.getId(), completeEvent(ResultType.SUCCESS));
this.currentTestClass = testClass(classId, testClass, this.currentTestSuite);
this.resultProcessor.started(this.currentTestClass, startEvent(this.currentTestSuite));
}
this.currentTestMethod = testMethod(testId, testClass, testMethod, this.currentTestClass);
this.resultProcessor.started(this.currentTestMethod, startEvent(this.currentTestClass));
}
@Override
public synchronized void testEnded(String testId, String testName) {
this.resultProcessor.completed(testId, completeEvent(ResultType.SUCCESS));
}
@Override
public synchronized void testFailed(int status, String testId, String testName, String trace, String expected, String actual) {
String message = testName + " failed";
if (expected != null || actual != null) {
message += " (expected=" + expected + ", actual=" + actual + ")";
}
this.resultProcessor.output(this.currentTestMethod.getId(), new DefaultTestOutputEvent(TestOutputEvent.Destination.StdOut, message));
this.resultProcessor.failure(this.currentTestMethod.getId(), new EclipseTestFailure(message, trace));
}
@Override
public synchronized void testReran(String testId, String testClass, String testName, int status, String trace, String expected, String actual) {
throw new UnsupportedOperationException("Unexpected call to testReran when running tests in Eclipse.");
}
@Override
public synchronized void testTreeEntry(String description) {
}
private static DefaultTestSuiteDescriptor testSuite(String suiteName, final Test testTask) {
return new DefaultTestSuiteDescriptor("root", suiteName) {
private static final long serialVersionUID = 1L;
@Override
public Object getOwnerBuildOperationId() {
return OperationIdGenerator.generateId(testTask);
}
};
}
private static DefaultTestClassDescriptor testClass(String id, String className, final TestDescriptorInternal parent) {
return new DefaultTestClassDescriptor(id, className){
private static final long serialVersionUID = 1L;
@Override
public TestDescriptorInternal getParent() {
return parent;
}
};
}
private static DefaultTestMethodDescriptor testMethod(String id, String className, String methodName, final TestDescriptorInternal parent) {
return new DefaultTestMethodDescriptor(id, className, methodName) {
private static final long serialVersionUID = 1L;
@Override
public TestDescriptorInternal getParent() {
return parent;
}
};
}
private static TestStartEvent startEvent() {
return new TestStartEvent(System.currentTimeMillis());
}
private static TestStartEvent startEvent(TestDescriptorInternal parent) {
return new TestStartEvent(System.currentTimeMillis(), parent.getId());
}
private static TestCompleteEvent completeEvent(ResultType resultType) {
return new TestCompleteEvent(System.currentTimeMillis(), resultType);
}
public static void main(String[] args) {
System.out.println(new RuntimeException("asdfasdf").toString());
}
}