Home | History | Annotate | Download | only in target
      1 /*
      2  * Copyright (C) 2016 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 vogar.target;
     18 
     19 import java.util.Arrays;
     20 import org.junit.runner.Description;
     21 import org.junit.runner.notification.Failure;
     22 import org.junit.runner.notification.RunListener;
     23 import vogar.Result;
     24 import vogar.monitor.TargetMonitor;
     25 import vogar.target.junit.JUnitUtils;
     26 
     27 /**
     28  * A {@link RunListener} that will notify the vogar main process of the results of the tests.
     29  */
     30 public class TargetMonitorRunListener extends RunListener {
     31 
     32     private final TargetMonitor monitor;
     33     private Failure failure;
     34 
     35     public TargetMonitorRunListener(TargetMonitor monitor) {
     36         this.monitor = monitor;
     37     }
     38 
     39     @Override
     40     public void testStarted(Description description) throws Exception {
     41         failure = null;
     42         monitor.outcomeStarted(JUnitUtils.getTestName(description));
     43     }
     44 
     45     @Override
     46     public void testFailure(Failure failure) throws Exception {
     47         this.failure = failure;
     48     }
     49 
     50     @Override
     51     public void testFinished(Description description) throws Exception {
     52         if (failure == null) {
     53             monitor.outcomeFinished(Result.SUCCESS);
     54         } else {
     55             @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     56             Throwable thrown = failure.getException();
     57             prepareForDisplay(thrown);
     58             thrown.printStackTrace(System.out);
     59             monitor.outcomeFinished(Result.EXEC_FAILED);
     60         }
     61     }
     62 
     63     /**
     64      * Strip vogar's lines from the stack trace. For example, we'd strip the
     65      * first two Assert lines and everything after the testFoo() line in this
     66      * stack trace:
     67      *
     68      *   at junit.framework.Assert.fail(Assert.java:198)
     69      *   at junit.framework.Assert.assertEquals(Assert.java:56)
     70      *   at junit.framework.Assert.assertEquals(Assert.java:61)
     71      *   at libcore.java.net.FooTest.testFoo(FooTest.java:124)
     72      *   at java.lang.reflect.Method.invokeNative(Native Method)
     73      *   at java.lang.reflect.Method.invoke(Method.java:491)
     74      *   at vogar.target.junit.Junit$JUnitTest.run(Junit.java:214)
     75      *   at vogar.target.junit.JUnitRunner$1.call(JUnitRunner.java:112)
     76      *   at vogar.target.junit.JUnitRunner$1.call(JUnitRunner.java:105)
     77      *   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
     78      *   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
     79      *   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
     80      *   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
     81      *   at java.lang.Thread.run(Thread.java:863)
     82      */
     83     private static void prepareForDisplay(Throwable t) {
     84         StackTraceElement[] stackTraceElements = t.getStackTrace();
     85         boolean foundVogar = false;
     86 
     87         int last = stackTraceElements.length - 1;
     88         for (; last >= 0; last--) {
     89             String className = stackTraceElements[last].getClassName();
     90             if (className.startsWith("vogar.target")) {
     91                 foundVogar = true;
     92             } else if (foundVogar
     93                     && !className.startsWith("java.lang.reflect")
     94                     && !className.startsWith("sun.reflect")
     95                     && !className.startsWith("junit.framework")) {
     96                 if (last < stackTraceElements.length) {
     97                     last++;
     98                 }
     99                 break;
    100             }
    101         }
    102 
    103         int first = 0;
    104         for (; first < last; first++) {
    105             String className = stackTraceElements[first].getClassName();
    106             if (!className.startsWith("junit.framework")) {
    107                 break;
    108             }
    109         }
    110 
    111         if (first > 0) {
    112             first--; // retain one assertSomething() line in the trace
    113         }
    114 
    115         if (first < last) {
    116             t.setStackTrace(Arrays.copyOfRange(stackTraceElements, first, last));
    117         }
    118     }
    119 }
    120