/*
* Copyright (C) 2008 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.ddmlib.testrunner;
import junit.framework.TestCase;
/**
* Tests InstrumentationResultParser.
*/
public class InstrumentationResultParserTest extends TestCase {
private InstrumentationResultParser mParser;
private VerifyingTestResult mTestResult;
// static dummy test names to use for validation
private static final String CLASS_NAME = "com.test.FooTest";
private static final String TEST_NAME = "testFoo";
private static final String STACK_TRACE = "java.lang.AssertionFailedException";
/**
* @param name - test name
*/
public InstrumentationResultParserTest(String name) {
super(name);
}
/**
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
mTestResult = new VerifyingTestResult();
mParser = new InstrumentationResultParser(mTestResult);
}
/**
* Tests that the test run started and test start events is sent on first
* bundle received.
*/
public void testTestStarted() {
StringBuilder output = buildCommonResult();
addStartCode(output);
injectTestString(output.toString());
assertCommonAttributes();
assertEquals(0, mTestResult.mNumTestsRun);
}
/**
* Tests that a single successful test execution.
*/
public void testTestSuccess() {
StringBuilder output = buildCommonResult();
addStartCode(output);
addCommonStatus(output);
addSuccessCode(output);
injectTestString(output.toString());
assertCommonAttributes();
assertEquals(1, mTestResult.mNumTestsRun);
assertEquals(null, mTestResult.mTestStatus);
}
/**
* Test basic parsing of failed test case.
*/
public void testTestFailed() {
StringBuilder output = buildCommonResult();
addStartCode(output);
addCommonStatus(output);
addStackTrace(output);
addFailureCode(output);
injectTestString(output.toString());
assertCommonAttributes();
assertEquals(1, mTestResult.mNumTestsRun);
assertEquals(ITestRunListener.TestFailure.FAILURE, mTestResult.mTestStatus);
assertEquals(STACK_TRACE, mTestResult.mTrace);
}
/**
* Test basic parsing and conversion of time from output.
*/
public void testTimeParsing() {
final String timeString = "Time: 4.9";
injectTestString(timeString);
assertEquals(4900, mTestResult.mTestTime);
}
/**
* Test basic parsing of a test run failure.
*/
public void testRunFailed() {
StringBuilder output = new StringBuilder();
final String errorMessage = "Unable to find instrumentation info";
addStatusKey(output, "Error", errorMessage);
addStatusCode(output, "-1");
output.append("INSTRUMENTATION_FAILED: com.dummy/android.test.InstrumentationTestRunner");
addLineBreak(output);
injectTestString(output.toString());
assertEquals(errorMessage, mTestResult.mRunFailedMessage);
}
/**
* Test parsing of a test run failure, where an instrumentation component failed to load
* Parsing input takes the from of INSTRUMENTATION_RESULT: fff
*/
public void testRunFailedResult() {
StringBuilder output = new StringBuilder();
final String errorMessage = "Unable to instantiate instrumentation";
output.append("INSTRUMENTATION_RESULT: shortMsg=");
output.append(errorMessage);
addLineBreak(output);
output.append("INSTRUMENTATION_CODE: 0");
addLineBreak(output);
injectTestString(output.toString());
assertEquals(errorMessage, mTestResult.mRunFailedMessage);
}
/**
* Builds a common test result using TEST_NAME and TEST_CLASS.
*/
private StringBuilder buildCommonResult() {
StringBuilder output = new StringBuilder();
// add test start bundle
addCommonStatus(output);
addStatusCode(output, "1");
// add end test bundle, without status
addCommonStatus(output);
return output;
}
/**
* Adds common status results to the provided output.
*/
private void addCommonStatus(StringBuilder output) {
addStatusKey(output, "stream", "\r\n" + CLASS_NAME);
addStatusKey(output, "test", TEST_NAME);
addStatusKey(output, "class", CLASS_NAME);
addStatusKey(output, "current", "1");
addStatusKey(output, "numtests", "1");
addStatusKey(output, "id", "InstrumentationTestRunner");
}
/**
* Adds a stack trace status bundle to output.
*/
private void addStackTrace(StringBuilder output) {
addStatusKey(output, "stack", STACK_TRACE);
}
/**
* Helper method to add a status key-value bundle.
*/
private void addStatusKey(StringBuilder outputBuilder, String key,
String value) {
outputBuilder.append("INSTRUMENTATION_STATUS: ");
outputBuilder.append(key);
outputBuilder.append('=');
outputBuilder.append(value);
addLineBreak(outputBuilder);
}
/**
* Append line break characters to output
*/
private void addLineBreak(StringBuilder outputBuilder) {
outputBuilder.append("\r\n");
}
private void addStartCode(StringBuilder outputBuilder) {
addStatusCode(outputBuilder, "1");
}
private void addSuccessCode(StringBuilder outputBuilder) {
addStatusCode(outputBuilder, "0");
}
private void addFailureCode(StringBuilder outputBuilder) {
addStatusCode(outputBuilder, "-2");
}
private void addStatusCode(StringBuilder outputBuilder, String value) {
outputBuilder.append("INSTRUMENTATION_STATUS_CODE: ");
outputBuilder.append(value);
addLineBreak(outputBuilder);
}
/**
* inject a test string into the result parser.
*
* @param result
*/
private void injectTestString(String result) {
byte[] data = result.getBytes();
mParser.addOutput(data, 0, data.length);
mParser.flush();
}
private void assertCommonAttributes() {
assertEquals(CLASS_NAME, mTestResult.mSuiteName);
assertEquals(1, mTestResult.mTestCount);
assertEquals(TEST_NAME, mTestResult.mTestName);
}
/**
* A specialized test listener that stores a single test events.
*/
private class VerifyingTestResult implements ITestRunListener {
String mSuiteName;
int mTestCount;
int mNumTestsRun;
String mTestName;
long mTestTime;
TestFailure mTestStatus;
String mTrace;
boolean mStopped;
/** stores the error message provided to testRunFailed */
String mRunFailedMessage;
VerifyingTestResult() {
mNumTestsRun = 0;
mTestStatus = null;
mStopped = false;
mRunFailedMessage = null;
}
public void testEnded(TestIdentifier test) {
mNumTestsRun++;
assertEquals("Unexpected class name", mSuiteName, test.getClassName());
assertEquals("Unexpected test ended", mTestName, test.getTestName());
}
public void testFailed(TestFailure status, TestIdentifier test, String trace) {
mTestStatus = status;
mTrace = trace;
assertEquals("Unexpected class name", mSuiteName, test.getClassName());
assertEquals("Unexpected test ended", mTestName, test.getTestName());
}
public void testRunEnded(long elapsedTime) {
mTestTime = elapsedTime;
}
public void testRunStarted(int testCount) {
mTestCount = testCount;
}
public void testRunStopped(long elapsedTime) {
mTestTime = elapsedTime;
mStopped = true;
}
public void testStarted(TestIdentifier test) {
mSuiteName = test.getClassName();
mTestName = test.getTestName();
}
public void testRunFailed(String errorMessage) {
mRunFailedMessage = errorMessage;
}
}
}
|