Home | History | Annotate | Download | only in result
      1 /*
      2  * Copyright (C) 2010 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 
     17 package com.android.tradefed.result;
     18 
     19 import com.android.tradefed.log.LogUtil.CLog;
     20 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
     21 
     22 import junit.framework.AssertionFailedError;
     23 import junit.framework.Test;
     24 import junit.framework.TestCase;
     25 import junit.framework.TestListener;
     26 
     27 import java.io.ByteArrayOutputStream;
     28 import java.io.PrintStream;
     29 import java.lang.annotation.Annotation;
     30 import java.lang.reflect.Method;
     31 import java.util.ArrayList;
     32 import java.util.HashMap;
     33 import java.util.List;
     34 
     35 /**
     36  * A class that listens to {@link junit.framework.TestListener} events and forwards them to an
     37  * {@link ITestInvocationListener}.
     38  * <p/>
     39  */
     40 public class JUnitToInvocationResultForwarder implements TestListener {
     41 
     42     private final List<ITestInvocationListener> mInvocationListeners;
     43 
     44     public JUnitToInvocationResultForwarder(ITestInvocationListener invocationListener) {
     45         mInvocationListeners = new ArrayList<ITestInvocationListener>(1);
     46         mInvocationListeners.add(invocationListener);
     47     }
     48 
     49     public JUnitToInvocationResultForwarder(List<ITestInvocationListener> invocationListeners) {
     50         mInvocationListeners = new ArrayList<ITestInvocationListener>(invocationListeners.size());
     51         mInvocationListeners.addAll(invocationListeners);
     52     }
     53 
     54     /**
     55      * {@inheritDoc}
     56      */
     57     @Override
     58     public void addError(Test test, Throwable t) {
     59         for (ITestInvocationListener listener : mInvocationListeners) {
     60             listener.testFailed(getTestId(test), getStackTrace(t));
     61         }
     62     }
     63 
     64     /**
     65      * {@inheritDoc}
     66      */
     67     @Override
     68     public void addFailure(Test test, AssertionFailedError t) {
     69         for (ITestInvocationListener listener : mInvocationListeners) {
     70             listener.testFailed(getTestId(test), getStackTrace(t));
     71         }
     72     }
     73 
     74     /**
     75      * {@inheritDoc}
     76      */
     77     @Override
     78     public void endTest(Test test) {
     79         HashMap<String, Metric> emptyMap = new HashMap<>();
     80         for (ITestInvocationListener listener : mInvocationListeners) {
     81             listener.testEnded(getTestId(test), emptyMap);
     82         }
     83     }
     84 
     85     /**
     86      * Callback from JUnit3 tests that can forward metrics.
     87      *
     88      * @param test The {@link Test} that just finished running.
     89      * @param metrics The metrics in a Map format to be passed to the results callback.
     90      */
     91     public void endTest(Test test, HashMap<String, Metric> metrics) {
     92         for (ITestInvocationListener listener : mInvocationListeners) {
     93             listener.testEnded(getTestId(test), metrics);
     94         }
     95     }
     96 
     97     /**
     98      * Callback from JUnit3 forwarder in order to get the logs from a test.
     99      *
    100      * @param dataName a String descriptive name of the data. e.g. "device_logcat". Note dataName
    101      *     may not be unique per invocation. ie implementers must be able to handle multiple calls
    102      *     with same dataName
    103      * @param dataType the LogDataType of the data
    104      * @param dataStream the InputStreamSource of the data. Implementers should call
    105      *     createInputStream to start reading the data, and ensure to close the resulting
    106      *     InputStream when complete. Callers should ensure the source of the data remains present
    107      *     and accessible until the testLog method completes.
    108      */
    109     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
    110         for (ITestInvocationListener listener : mInvocationListeners) {
    111             listener.testLog(dataName, dataType, dataStream);
    112         }
    113     }
    114 
    115     /** {@inheritDoc} */
    116     @Override
    117     public void startTest(Test test) {
    118         for (ITestInvocationListener listener : mInvocationListeners) {
    119             listener.testStarted(getTestId(test));
    120         }
    121     }
    122 
    123     /**
    124      * Return the {@link TestDescription} equivalent for the {@link Test}.
    125      *
    126      * @param test the {@link Test} to convert
    127      * @return the {@link TestDescription}
    128      */
    129     private TestDescription getTestId(Test test) {
    130         final String className = test.getClass().getName();
    131         String testName = "";
    132         if (test instanceof TestCase) {
    133             testName = ((TestCase) test).getName();
    134         }
    135         Annotation[] annotations = new Annotation[0];
    136         try {
    137             // Backfill the annotations on a JUnit3 method
    138             Method testMethod = test.getClass().getMethod(testName);
    139             annotations = testMethod.getAnnotations();
    140         } catch (NoSuchMethodException | SecurityException e) {
    141             // Should not happen, at that point the test method is ensured to exists.
    142             CLog.e("Ignoring this exception:");
    143             CLog.e(e);
    144         }
    145         return new TestDescription(className, testName, annotations);
    146     }
    147 
    148     /**
    149      * Gets the stack trace in {@link String}.
    150      *
    151      * @param throwable the {@link Throwable} to convert.
    152      * @return a {@link String} stack trace
    153      */
    154     private String getStackTrace(Throwable throwable) {
    155         // dump the print stream results to the ByteArrayOutputStream, so contents can be evaluated
    156         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    157         PrintStream bytePrintStream = new PrintStream(outputStream);
    158         throwable.printStackTrace(bytePrintStream);
    159         return outputStream.toString();
    160     }
    161 }
    162