blob: 802eff845137a4672883e8ebc03320e69e4727ae [file] [log] [blame]
/*
* Copyright (C) 2009 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.google.coretests;
import java.lang.reflect.Method;
import junit.framework.Protectable;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.SideEffect;
/**
* A special TestResult implementation that is able to filter out annotated
* tests and handles our known failures properly (expects them to fail).
* Handy when running the Core Libraries tests on Android, the bare-metal
* Dalvik VM, or the RI.
*/
public class CoreTestResult extends TestResult {
/**
* The flags the user specified for this test run.
*/
protected int fFlags;
/**
* The timeout the user specified for this test run.
*/
protected int fTimeout;
/**
* The total number of tests in the original suite.
*/
protected int fTotalTestCount;
/**
* The number of Android-only tests in the original suite.
*/
protected int fAndroidOnlyCount;
/**
* The number of broken tests in the original suite.
*/
protected int fBrokenTestCount;
/**
* The number of known failures in the original suite.
*/
protected int fKnownFailureCount;
/**
* The number of side-effective tests in the original suite.
*/
protected int fSideEffectCount;
/**
* The number of normal (non-annotated) tests in the original suite.
*/
protected int fNormalTestCount;
/**
* The number of ignored tests, that is, the number of tests that were
* excluded from this suite due to their annotations.
*/
protected int fIgnoredCount;
/**
* Creates a new CoreTestResult with the given flags and timeout.
*/
public CoreTestResult(int flags, int timeout) {
super();
fFlags = flags;
fTimeout = timeout;
}
/**
* Checks whether the given TestCase method has the given annotation.
*/
@SuppressWarnings("unchecked")
boolean hasAnnotation(TestCase test, Class clazz) {
try {
Method method = test.getClass().getMethod(test.getName());
return method.getAnnotation(clazz) != null;
} catch (Exception e) {
// Ignore
}
return false;
}
@Override
@SuppressWarnings("deprecation")
public void runProtected(final Test test, Protectable p) {
if ((fFlags & CoreTestSuite.DRY_RUN) == 0) {
if (test instanceof TestCase) {
TestCase testCase = (TestCase)test;
// Check whether we need to invert the test result (known failures)
boolean invert = hasAnnotation(testCase, KnownFailure.class) &&
(fFlags & CoreTestSuite.INVERT_KNOWN_FAILURES) != 0;
// Check whether we need to isolate the test (side effects)
boolean isolate = hasAnnotation(testCase, SideEffect.class) &&
(fFlags & CoreTestSuite.ISOLATE_NONE) == 0 ||
(fFlags & CoreTestSuite.ISOLATE_ALL) != 0;
CoreTestRunnable runnable = new CoreTestRunnable(
testCase, this, p, invert, isolate);
if (fTimeout > 0) {
Thread thread = new Thread(runnable);
thread.start();
try {
thread.join(fTimeout * 1000);
} catch (InterruptedException ex) {
// Ignored
}
if (thread.isAlive()) {
StackTraceElement[] trace = thread.getStackTrace();
runnable.stop();
thread.stop();
try {
thread.join(fTimeout * 1000);
} catch (InterruptedException ex) {
// Ignored
}
CoreTestTimeout timeout = new CoreTestTimeout("Test timed out");
timeout.setStackTrace(trace);
addError(test, timeout);
}
} else {
runnable.run();
}
}
}
}
/**
* Updates the statistics in this TestResult. Called from the TestSuite,
* since, once the original suite has been filtered, we don't actually see
* these tests here anymore.
*/
void updateStats(int total, int androidOnly, int broken, int knownFailure,
int normal, int ignored, int sideEffect) {
this.fTotalTestCount += total;
this.fAndroidOnlyCount += androidOnly;
this.fBrokenTestCount += broken;
this.fKnownFailureCount += knownFailure;
this.fNormalTestCount += normal;
this.fIgnoredCount += ignored;
this.fSideEffectCount += sideEffect;
}
}