blob: 429ae92235dedf3e91f6b91355fcbcdb77b8d94c [file] [log] [blame]
/*
* Copyright (C) 2016 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.cts.core.runner;
import android.app.Instrumentation;
import android.os.Bundle;
import android.support.test.internal.util.AndroidRunnerParams;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import junit.framework.AssertionFailedError;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import static android.app.Instrumentation.REPORT_KEY_IDENTIFIER;
import static android.app.Instrumentation.REPORT_KEY_STREAMRESULT;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.REPORT_KEY_RUNTIME;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.REPORT_VALUE_ID;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NAME_CLASS;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NAME_TEST;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NUM_CURRENT;
import static android.test.InstrumentationTestRunner.REPORT_KEY_NUM_TOTAL;
import static android.test.InstrumentationTestRunner.REPORT_KEY_STACK;
import static android.test.InstrumentationTestRunner.REPORT_VALUE_RESULT_ERROR;
import static android.test.InstrumentationTestRunner.REPORT_VALUE_RESULT_FAILURE;
import static android.test.InstrumentationTestRunner.REPORT_VALUE_RESULT_OK;
import static android.test.InstrumentationTestRunner.REPORT_VALUE_RESULT_START;
/**
* Listens to result of running tests, collates details and sends intermediate status information
* back to the host.
*/
class StatusUpdaterRunListener extends RunListener {
/**
* The {@link Instrumentation} for which this will report information.
*/
private final Instrumentation instrumentation;
private final AndroidRunnerParams runnerParams;
private final int totalTestCount;
/**
* The list of failed tests.
*/
private final List<String> failedTests;
private Bundle currentTestResult;
private int resultStatus;
private int totalSuccess = 0;
private int totalFailures = 0;
private long runStartTime;
private long runElapsedTime;
private long testStartTime;
public StatusUpdaterRunListener(Instrumentation instrumentation,
AndroidRunnerParams runnerParams,
int totalTestCount) {
this.instrumentation = instrumentation;
this.runnerParams = runnerParams;
this.totalTestCount = totalTestCount;
failedTests = new ArrayList<>();
}
/**
* Send an update to the test runner informing it we are starting a test. If this is not run
* then
* the test runner will think the test was never run, and mark it as failed.
*
* @param className
* The name of the class being tested.
* @param methodName
* The name of the test method being tested.
* @return A bundle containing test class, method, and report name. This bundle has been sent
* back
* to the host.
*/
private Bundle sendStartTestInfo(String className, int testNum, String methodName) {
Bundle data = new Bundle();
data.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
data.putInt(REPORT_KEY_NUM_TOTAL, totalTestCount);
data.putInt(REPORT_KEY_NUM_CURRENT, testNum);
data.putString(REPORT_KEY_NAME_CLASS, className);
data.putString(REPORT_KEY_NAME_TEST, methodName);
instrumentation.sendStatus(REPORT_VALUE_RESULT_START, data);
return data;
}
@Override
public void testRunStarted(Description description) throws Exception {
runStartTime = System.currentTimeMillis();
}
@Override
public void testStarted(Description description) throws Exception {
String className = description.getClassName();
int count = totalSuccess + totalFailures;
String methodName = description.getMethodName();
currentTestResult = sendStartTestInfo(className, count, methodName);
resultStatus = REPORT_VALUE_RESULT_OK;
testStartTime = System.currentTimeMillis();
}
@Override
public void testFailure(Failure failure) throws Exception {
Description description = failure.getDescription();
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
Throwable exception = failure.getException();
if (exception instanceof AssertionFailedError) {
resultStatus = REPORT_VALUE_RESULT_FAILURE;
} else {
resultStatus = REPORT_VALUE_RESULT_ERROR;
}
String information = failure.getTrace();
currentTestResult.putString(REPORT_KEY_STACK, information);
String output = "Error: " + description + "\n" + information;
currentTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, output);
}
@Override
public void testFinished(Description description) throws Exception {
long timeTaken = System.currentTimeMillis() - testStartTime;
currentTestResult.putFloat(REPORT_KEY_RUNTIME, timeTaken / 1000);
if (resultStatus == REPORT_VALUE_RESULT_OK) {
totalSuccess++;
String output = "Success: " + description;
currentTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, output);
} else {
totalFailures++;
failedTests.add(description.toString());
}
instrumentation.sendStatus(resultStatus, currentTestResult);
}
@Override
public void testRunFinished(Result result) throws Exception {
runElapsedTime = System.currentTimeMillis() - runStartTime;
}
public Bundle getFinalResults() {
int totalTests = totalFailures + totalSuccess;
Log.d(CoreTestRunner.TAG, (runnerParams.isSkipExecution() ? "Skipped " : "Ran ")
+ totalTests + " tests, " + totalSuccess + " passed, " + totalFailures + " failed");
Bundle results = new Bundle();
results.putString(REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
results.putInt(REPORT_KEY_NUM_TOTAL, totalTests);
String report;
if (totalFailures == 0) {
report = "All " + totalSuccess + " tests passed.\n";
} else {
report = "Failures " + totalFailures + '\n';
for (String classname : failedTests) {
report += classname + '\n';
}
}
// Report the elapsed time (in seconds).
report += "Time: " + (runElapsedTime / 1000.0);
results.putString(REPORT_KEY_STREAMRESULT, report);
return results;
}
public Bundle getCountResults() {
Log.d(CoreTestRunner.TAG, "Counted " + (totalFailures + totalSuccess) + " tests, "
+ totalSuccess + " passed, " + totalFailures + " failed");
Bundle results = new Bundle();
results.putString(REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
results.putInt(REPORT_KEY_NUM_TOTAL, totalSuccess);
return results;
}
}