1 /*
2  * Copyright (C) 2014 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.cts.tradefed.result;
18 
19 import com.android.compatibility.common.util.AbiUtils;
20 import com.android.cts.tradefed.device.DeviceInfoCollector;
21 import com.android.ddmlib.Log;
22 import com.android.ddmlib.Log.LogLevel;
23 import com.android.ddmlib.testrunner.TestIdentifier;
24 import com.android.tradefed.build.IBuildInfo;
25 import com.android.tradefed.config.Option;
26 import com.android.tradefed.config.OptionCopier;
27 import com.android.tradefed.log.LogUtil.CLog;
28 import com.android.tradefed.result.IShardableListener;
29 import com.android.tradefed.result.StubTestInvocationListener;
30 
31 import java.util.Map;
32 
33 /**
34  * Dumps tests in progress to stdout
35  */
36 public class CtsTestLogReporter extends StubTestInvocationListener implements IShardableListener {
37 
38     private static final String DEVICE_INFO_ERROR = "DEVICE_INFO_ERROR_";
39 
40     @Option(name = "quiet-output", description = "Mute display of test results.")
41     private boolean mQuietOutput = false;
42 
43     protected IBuildInfo mBuildInfo;
44     private String mDeviceSerial;
45     private TestResults mResults = new TestResults();
46     private TestPackageResult mCurrentPkgResult = null;
47     private boolean mIsDeviceInfoRun = false;
48     private boolean mIsExtendedDeviceInfoRun = false;
49 
50     @Override
invocationStarted(IBuildInfo buildInfo)51     public void invocationStarted(IBuildInfo buildInfo) {
52         mDeviceSerial = buildInfo.getDeviceSerial() == null ? "unknown_device" : buildInfo.getDeviceSerial();
53     }
54 
55     /**
56      * Reports the start of a test run.
57      *
58      * @param id the unique identifier of this test run, generated by
59      * {@link AbiUtils#createId(String, String)}.
60      * @param numTests total number of tests in test run
61      */
62     @Override
testRunStarted(String id, int numTests)63     public void testRunStarted(String id, int numTests) {
64         if (mCurrentPkgResult != null && !id.equals(mCurrentPkgResult.getId())) {
65             // display results from previous run
66             logCompleteRun(mCurrentPkgResult);
67         }
68         mIsDeviceInfoRun = DeviceInfoCollector.IDS.contains(id);
69         mIsExtendedDeviceInfoRun = DeviceInfoCollector.EXTENDED_IDS.contains(id);
70         if (mIsDeviceInfoRun) {
71             logResult("Collecting device info");
72         } else if (mIsExtendedDeviceInfoRun) {
73             logResult("Collecting extended device info");
74         } else  {
75             if (mCurrentPkgResult == null || !id.equals(mCurrentPkgResult.getId())) {
76                 logResult("-----------------------------------------");
77                 logResult("Test package %s started", id);
78                 logResult("-----------------------------------------");
79             }
80             mCurrentPkgResult = mResults.getOrCreatePackage(id);
81         }
82     }
83 
84     /**
85      * {@inheritDoc}
86      */
87     @Override
testStarted(TestIdentifier test)88     public void testStarted(TestIdentifier test) {
89         if (mIsExtendedDeviceInfoRun) {
90             return;
91         }
92         mCurrentPkgResult.insertTest(test);
93     }
94 
95     /**
96      * {@inheritDoc}
97      */
98     @Override
testFailed(TestIdentifier test, String trace)99     public void testFailed(TestIdentifier test, String trace) {
100         if (mIsExtendedDeviceInfoRun) {
101             return;
102         }
103         mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
testAssumptionFailure(TestIdentifier test, String trace)110     public void testAssumptionFailure(TestIdentifier test, String trace) {
111         if (mIsExtendedDeviceInfoRun) {
112             return;
113         }
114         // TODO: do something different here?
115         mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
116     }
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
testEnded(TestIdentifier test, Map<String, String> testMetrics)122     public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
123         if (mIsExtendedDeviceInfoRun) {
124             for (Map.Entry<String, String> metricsEntry : testMetrics.entrySet()) {
125                 String key = metricsEntry.getKey();
126                 String value = metricsEntry.getValue();
127                 if (key.startsWith(DEVICE_INFO_ERROR)) {
128                     throw new RuntimeException(String.format(
129                         "Error collecting extended device info: %s=%s", key, value));
130                 }
131             }
132             return;
133         }
134         mCurrentPkgResult.reportTestEnded(test, testMetrics);
135         Test result = mCurrentPkgResult.findTest(test);
136         String stack = result.getStackTrace() == null ? "" : "\n" + result.getStackTrace();
137         logResult("%s#%s %s %s", test.getClassName(), test.getTestName(), result.getResult(),
138                 stack);
139     }
140 
141     /**
142      * {@inheritDoc}
143      */
144     @Override
invocationEnded(long elapsedTime)145     public void invocationEnded(long elapsedTime) {
146         if (mIsExtendedDeviceInfoRun) {
147             return;
148         }
149         // display the results of the last completed run
150         if (mCurrentPkgResult != null) {
151             logCompleteRun(mCurrentPkgResult);
152         }
153     }
154 
logResult(String format, Object... args)155     private void logResult(String format, Object... args) {
156         if (mQuietOutput) {
157             CLog.i(format, args);
158         } else {
159             Log.logAndDisplay(LogLevel.INFO, mDeviceSerial, String.format(format, args));
160         }
161     }
162 
logCompleteRun(TestPackageResult pkgResult)163     private void logCompleteRun(TestPackageResult pkgResult) {
164         String appPackageName = pkgResult.getAppPackageName();
165         if (appPackageName.equals(DeviceInfoCollector.APP_PACKAGE_NAME)) {
166             logResult("Device info collection complete");
167             return;
168         } else if (appPackageName.equals(DeviceInfoCollector.EXTENDED_APP_PACKAGE_NAME)) {
169             logResult("Extended device info collection complete");
170             return;
171         }
172         logResult("%s package complete: Passed %d, Failed %d, Not Executed %d",
173                 pkgResult.getId(), pkgResult.countTests(CtsTestStatus.PASS),
174                 pkgResult.countTests(CtsTestStatus.FAIL),
175                 pkgResult.countTests(CtsTestStatus.NOT_EXECUTED));
176     }
177 
178     @Override
clone()179     public IShardableListener clone() {
180         CtsTestLogReporter clone = new CtsTestLogReporter();
181         OptionCopier.copyOptionsNoThrow(this, clone);
182         return clone;
183     }
184 }
185