Home | History | Annotate | Download | only in testtype
      1 /*
      2  * Copyright (C) 2011 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.android.tradefed.testtype;
     17 
     18 import com.android.tradefed.device.DeviceNotAvailableException;
     19 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
     20 import com.android.tradefed.result.JUnitToInvocationResultForwarder;
     21 import com.android.tradefed.testtype.MetricTestCase.LogHolder;
     22 import com.android.tradefed.util.StreamUtil;
     23 
     24 import junit.framework.AssertionFailedError;
     25 import junit.framework.Protectable;
     26 import junit.framework.Test;
     27 import junit.framework.TestCase;
     28 import junit.framework.TestListener;
     29 import junit.framework.TestResult;
     30 
     31 import java.util.ArrayList;
     32 import java.util.HashMap;
     33 import java.util.List;
     34 
     35 /**
     36  * An specialization of {@link junit.framework.TestResult} that will abort when a
     37  * {@link DeviceNotAvailableException} occurs
     38  */
     39 public class DeviceTestResult extends TestResult {
     40 
     41     @SuppressWarnings("serial")
     42     public class RuntimeDeviceNotAvailableException extends RuntimeException {
     43         private DeviceNotAvailableException mException;
     44 
     45         RuntimeDeviceNotAvailableException(DeviceNotAvailableException e) {
     46             super(e.getMessage());
     47             mException = e;
     48         }
     49 
     50         DeviceNotAvailableException getDeviceException() {
     51             return mException;
     52         }
     53     }
     54 
     55     /**
     56      * Runs a TestCase.
     57      *
     58      * @throws RuntimeDeviceNotAvailableException if a DeviceNotAvailableException occurs
     59      */
     60     @Override
     61     public void runProtected(final Test test, Protectable p) {
     62         // this is a copy of the superclass runProtected code, with the extra clause
     63         // for DeviceNotAvailableException
     64         try {
     65             p.protect();
     66         }
     67         catch (AssertionFailedError e) {
     68             addFailure(test, e);
     69         }
     70         catch (ThreadDeath e) { // don't catch ThreadDeath by accident
     71             throw e;
     72         }
     73         catch (DeviceNotAvailableException e) {
     74             addError(test, e);
     75             throw new RuntimeDeviceNotAvailableException(e);
     76         }
     77         catch (Throwable e) {
     78             addError(test, e);
     79         }
     80     }
     81 
     82     @Override
     83     protected void run(final TestCase test) {
     84         // this is a copy of the superclass run code, with the extra finally clause
     85         // to ensure endTest is called when RuntimeDeviceNotAvailableException occurs
     86         startTest(test);
     87         Protectable p = new Protectable() {
     88             @Override
     89             public void protect() throws Throwable {
     90                 test.runBare();
     91             }
     92         };
     93         try {
     94             runProtected(test, p);
     95         } finally {
     96             endTest(test);
     97         }
     98     }
     99 
    100     /** {@inheritDoc} */
    101     @Override
    102     public void endTest(Test test) {
    103         HashMap<String, Metric> metrics = new HashMap<>();
    104         if (test instanceof MetricTestCase) {
    105             MetricTestCase metricTest = (MetricTestCase) test;
    106             metrics.putAll(metricTest.mMetrics);
    107             // reset the metric for next test.
    108             metricTest.mMetrics = new HashMap<String, Metric>();
    109 
    110             // testLog the log files
    111             for (TestListener each : cloneListeners()) {
    112                 for (LogHolder log : metricTest.mLogs) {
    113                     if (each instanceof JUnitToInvocationResultForwarder) {
    114                         ((JUnitToInvocationResultForwarder) each)
    115                                 .testLog(log.mDataName, log.mDataType, log.mDataStream);
    116                     }
    117                     StreamUtil.cancel(log.mDataStream);
    118                 }
    119             }
    120             metricTest.mLogs.clear();
    121         }
    122 
    123         for (TestListener each : cloneListeners()) {
    124             // when possible pass the metrics collected from the tests to our reporters.
    125             if (!metrics.isEmpty() && each instanceof JUnitToInvocationResultForwarder) {
    126                 ((JUnitToInvocationResultForwarder) each).endTest(test, metrics);
    127             } else {
    128                 each.endTest(test);
    129             }
    130         }
    131     }
    132 
    133     /**
    134      * Returns a copy of the listeners. Copied from {@link TestResult} to enable overriding {@link
    135      * #endTest(Test)} in a similar way. This allows to override {@link #endTest(Test)} and report
    136      * our metrics.
    137      */
    138     private synchronized List<TestListener> cloneListeners() {
    139         List<TestListener> result = new ArrayList<TestListener>();
    140         result.addAll(fListeners);
    141         return result;
    142     }
    143 }
    144