• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.media.tests;
18 
19 import com.android.tradefed.log.LogUtil;
20 import com.android.tradefed.metrics.proto.MetricMeasurement;
21 import com.android.tradefed.result.CollectingTestListener;
22 import com.android.tradefed.result.FailureDescription;
23 import com.android.tradefed.result.FileInputStreamSource;
24 import com.android.tradefed.result.ITestInvocationListener;
25 import com.android.tradefed.result.InputStreamSource;
26 import com.android.tradefed.result.LogDataType;
27 import com.android.tradefed.result.TestDescription;
28 import com.android.tradefed.util.StreamUtil;
29 import com.android.tradefed.util.proto.TfMetricProtoUtil;
30 
31 import java.io.File;
32 import java.util.HashMap;
33 import java.util.Map;
34 
35 public class CameraTestMetricsCollectionListener {
36 
37 protected static abstract class AbstractCameraTestMetricsCollectionListener extends CollectingTestListener {
38     private ITestInvocationListener mListener;
39     private Map<String, String> mMetrics = new HashMap<>();
40     private Map<String, String> mFatalErrors = new HashMap<>();
41     private CameraTestBase mCameraTestBase;
42 
43     private static final String INCOMPLETE_TEST_ERR_MSG_PREFIX =
44             "Test failed to run to completion. Reason: 'Instrumentation run failed";
45 
AbstractCameraTestMetricsCollectionListener(ITestInvocationListener listener)46     public AbstractCameraTestMetricsCollectionListener(ITestInvocationListener listener) {
47         mListener = listener;
48         mCameraTestBase = new CameraTestBase();
49     }
50     /**
51      * Report the end of an individual camera test and delegate handling the collected metrics to
52      * subclasses. Do not override testEnded to manipulate the test metrics after each test.
53      * Instead, use handleMetricsOnTestEnded.
54      *
55      * @param test identifies the test
56      * @param testMetrics a {@link Map} of the metrics emitted
57      */
58     @Override
testEnded( TestDescription test, long endTime, HashMap<String, MetricMeasurement.Metric> testMetrics)59     public void testEnded(
60             TestDescription test,
61             long endTime,
62             HashMap<String, MetricMeasurement.Metric> testMetrics) {
63         super.testEnded(test, endTime, testMetrics);
64         handleMetricsOnTestEnded(test, TfMetricProtoUtil.compatibleConvert(testMetrics));
65         stopDumping(test);
66         mListener.testEnded(test, endTime, testMetrics);
67     }
68 
69     @Override
testStarted(TestDescription test, long startTime)70     public void testStarted(TestDescription test, long startTime) {
71         super.testStarted(test, startTime);
72         startDumping(test);
73         mListener.testStarted(test, startTime);
74     }
75 
76     @Override
testFailed(TestDescription test, String trace)77     public void testFailed(TestDescription test, String trace) {
78         super.testFailed(test, trace);
79         // If the test failed to run to complete, this is an exceptional case.
80         // Let this test run fail so that it can rerun.
81         if (trace.startsWith(INCOMPLETE_TEST_ERR_MSG_PREFIX)) {
82             mFatalErrors.put(test.getTestName(), trace);
83             LogUtil.CLog.d("Test (%s) failed due to fatal error : %s", test.getTestName(), trace);
84         }
85         mListener.testFailed(test, trace);
86     }
87 
88     @Override
testRunFailed(String errorMessage)89     public void testRunFailed(String errorMessage) {
90         super.testRunFailed(errorMessage);
91         mFatalErrors.put(mCameraTestBase.getRuKey(), errorMessage);
92     }
93 
94         @Override
testRunFailed(FailureDescription failure)95         public void testRunFailed(FailureDescription failure) {
96             super.testRunFailed(failure);
97             mFatalErrors.put(mCameraTestBase.getRuKey(), failure.getErrorMessage());
98         }
99 
100     @Override
testRunEnded( long elapsedTime, HashMap<String, MetricMeasurement.Metric> runMetrics)101     public void testRunEnded(
102             long elapsedTime, HashMap<String, MetricMeasurement.Metric> runMetrics) {
103         super.testRunEnded(elapsedTime, runMetrics);
104         handleTestRunEnded(mListener, elapsedTime, TfMetricProtoUtil.compatibleConvert(runMetrics));
105         // never be called since handleTestRunEnded will handle it if needed.
106         // mListener.testRunEnded(elapsedTime, runMetrics);
107     }
108 
109     @Override
testRunStarted(String runName, int testCount)110     public void testRunStarted(String runName, int testCount) {
111         super.testRunStarted(runName, testCount);
112         mListener.testRunStarted(runName, testCount);
113     }
114 
115         @Override
testRunStarted(String runName, int testCount, int attemptNumber)116         public void testRunStarted(String runName, int testCount, int attemptNumber) {
117             super.testRunStarted(runName, testCount, attemptNumber);
118             mListener.testRunStarted(runName, testCount, attemptNumber);
119         }
120 
121         @Override
testRunStarted( String runName, int testCount, int attemptNumber, long startTime)122         public void testRunStarted(
123                 String runName, int testCount, int attemptNumber, long startTime) {
124             super.testRunStarted(runName, testCount, attemptNumber, startTime);
125             mListener.testRunStarted(runName, testCount, attemptNumber, startTime);
126         }
127 
128     @Override
testRunStopped(long elapsedTime)129     public void testRunStopped(long elapsedTime) {
130         super.testRunStopped(elapsedTime);
131         mListener.testRunStopped(elapsedTime);
132     }
133 
134     @Override
testLog(String dataName, LogDataType dataType, InputStreamSource dataStream)135     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
136         super.testLog(dataName, dataType, dataStream);
137         mListener.testLog(dataName, dataType, dataStream);
138     }
139 
startDumping(TestDescription test)140     protected void startDumping(TestDescription test) {
141         if (mCameraTestBase.shouldDumpMeminfo()) {
142             mCameraTestBase.mMeminfoTimer.start(test);
143         }
144         if (mCameraTestBase.shouldDumpThreadCount()) {
145             mCameraTestBase.mThreadTrackerTimer.start(test);
146         }
147     }
148 
stopDumping(TestDescription test)149     protected void stopDumping(TestDescription test) {
150         InputStreamSource outputSource = null;
151         File outputFile = null;
152         if (mCameraTestBase.shouldDumpMeminfo()) {
153             mCameraTestBase.mMeminfoTimer.stop();
154             // Grab a snapshot of meminfo file and post it to dashboard.
155             try {
156                 outputFile = mCameraTestBase.mMeminfoTimer.getOutputFile();
157                 outputSource = new FileInputStreamSource(outputFile, true /* delete */);
158                 String logName = String.format("meminfo_%s", test.getTestName());
159                 mListener.testLog(logName, LogDataType.TEXT, outputSource);
160             } finally {
161                 StreamUtil.cancel(outputSource);
162             }
163         }
164         if (mCameraTestBase.shouldDumpThreadCount()) {
165             mCameraTestBase.mThreadTrackerTimer.stop();
166             try {
167                 outputFile = mCameraTestBase.mThreadTrackerTimer.getOutputFile();
168                 outputSource = new FileInputStreamSource(outputFile, true /* delete */);
169                 String logName = String.format("ps_%s", test.getTestName());
170                 mListener.testLog(logName, LogDataType.TEXT, outputSource);
171             } finally {
172                 StreamUtil.cancel(outputSource);
173             }
174         }
175     }
176 
getAggregatedMetrics()177     public Map<String, String> getAggregatedMetrics() {
178         return mMetrics;
179     }
180 
getListeners()181     public ITestInvocationListener getListeners() {
182         return mListener;
183     }
184 
185     /**
186      * Determine that the test run failed with fatal errors.
187      *
188      * @return True if test run has a failure due to fatal error.
189      */
hasTestRunFatalError()190     public boolean hasTestRunFatalError() {
191         return (getNumTotalTests() > 0 && mFatalErrors.size() > 0);
192     }
193 
getFatalErrors()194     public Map<String, String> getFatalErrors() {
195         return mFatalErrors;
196     }
197 
getErrorMessage()198     public String getErrorMessage() {
199         StringBuilder sb = new StringBuilder();
200         for (Map.Entry<String, String> error : mFatalErrors.entrySet()) {
201             sb.append(error.getKey());
202             sb.append(" : ");
203             sb.append(error.getValue());
204             sb.append("\n");
205         }
206         return sb.toString();
207     }
208 
handleMetricsOnTestEnded(TestDescription test, Map<String, String> testMetrics)209     abstract void handleMetricsOnTestEnded(TestDescription test, Map<String, String> testMetrics);
210 
handleTestRunEnded( ITestInvocationListener listener, long elapsedTime, Map<String, String> runMetrics)211     abstract void handleTestRunEnded(
212             ITestInvocationListener listener, long elapsedTime, Map<String, String> runMetrics);
213 }
214 
215 protected static class DefaultCollectingListener extends AbstractCameraTestMetricsCollectionListener {
216     private CameraTestBase mCameraTestBase;
217 
DefaultCollectingListener(ITestInvocationListener listener)218     public DefaultCollectingListener(ITestInvocationListener listener) {
219         super(listener);
220         mCameraTestBase = new CameraTestBase();
221     }
222 
223     @Override
handleMetricsOnTestEnded(TestDescription test, Map<String, String> testMetrics)224     public void handleMetricsOnTestEnded(TestDescription test, Map<String, String> testMetrics) {
225         if (testMetrics == null) {
226             return; // No-op if there is nothing to post.
227         }
228         getAggregatedMetrics().putAll(testMetrics);
229     }
230 
231     @Override
handleTestRunEnded( ITestInvocationListener listener, long elapsedTime, Map<String, String> runMetrics)232     public void handleTestRunEnded(
233             ITestInvocationListener listener, long elapsedTime, Map<String, String> runMetrics) {
234         // Post aggregated metrics at the end of test run.
235         listener.testRunEnded(
236                 mCameraTestBase.getTestDurationMs(),
237                 TfMetricProtoUtil.upgradeConvert(getAggregatedMetrics()));
238     }
239  }
240 }
241