• 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 package com.android.tradefed.device.metric;
17 
18 import com.android.annotations.VisibleForTesting;
19 import com.android.tradefed.device.ILogcatReceiver;
20 import com.android.tradefed.device.ITestDevice;
21 import com.android.tradefed.device.LogcatReceiver;
22 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
23 import com.android.tradefed.result.InputStreamSource;
24 import com.android.tradefed.result.LogDataType;
25 import com.android.tradefed.result.TestDescription;
26 import com.android.tradefed.util.IRunUtil;
27 import com.android.tradefed.util.RunUtil;
28 
29 import java.util.HashMap;
30 import java.util.Map;
31 
32 /** Collector that will capture and log a logcat when a test case fails. */
33 public class LogcatOnFailureCollector extends BaseDeviceMetricCollector {
34 
35     private static final int MAX_LOGAT_SIZE_BYTES = 4 * 1024 * 1024;
36     /** Always include a bit of prior data to capture what happened before */
37     private static final int OFFSET_CORRECTION = 20000;
38 
39     private static final String NAME_FORMAT = "%s-%s-logcat-on-failure";
40 
41     private Map<ITestDevice, ILogcatReceiver> mLogcatReceivers = new HashMap<>();
42     private Map<ITestDevice, Integer> mOffset = new HashMap<>();
43 
44     @Override
onTestRunStart(DeviceMetricData runData)45     public void onTestRunStart(DeviceMetricData runData) {
46         for (ITestDevice device : getDevices()) {
47             // In case of multiple runs for the same test runner, re-init the receiver.
48             initReceiver(device);
49             // Get the current offset of the buffer to be able to query later
50             int offset = (int) mLogcatReceivers.get(device).getLogcatData().size();
51             if (offset > OFFSET_CORRECTION) {
52                 offset -= OFFSET_CORRECTION;
53             }
54             mOffset.put(device, offset);
55         }
56     }
57 
58     @Override
onTestStart(DeviceMetricData testData)59     public void onTestStart(DeviceMetricData testData) {
60         // TODO: Handle the buffer to reset it at the test start
61     }
62 
63     @Override
onTestFail(DeviceMetricData testData, TestDescription test)64     public void onTestFail(DeviceMetricData testData, TestDescription test) {
65         for (ITestDevice device : getDevices()) {
66             // Delay slightly for the error to get in the logcat
67             getRunUtil().sleep(100);
68             try (InputStreamSource logcatSource =
69                     mLogcatReceivers
70                             .get(device)
71                             .getLogcatData(MAX_LOGAT_SIZE_BYTES, mOffset.get(device))) {
72                 String name = String.format(NAME_FORMAT, test.toString(), device.getSerialNumber());
73                 super.testLog(name, LogDataType.LOGCAT, logcatSource);
74             }
75         }
76     }
77 
78     @Override
onTestRunEnd(DeviceMetricData runData, Map<String, Metric> currentRunMetrics)79     public void onTestRunEnd(DeviceMetricData runData, Map<String, Metric> currentRunMetrics) {
80         clearReceivers();
81     }
82 
83     @VisibleForTesting
createLogcatReceiver(ITestDevice device)84     ILogcatReceiver createLogcatReceiver(ITestDevice device) {
85         return new LogcatReceiver(device, "logcat", device.getOptions().getMaxLogcatDataSize(), 0);
86     }
87 
88     @VisibleForTesting
getRunUtil()89     IRunUtil getRunUtil() {
90         return RunUtil.getDefault();
91     }
92 
initReceiver(ITestDevice device)93     private void initReceiver(ITestDevice device) {
94         if (mLogcatReceivers.get(device) == null) {
95             ILogcatReceiver receiver = createLogcatReceiver(device);
96             mLogcatReceivers.put(device, receiver);
97             receiver.start();
98         }
99     }
100 
clearReceivers()101     private void clearReceivers() {
102         for (ILogcatReceiver receiver : mLogcatReceivers.values()) {
103             receiver.stop();
104             receiver.clear();
105         }
106         mLogcatReceivers.clear();
107         mOffset.clear();
108     }
109 }
110