/* * 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; } }