• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.suite;
17 
18 import com.android.ddmlib.Log.LogLevel;
19 import com.android.tradefed.log.LogUtil.CLog;
20 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
21 import com.android.tradefed.result.CollectingTestListener;
22 import com.android.tradefed.result.ILogSaverListener;
23 import com.android.tradefed.result.ITestInvocationListener;
24 import com.android.tradefed.result.InputStreamSource;
25 import com.android.tradefed.result.LogDataType;
26 import com.android.tradefed.result.LogFile;
27 import com.android.tradefed.result.LogSaverResultForwarder;
28 import com.android.tradefed.result.TestDescription;
29 import com.android.tradefed.result.TestRunResult;
30 import com.android.tradefed.testtype.IRemoteTest;
31 
32 import java.util.HashMap;
33 
34 /**
35  * Listener attached to each {@link IRemoteTest} of each module in order to collect the list of
36  * results.
37  */
38 public class ModuleListener extends CollectingTestListener {
39 
40     private boolean mSkip = false;
41     private boolean mTestFailed = false;
42     private int mTestsRan = 1;
43     private ITestInvocationListener mMainListener;
44     private boolean mHasFailed = false;
45 
46     private boolean mCollectTestsOnly = false;
47     /** Track runs in progress for logging purpose */
48     private boolean mRunInProgress = false;
49 
50     /** Constructor. */
ModuleListener(ITestInvocationListener listener)51     public ModuleListener(ITestInvocationListener listener) {
52         mMainListener = listener;
53         mRunInProgress = false;
54         setIsAggregrateMetrics(true);
55     }
56 
57     /** Sets whether or not we are only collecting the tests. */
setCollectTestsOnly(boolean collectTestsOnly)58     public void setCollectTestsOnly(boolean collectTestsOnly) {
59         mCollectTestsOnly = collectTestsOnly;
60     }
61 
62     @Override
testRunStarted(String name, int numTests, int attemptNumber)63     public void testRunStarted(String name, int numTests, int attemptNumber) {
64         mRunInProgress = true;
65         // In case of retry of the same run, do not add the expected count again. This allows
66         // situation where test runner has a built-in retry (like InstrumentationTest) and calls
67         // testRunStart several times to be counted properly.
68         if (getTestRunAtAttempt(name, attemptNumber) != null) {
69             numTests = 0;
70         }
71         super.testRunStarted(name, numTests, attemptNumber);
72         if (attemptNumber != 0) {
73             mTestsRan = 1;
74         }
75     }
76 
77     /** {@inheritDoc} */
78     @Override
testRunFailed(String errorMessage)79     public void testRunFailed(String errorMessage) {
80         mHasFailed = true;
81         CLog.d("ModuleListener.testRunFailed(%s)", errorMessage);
82         super.testRunFailed(errorMessage);
83     }
84 
85     /** {@inheritDoc} */
86     @Override
testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics)87     public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) {
88         super.testRunEnded(elapsedTime, runMetrics);
89         mRunInProgress = false;
90     }
91 
92     /** Returns whether or not the listener session has failed. */
hasFailed()93     public boolean hasFailed() {
94         return mHasFailed;
95     }
96 
97     /** {@inheritDoc} */
98     @Override
testStarted(TestDescription test, long startTime)99     public void testStarted(TestDescription test, long startTime) {
100         if (!mCollectTestsOnly) {
101             CLog.d("ModuleListener.testStarted(%s)", test.toString());
102         }
103         mTestFailed = false;
104         super.testStarted(test, startTime);
105         if (mSkip) {
106             super.testIgnored(test);
107         }
108     }
109 
110     /** Helper to log the test passed if it didn't fail. */
logTestPassed(String testName)111     private void logTestPassed(String testName) {
112         if (!mTestFailed && !mCollectTestsOnly) {
113             CLog.logAndDisplay(
114                     LogLevel.INFO, "[%d/%d] %s pass", mTestsRan, getExpectedTests(), testName);
115         }
116         mTestsRan++;
117     }
118 
119     /** {@inheritDoc} */
120     @Override
testEnded(TestDescription test, HashMap<String, Metric> testMetrics)121     public void testEnded(TestDescription test, HashMap<String, Metric> testMetrics) {
122         testEnded(test, System.currentTimeMillis(), testMetrics);
123     }
124 
125     /** {@inheritDoc} */
126     @Override
testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics)127     public void testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics) {
128         logTestPassed(test.toString());
129         super.testEnded(test, endTime, testMetrics);
130     }
131 
132     /** {@inheritDoc} */
133     @Override
testFailed(TestDescription test, String trace)134     public void testFailed(TestDescription test, String trace) {
135         if (mSkip) {
136             return;
137         }
138         CLog.logAndDisplay(
139                 LogLevel.INFO,
140                 "[%d/%d] %s fail:\n%s",
141                 mTestsRan,
142                 getExpectedTests(),
143                 test.toString(),
144                 trace);
145         mTestFailed = true;
146         super.testFailed(test, trace);
147     }
148 
149     /** Whether or not to mark all the test cases skipped. */
setMarkTestsSkipped(boolean skip)150     public void setMarkTestsSkipped(boolean skip) {
151         mSkip = skip;
152     }
153 
154     /** {@inheritDoc} */
155     @Override
testLog(String dataName, LogDataType dataType, InputStreamSource dataStream)156     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
157         if (mMainListener instanceof LogSaverResultForwarder) {
158             // If the listener is a log saver, we should simply forward the testLog not save again.
159             ((LogSaverResultForwarder) mMainListener)
160                     .testLogForward(dataName, dataType, dataStream);
161         } else {
162             super.testLog(dataName, dataType, dataStream);
163         }
164     }
165 
166     /** {@inheritDoc} */
167     @Override
testLogSaved( String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile)168     public void testLogSaved(
169             String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile) {
170         // Forward to CollectingTestListener to store the logs
171         super.testLogSaved(dataName, dataType, dataStream, logFile);
172         // Forward to the main listener so logs are properly reported to the end result_reporters.
173         if (mMainListener instanceof ILogSaverListener) {
174             ((ILogSaverListener) mMainListener)
175                     .testLogSaved(dataName, dataType, dataStream, logFile);
176         }
177     }
178 
179     /** {@inheritDoc} */
180     @Override
logAssociation(String dataName, LogFile logFile)181     public void logAssociation(String dataName, LogFile logFile) {
182         if (mRunInProgress) {
183             super.logAssociation(dataName, logFile);
184         } else {
185             // If no runs are in progress, any logs is reported at the module level.
186             if (mMainListener instanceof ILogSaverListener) {
187                 ((ILogSaverListener) mMainListener).logAssociation(dataName, logFile);
188             }
189         }
190     }
191 
192     /**
193      * Check if any runs in the given attempt have incompleted (aka "run failure").
194      *
195      * @param attemptNumber indicates which attempt should the test runs come from.
196      * @return true if any of the runs in the given attempt has crashed.
197      */
hasRunCrashedAtAttempt(int attemptNumber)198     public boolean hasRunCrashedAtAttempt(int attemptNumber) {
199         for (String runName : getTestRunNames()) {
200             TestRunResult run = getTestRunAtAttempt(runName, attemptNumber);
201             if (run != null && run.isRunFailure()) {
202                 return true;
203             }
204         }
205         return false;
206     }
207 }
208