1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.coretests; 17 18 import java.lang.reflect.Method; 19 20 import junit.framework.Protectable; 21 import junit.framework.Test; 22 import junit.framework.TestCase; 23 import junit.framework.TestResult; 24 import dalvik.annotation.KnownFailure; 25 import dalvik.annotation.SideEffect; 26 27 /** 28 * A special TestResult implementation that is able to filter out annotated 29 * tests and handles our known failures properly (expects them to fail). 30 * Handy when running the Core Libraries tests on Android, the bare-metal 31 * Dalvik VM, or the RI. 32 */ 33 public class CoreTestResult extends TestResult { 34 35 /** 36 * The flags the user specified for this test run. 37 */ 38 protected int fFlags; 39 40 /** 41 * The timeout the user specified for this test run. 42 */ 43 protected int fTimeout; 44 45 /** 46 * The total number of tests in the original suite. 47 */ 48 protected int fTotalTestCount; 49 50 /** 51 * The number of Android-only tests in the original suite. 52 */ 53 protected int fAndroidOnlyCount; 54 55 /** 56 * The number of broken tests in the original suite. 57 */ 58 protected int fBrokenTestCount; 59 60 /** 61 * The number of known failures in the original suite. 62 */ 63 protected int fKnownFailureCount; 64 65 /** 66 * The number of side-effective tests in the original suite. 67 */ 68 protected int fSideEffectCount; 69 70 /** 71 * The number of normal (non-annotated) tests in the original suite. 72 */ 73 protected int fNormalTestCount; 74 75 /** 76 * The number of ignored tests, that is, the number of tests that were 77 * excluded from this suite due to their annotations. 78 */ 79 protected int fIgnoredCount; 80 81 /** 82 * Creates a new CoreTestResult with the given flags and timeout. 83 */ 84 public CoreTestResult(int flags, int timeout) { 85 super(); 86 87 fFlags = flags; 88 fTimeout = timeout; 89 } 90 91 /** 92 * Checks whether the given TestCase method has the given annotation. 93 */ 94 @SuppressWarnings("unchecked") 95 boolean hasAnnotation(TestCase test, Class clazz) { 96 try { 97 Method method = test.getClass().getMethod(test.getName()); 98 return method.getAnnotation(clazz) != null; 99 } catch (Exception e) { 100 // Ignore 101 } 102 103 return false; 104 } 105 106 @Override 107 @SuppressWarnings("deprecation") 108 public void runProtected(final Test test, Protectable p) { 109 if ((fFlags & CoreTestSuite.DRY_RUN) == 0) { 110 if (test instanceof TestCase) { 111 TestCase testCase = (TestCase)test; 112 113 // Check whether we need to invert the test result (known failures) 114 boolean invert = hasAnnotation(testCase, KnownFailure.class) && 115 (fFlags & CoreTestSuite.INVERT_KNOWN_FAILURES) != 0; 116 117 // Check whether we need to isolate the test (side effects) 118 boolean isolate = hasAnnotation(testCase, SideEffect.class) && 119 (fFlags & CoreTestSuite.ISOLATE_NONE) == 0 || 120 (fFlags & CoreTestSuite.ISOLATE_ALL) != 0; 121 122 CoreTestRunnable runnable = new CoreTestRunnable( 123 testCase, this, p, invert, isolate); 124 125 if (fTimeout > 0) { 126 Thread thread = new Thread(runnable); 127 thread.start(); 128 try { 129 thread.join(fTimeout * 1000); 130 } catch (InterruptedException ex) { 131 // Ignored 132 } 133 if (thread.isAlive()) { 134 StackTraceElement[] trace = thread.getStackTrace(); 135 runnable.stop(); 136 thread.stop(); 137 try { 138 thread.join(fTimeout * 1000); 139 } catch (InterruptedException ex) { 140 // Ignored 141 } 142 143 CoreTestTimeout timeout = new CoreTestTimeout("Test timed out"); 144 timeout.setStackTrace(trace); 145 addError(test, timeout); 146 } 147 } else { 148 runnable.run(); 149 } 150 } 151 } 152 } 153 154 /** 155 * Updates the statistics in this TestResult. Called from the TestSuite, 156 * since, once the original suite has been filtered, we don't actually see 157 * these tests here anymore. 158 */ 159 void updateStats(int total, int androidOnly, int broken, int knownFailure, 160 int normal, int ignored, int sideEffect) { 161 162 this.fTotalTestCount += total; 163 this.fAndroidOnlyCount += androidOnly; 164 this.fBrokenTestCount += broken; 165 this.fKnownFailureCount += knownFailure; 166 this.fNormalTestCount += normal; 167 this.fIgnoredCount += ignored; 168 this.fSideEffectCount += sideEffect; 169 } 170 } 171