• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.result;
17 
18 import com.android.tradefed.config.IConfiguration;
19 import com.android.tradefed.config.IConfigurationReceiver;
20 import com.android.tradefed.invoker.IInvocationContext;
21 import com.android.tradefed.log.ITestLogger;
22 import com.android.tradefed.log.LogUtil.CLog;
23 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
24 import com.android.tradefed.result.retry.ISupportGranularResults;
25 import com.android.tradefed.testtype.suite.ModuleDefinition;
26 import com.android.tradefed.util.FileUtil;
27 
28 import com.google.common.annotations.VisibleForTesting;
29 import com.google.common.base.Strings;
30 
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.HashMap;
34 import java.util.Map.Entry;
35 
36 /** Report in a file possible filters to exclude passed test. */
37 public class ReportPassedTests extends CollectingTestListener
38         implements IConfigurationReceiver, ISupportGranularResults {
39 
40     private static final int MAX_TEST_CASES_BATCH = 500;
41     private static final String PASSED_TEST_LOG = "passed_tests";
42     private boolean mInvocationFailed = false;
43     private ITestLogger mLogger;
44     private boolean mModuleInProgress;
45     private IInvocationContext mContextForEmptyModule;
46     private Integer mShardIndex;
47     private File mPassedTests;
48 
setLogger(ITestLogger logger)49     public void setLogger(ITestLogger logger) {
50         mLogger = logger;
51     }
52 
53     @Override
supportGranularResults()54     public boolean supportGranularResults() {
55         return false;
56     }
57 
58     @Override
invocationStarted(IInvocationContext context)59     public void invocationStarted(IInvocationContext context) {
60         super.invocationStarted(context);
61         try {
62             mPassedTests = FileUtil.createTempFile(PASSED_TEST_LOG, ".txt");
63         } catch (IOException e) {
64             CLog.e(e);
65         }
66     }
67 
68     @Override
setConfiguration(IConfiguration configuration)69     public void setConfiguration(IConfiguration configuration) {
70         if (configuration.getCommandOptions().getShardIndex() != null) {
71             mShardIndex = configuration.getCommandOptions().getShardIndex();
72         }
73     }
74 
75     @Override
testModuleStarted(IInvocationContext moduleContext)76     public void testModuleStarted(IInvocationContext moduleContext) {
77         super.testModuleStarted(moduleContext);
78         mModuleInProgress = true;
79         mContextForEmptyModule = moduleContext;
80     }
81 
82     @Override
testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics)83     public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) {
84         mContextForEmptyModule = null;
85         super.testRunEnded(elapsedTime, runMetrics);
86         if (!mModuleInProgress) {
87             gatherPassedTests(
88                     getCurrentRunResults(), getBaseName(getCurrentRunResults()), mInvocationFailed);
89             clearResultsForName(getCurrentRunResults().getName());
90             // Clear the failure for aggregation
91             getCurrentRunResults().resetRunFailure();
92         }
93     }
94 
95     @Override
testModuleEnded()96     public void testModuleEnded() {
97         if (mContextForEmptyModule != null) {
98             // If the module was empty
99             String moduleId = mContextForEmptyModule.getAttributes()
100                     .getUniqueMap().get(ModuleDefinition.MODULE_ID);
101             if (moduleId != null) {
102                 super.testRunStarted(moduleId, 0);
103                 super.testRunEnded(0L, new HashMap<String, Metric>());
104             }
105             mContextForEmptyModule = null;
106         }
107         super.testModuleEnded();
108         gatherPassedTests(
109                 getCurrentRunResults(), getBaseName(getCurrentRunResults()), mInvocationFailed);
110         clearResultsForName(getCurrentRunResults().getName());
111         // Clear the failure for aggregation
112         getCurrentRunResults().resetRunFailure();
113         mModuleInProgress = false;
114     }
115 
116     @Override
invocationFailed(FailureDescription failure)117     public void invocationFailed(FailureDescription failure) {
118         super.invocationFailed(failure);
119         mInvocationFailed = true;
120     }
121 
122     @Override
invocationEnded(long elapsedTime)123     public void invocationEnded(long elapsedTime) {
124         try {
125             super.invocationEnded(elapsedTime);
126             createPassedLog();
127         } finally {
128             FileUtil.deleteFile(mPassedTests);
129         }
130     }
131 
createPassedLog()132     private void createPassedLog() {
133         if (mLogger == null || mPassedTests == null) {
134             return;
135         }
136         for (TestRunResult result : getMergedTestRunResults()) {
137             gatherPassedTests(result, getBaseName(result), false);
138         }
139         if (mPassedTests.length() == 0) {
140             CLog.d("No new filter for passed_test");
141             return;
142         }
143         testLog(mPassedTests);
144     }
145 
146     @VisibleForTesting
testLog(File toBeLogged)147     void testLog(File toBeLogged) {
148         try (FileInputStreamSource source = new FileInputStreamSource(toBeLogged)) {
149             mLogger.testLog(PASSED_TEST_LOG, LogDataType.PASSED_TESTS, source);
150         }
151     }
152 
getBaseName(TestRunResult runResult)153     private String getBaseName(TestRunResult runResult) {
154         IInvocationContext context = getModuleContextForRunResult(runResult.getName());
155         // If it's a test module
156         if (context != null) {
157             return context.getAttributes().getUniqueMap().get(ModuleDefinition.MODULE_ID);
158         } else {
159             return runResult.getName();
160         }
161     }
162 
gatherPassedTests( TestRunResult runResult, String baseName, boolean invocationFailure)163     private void gatherPassedTests(
164             TestRunResult runResult, String baseName, boolean invocationFailure) {
165         if (mShardIndex != null) {
166             baseName = "shard_" + mShardIndex + " " + baseName;
167         }
168         StringBuilder sb = new StringBuilder();
169         if (!runResult.hasFailedTests() && !runResult.isRunFailure() && !invocationFailure) {
170             sb.append(baseName);
171             sb.append("\n");
172             writeToFile(sb.toString());
173             return;
174         }
175         int i = 0;
176         for (Entry<TestDescription, TestResult> res : runResult.getTestResults().entrySet()) {
177             if (TestStatus.FAILURE.equals(res.getValue().getResultStatus())) {
178                 continue;
179             }
180             // Consider SKIPPED as failure so it can be retried
181             if (TestStatus.SKIPPED.equals(res.getValue().getResultStatus())) {
182                 continue;
183             }
184             sb.append(baseName + " " + res.getKey().toString());
185             sb.append("\n");
186             i++;
187             if (i > MAX_TEST_CASES_BATCH) {
188                 writeToFile(sb.toString());
189                 sb = new StringBuilder();
190                 i = 0;
191             }
192         }
193         writeToFile(sb.toString());
194     }
195 
writeToFile(String toWrite)196     private void writeToFile(String toWrite) {
197         if (Strings.isNullOrEmpty(toWrite)) {
198             return;
199         }
200         try {
201             FileUtil.writeToFile(toWrite, mPassedTests, true);
202         } catch (IOException e) {
203             CLog.e(e);
204         }
205     }
206 }
207