blob: 02ae4fcc562e0f7a2a89efc996713321de90bfba [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.tradefed.result;
import com.android.ddmlib.Log;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestListener;
import junit.framework.TestResult;
import org.junit.internal.AssumptionViolatedException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Map;
/**
* A class that listens to {@link ITestInvocationListener} events and forwards them to a
* {@link junit.framework.TestListener}.
* <p/>
*/
public class InvocationToJUnitResultForwarder implements ITestInvocationListener {
private static final String LOG_TAG = "InvocationToJUnitResultForwarder";
private TestListener mJUnitListener;
public InvocationToJUnitResultForwarder(TestListener junitListener) {
mJUnitListener = junitListener;
}
protected TestListener getJUnitListener() {
return mJUnitListener;
}
/**
* {@inheritDoc}
*/
@Override
public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
mJUnitListener.endTest(new TestIdentifierResult(test));
}
/**
* {@inheritDoc}
*/
@Override
public void testFailed(TestIdentifier testId, String trace) {
Test test = new TestIdentifierResult(testId);
// TODO: is it accurate to represent the trace as AssertionFailedError?
mJUnitListener.addFailure(test, new AssertionFailedError(trace));
}
@Override
public void testAssumptionFailure(TestIdentifier testId, String trace) {
Test test = new TestIdentifierResult(testId);
AssumptionViolatedException throwable = new AssumptionViolatedException(trace);
mJUnitListener.addError(test, throwable);
}
/**
* {@inheritDoc}
*/
@Override
public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {
// TODO: no run ended method on TestListener - would be good to propagate the elaspedTime
// info up
Log.i(LOG_TAG, String.format("run ended %d ms", elapsedTime));
}
/**
* {@inheritDoc}
*/
@Override
public void testRunFailed(String errorMessage) {
// TODO: no run failed method on TestListener - would be good to propagate this up
Log.e(LOG_TAG, String.format("run failed: %s", errorMessage));
}
/**
* {@inheritDoc}
*/
@Override
public void testRunStarted(String runName, int testCount) {
// TODO: no run started method on TestResult - would be good to propagate this up
Log.i(LOG_TAG, String.format("run %s started: %d tests", runName, testCount));
}
/**
* {@inheritDoc}
*/
@Override
public void testRunStopped(long elapsedTime) {
Log.i(LOG_TAG, String.format("run stopped: %d ms", elapsedTime));
}
/**
* {@inheritDoc}
*/
@Override
public void testStarted(TestIdentifier test) {
Log.d(LOG_TAG, test.toString());
mJUnitListener.startTest(new TestIdentifierResult(test));
}
/**
* A class that converts a {@link TestIdentifier} to a JUnit {@link Test}
*
* TODO: The JUnit {@link TestListener} seems to assume a descriptive interface of some sort
* for Test, that is not in its defined methods. Assume for now that its toString()
*/
static class TestIdentifierResult implements Test {
private final TestIdentifier mTestId;
private TestIdentifierResult(TestIdentifier testId) {
mTestId = testId;
}
/**
* {@inheritDoc}
*/
@Override
public int countTestCases() {
return 1;
}
/**
* {@inheritDoc}
*/
@Override
public void run(TestResult result) {
// this class for reporting purposes only, ignore
throw new UnsupportedOperationException();
}
/**
* Specialize this to base equality on TestIdentifier.
*/
@Override
public boolean equals(Object other) {
return mTestId.equals(other);
}
/**
* Specialize this to base hashCode on TestIdentifier.
*/
@Override
public int hashCode() {
return mTestId.hashCode();
}
/**
* Return a user-friendly descriptive string.
*/
@Override
public String toString() {
// TODO: use ':' or '#' as separator? The eternal debate rages on!
return String.format("%s:%s", mTestId.getClassName(), mTestId.getTestName());
}
}
/**
* Class that can represent a remote {@link String} stack trace as a {@link Throwable} or
* for display purposes.
*/
private static class RemoteException extends Throwable {
private static final long serialVersionUID = 8510440697482917390L;
private final String mStackTrace;
RemoteException(String stack) {
mStackTrace = stack;
}
@Override
public void printStackTrace() {
System.err.print(mStackTrace);
}
@Override
public void printStackTrace(PrintStream s) {
s.print(mStackTrace);
}
@Override
public void printStackTrace(PrintWriter s) {
s.print(mStackTrace);
}
@Override
public void setStackTrace(StackTraceElement[] stackTrace) {
// Force exception to be thrown here. don't want parent to override the data.
// alternatively could make this a no-op
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return mStackTrace;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
/**
* {@inheritDoc}
*/
@Override
public void invocationEnded(long elapsedTime) {
// ignore
}
/**
* {@inheritDoc}
*/
@Override
public void invocationFailed(Throwable cause) {
// ignore
}
/**
* {@inheritDoc}
*/
@Override
public TestSummary getSummary() {
// ignore
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void invocationStarted(IBuildInfo buildInfo) {
// ignore
}
/**
* {@inheritDoc}
*/
@Override
public void testLog(String dataName, LogDataType logData, InputStreamSource dataStream) {
// ignore
}
@Override
public void testIgnored(TestIdentifier test) {
// ignore
}
}