Home | History | Annotate | Download | only in coretests
      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