Home | History | Annotate | Download | only in invoker
      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.invoker;
     17 
     18 import com.android.ddmlib.Log.LogLevel;
     19 import com.android.ddmlib.testrunner.TestIdentifier;
     20 import com.android.ddmlib.testrunner.TestResult;
     21 import com.android.ddmlib.testrunner.TestResult.TestStatus;
     22 import com.android.ddmlib.testrunner.TestRunResult;
     23 import com.android.tradefed.log.LogUtil.CLog;
     24 import com.android.tradefed.result.CollectingTestListener;
     25 import com.android.tradefed.result.ITestInvocationListener;
     26 import com.android.tradefed.result.InputStreamSource;
     27 import com.android.tradefed.result.LogDataType;
     28 
     29 import java.util.Map;
     30 
     31 /**
     32  * A {@link ITestInvocationListener} that collects results from a invocation shard (aka an
     33  * invocation split to run on multiple resources in parallel), and forwards them to another
     34  * listener.
     35  */
     36 public class ShardListener extends CollectingTestListener {
     37 
     38     private ITestInvocationListener mMasterListener;
     39 
     40     /**
     41      * Create a {@link ShardListener}.
     42      *
     43      * @param master the {@link ITestInvocationListener} the results should be forwarded. To prevent
     44      *     collisions with other {@link ShardListener}s, this object will synchronize on
     45      *     <var>master</var> when forwarding results. And results will only be sent once the
     46      *     invocation shard completes.
     47      */
     48     public ShardListener(ITestInvocationListener master) {
     49         mMasterListener = master;
     50     }
     51 
     52     /**
     53      * {@inheritDoc}
     54      * @deprecated use {@link #invocationStarted(IInvocationContext)} instead.
     55      */
     56     @Override
     57     @Deprecated
     58     public void invocationStarted(IInvocationContext context) {
     59         super.invocationStarted(context);
     60         synchronized (mMasterListener) {
     61             mMasterListener.invocationStarted(context);
     62         }
     63     }
     64 
     65     /**
     66      * {@inheritDoc}
     67      */
     68     @Override
     69     public void invocationFailed(Throwable cause) {
     70         super.invocationFailed(cause);
     71         synchronized (mMasterListener) {
     72             mMasterListener.invocationFailed(cause);
     73         }
     74     }
     75 
     76     /**
     77      * {@inheritDoc}
     78      */
     79     @Override
     80     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
     81         // forward testLog results immediately, since they are not order dependent and there are
     82         // not stored by CollectingTestListener
     83         synchronized (mMasterListener) {
     84             mMasterListener.testLog(dataName, dataType, dataStream);
     85         }
     86     }
     87 
     88     /**
     89      * {@inheritDoc}
     90      */
     91     @Override
     92     public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {
     93         super.testRunEnded(elapsedTime, runMetrics);
     94         CLog.logAndDisplay(LogLevel.INFO, "Sharded test completed: %s",
     95                 getCurrentRunResults().getName());
     96     }
     97 
     98     /**
     99      * {@inheritDoc}
    100      */
    101     @Override
    102     public void testRunFailed(String failureMessage) {
    103         super.testRunFailed(failureMessage);
    104         CLog.logAndDisplay(LogLevel.ERROR, "FAILED: %s failed with message: %s",
    105                 getCurrentRunResults().getName(), failureMessage);
    106     }
    107 
    108     /**
    109      * {@inheritDoc}
    110      */
    111     @Override
    112     public void invocationEnded(long elapsedTime) {
    113         super.invocationEnded(elapsedTime);
    114         synchronized (mMasterListener) {
    115             for (TestRunResult runResult : getRunResults()) {
    116                 mMasterListener.testRunStarted(runResult.getName(), runResult.getNumTests());
    117                 forwardTestResults(runResult.getTestResults());
    118                 if (runResult.isRunFailure()) {
    119                     mMasterListener.testRunFailed(runResult.getRunFailureMessage());
    120                 }
    121                 mMasterListener.testRunEnded(runResult.getElapsedTime(), runResult.getRunMetrics());
    122             }
    123             mMasterListener.invocationEnded(elapsedTime);
    124         }
    125     }
    126 
    127     private void forwardTestResults(Map<TestIdentifier, TestResult> testResults) {
    128         for (Map.Entry<TestIdentifier, TestResult> testEntry : testResults.entrySet()) {
    129             mMasterListener.testStarted(testEntry.getKey(), testEntry.getValue().getStartTime());
    130             switch (testEntry.getValue().getStatus()) {
    131                 case FAILURE:
    132                     mMasterListener.testFailed(testEntry.getKey(),
    133                             testEntry.getValue().getStackTrace());
    134                     break;
    135                 case ASSUMPTION_FAILURE:
    136                     mMasterListener.testAssumptionFailure(testEntry.getKey(),
    137                             testEntry.getValue().getStackTrace());
    138                     break;
    139                 case IGNORED:
    140                     mMasterListener.testIgnored(testEntry.getKey());
    141                     break;
    142                 default:
    143                     break;
    144             }
    145             if (!testEntry.getValue().getStatus().equals(TestStatus.INCOMPLETE)) {
    146                 mMasterListener.testEnded(
    147                         testEntry.getKey(),
    148                         testEntry.getValue().getEndTime(),
    149                         testEntry.getValue().getMetrics());
    150             }
    151         }
    152     }
    153 }
    154