1 /* 2 * Copyright (C) 2016 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.compatibility.common.tradefed.result; 18 19 import com.android.ddmlib.Log; 20 import com.android.ddmlib.Log.LogLevel; 21 import com.android.ddmlib.testrunner.TestIdentifier; 22 import com.android.tradefed.build.IBuildInfo; 23 import com.android.tradefed.config.Option; 24 import com.android.tradefed.config.OptionClass; 25 import com.android.tradefed.config.OptionCopier; 26 import com.android.tradefed.log.LogUtil.CLog; 27 import com.android.tradefed.result.IShardableListener; 28 import com.android.tradefed.result.StubTestInvocationListener; 29 import com.android.tradefed.util.TimeUtil; 30 31 import java.util.Map; 32 33 /** 34 * Write test progress to the test console. 35 */ 36 public class ConsoleReporter extends StubTestInvocationListener implements IShardableListener { 37 38 private static final String UNKNOWN_DEVICE = "unknown_device"; 39 40 @Option(name = "quiet-output", description = "Mute display of test results.") 41 private boolean mQuietOutput = false; 42 43 private String mDeviceSerial = UNKNOWN_DEVICE; 44 private boolean mTestFailed; 45 private String mModuleId; 46 private int mCurrentTestNum; 47 private int mTotalTestsInModule; 48 private int mPassedTests; 49 private int mFailedTests; 50 51 /** 52 * {@inheritDoc} 53 */ 54 @Override invocationStarted(IBuildInfo buildInfo)55 public void invocationStarted(IBuildInfo buildInfo) { 56 if (buildInfo == null) { 57 CLog.w("buildInfo should not be null"); 58 return; 59 } 60 // Escape any "%" signs in the device serial. 61 mDeviceSerial = buildInfo.getDeviceSerial().replace("%", "%%"); 62 } 63 64 /** 65 * {@inheritDoc} 66 */ 67 @Override testRunStarted(String id, int numTests)68 public void testRunStarted(String id, int numTests) { 69 if (mModuleId == null || !mModuleId.equals(id)) { 70 mModuleId = id; 71 mTotalTestsInModule = numTests; 72 // Reset counters 73 mCurrentTestNum = 0; 74 mPassedTests = 0; 75 mFailedTests = 0; 76 mTestFailed = false; 77 logMessage("Starting %s with %d test%s", 78 id, mTotalTestsInModule, (mTotalTestsInModule > 1) ? "s" : ""); 79 } else { 80 mTotalTestsInModule += numTests; 81 logMessage("Continuing %s with %d test%s", 82 id, mTotalTestsInModule, (mTotalTestsInModule > 1) ? "s" : ""); 83 } 84 } 85 86 /** 87 * {@inheritDoc} 88 */ 89 @Override testStarted(TestIdentifier test)90 public void testStarted(TestIdentifier test) { 91 mTestFailed = false; 92 mCurrentTestNum++; 93 } 94 95 /** 96 * {@inheritDoc} 97 */ 98 @Override testFailed(TestIdentifier test, String trace)99 public void testFailed(TestIdentifier test, String trace) { 100 logProgress("%s fail: %s", test, trace); 101 mTestFailed = true; 102 mFailedTests++; 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override testIgnored(TestIdentifier test)109 public void testIgnored(TestIdentifier test) { 110 mCurrentTestNum--; 111 logProgress("%s ignore", test); 112 } 113 114 /** 115 * {@inheritDoc} 116 */ 117 @Override testAssumptionFailure(TestIdentifier test, String trace)118 public void testAssumptionFailure(TestIdentifier test, String trace) { 119 logProgress("%s failed assumption: %s", test, trace); 120 } 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override testEnded(TestIdentifier test, Map<String, String> testMetrics)126 public void testEnded(TestIdentifier test, Map<String, String> testMetrics) { 127 if (!mTestFailed) { 128 logProgress("%s pass", test); 129 mPassedTests++; 130 } 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 @Override testRunFailed(String errorMessage)137 public void testRunFailed(String errorMessage) { 138 logMessage(errorMessage); 139 } 140 141 142 /** 143 * {@inheritDoc} 144 */ 145 @Override testRunEnded(long elapsedTime, Map<String, String> metrics)146 public void testRunEnded(long elapsedTime, Map<String, String> metrics) { 147 int notExecuted = mTotalTestsInModule - mCurrentTestNum; 148 String status = notExecuted > 0 ? "failed" : "completed"; 149 logMessage("%s %s in %s. %d passed, %d failed, %d not executed", 150 mModuleId, 151 status, 152 TimeUtil.formatElapsedTime(elapsedTime), 153 mPassedTests, 154 mFailedTests, 155 notExecuted); 156 } 157 158 /** 159 * {@inheritDoc} 160 */ 161 @Override testRunStopped(long elapsedTime)162 public void testRunStopped(long elapsedTime) { 163 logMessage("%s stopped (%s)", mModuleId, TimeUtil.formatElapsedTime(elapsedTime)); 164 } 165 166 /** 167 * Print out message with test execution status. 168 */ logProgress(String format, Object... args)169 private void logProgress(String format, Object... args) { 170 format = String.format("[%s %s %s] %s", progress(), mModuleId, mDeviceSerial, format); 171 log(format, args); 172 } 173 174 /** 175 * Print out message to the console 176 */ logMessage(String format, Object... args)177 private void logMessage(String format, Object... args) { 178 format = String.format("[%s] %s", mDeviceSerial, format); 179 log(format, args); 180 } 181 182 /** 183 * Print out to the console or log silently when mQuietOutput is true. 184 */ log(String format, Object... args)185 private void log(String format, Object... args) { 186 if (mQuietOutput) { 187 CLog.i(format, args); 188 } else { 189 CLog.logAndDisplay(LogLevel.INFO, format, args); 190 } 191 } 192 193 /** 194 * {@inheritDoc} 195 */ 196 @Override clone()197 public IShardableListener clone() { 198 ConsoleReporter clone = new ConsoleReporter(); 199 OptionCopier.copyOptionsNoThrow(this, clone); 200 return clone; 201 } 202 203 /** 204 * Return a string containing the percentage complete of module test execution. 205 */ progress()206 private String progress() { 207 return String.format("%d/%d", mCurrentTestNum, mTotalTestsInModule); 208 } 209 getDeviceSerial()210 String getDeviceSerial() { 211 return mDeviceSerial; 212 } 213 getTestFailed()214 boolean getTestFailed() { 215 return mTestFailed; 216 } 217 getModuleId()218 String getModuleId() { 219 return mModuleId; 220 } 221 getCurrentTestNum()222 int getCurrentTestNum() { 223 return mCurrentTestNum; 224 } 225 getTotalTestsInModule()226 int getTotalTestsInModule() { 227 return mTotalTestsInModule; 228 } 229 getPassedTests()230 int getPassedTests() { 231 return mPassedTests; 232 } 233 getFailedTests()234 int getFailedTests() { 235 return mFailedTests; 236 } 237 } 238