1 /* 2 * Copyright (C) 2018 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.tradefed.device.metric; 18 19 import com.android.annotations.VisibleForTesting; 20 import com.android.compatibility.common.tradefed.build.VtsCompatibilityInvocationHelper; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.OptionClass; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.device.ITestDevice; 25 import com.android.tradefed.log.LogUtil.CLog; 26 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 27 import com.android.tradefed.targetprep.VtsCoveragePreparer; 28 import com.android.tradefed.util.CommandResult; 29 import com.android.tradefed.util.CommandStatus; 30 import com.android.tradefed.util.RunInterruptedException; 31 import com.android.tradefed.util.VtsPythonRunnerHelper; 32 33 import java.io.File; 34 import java.io.FileNotFoundException; 35 import java.util.Map; 36 /** 37 * A {@link IMetricCollector} that enables vts coverage measurement during a 38 * test and generates the coverage report after the test run. 39 */ 40 @OptionClass(alias = "vts-coverage-collector") 41 public class VtsCoverageCollector extends BaseDeviceMetricCollector { 42 static final long BASE_TIMEOUT = 1000 * 60 * 20; // timeout for fetching artifacts 43 44 private VtsPythonRunnerHelper mPythonRunnerHelper = null; 45 @Override onTestRunStart(DeviceMetricData testData)46 public void onTestRunStart(DeviceMetricData testData) { 47 for (ITestDevice device : getDevices()) { 48 try { 49 device.executeShellCommand("rm -rf /data/misc/trace/*"); 50 } catch (DeviceNotAvailableException e) { 51 CLog.e("Failed to cleanup existing traces: " + e.toString()); 52 } 53 } 54 } 55 56 @Override onTestRunEnd(DeviceMetricData testData, final Map<String, Metric> currentTestCaseMetrics)57 public void onTestRunEnd(DeviceMetricData testData, 58 final Map<String, Metric> currentTestCaseMetrics) throws RunInterruptedException { 59 String moduleName = getRunName().replace(' ', '_'); 60 CLog.i("Test module name: " + moduleName); 61 IBuildInfo buildInfo = getBuildInfos().get(0); 62 if (buildInfo == null) { 63 CLog.e("Could not get build Info."); 64 return; 65 } 66 if (mPythonRunnerHelper == null) { 67 File workingDir = null; 68 VtsCompatibilityInvocationHelper invocationHelper = createInvocationHelper(); 69 try { 70 workingDir = invocationHelper.getTestsDir(); 71 } catch (FileNotFoundException e) { 72 CLog.e("VtsCompatibilityInvocationHelper cannot find test case directory. " 73 + "Command working directory not set."); 74 } 75 mPythonRunnerHelper = new VtsPythonRunnerHelper(buildInfo, workingDir); 76 } 77 for (ITestDevice device : getDevices()) { 78 String serial = device.getSerialNumber(); 79 String gcovDirPath = getGcoveResrouceDir(buildInfo, device); 80 if (gcovDirPath == null) { 81 CLog.e("Could not get gcov resource dir path."); 82 return; 83 } 84 String coverage_report_dir = buildInfo.getBuildAttributes().get("coverage_report_path"); 85 if (coverage_report_dir == null) { 86 CLog.e("Must specify the directory to store the coverage report."); 87 return; 88 } 89 File local_coverage_report_dir = new File(coverage_report_dir, moduleName); 90 91 String cmdString = "python" 92 + " -m vts.utils.python.coverage.coverage_utils get_coverage --serial " + serial 93 + " --gcov_rescource_path " + gcovDirPath + " --report_path " 94 + local_coverage_report_dir.getAbsolutePath() + " --report_prefix " 95 + moduleName; 96 String[] cmd = cmdString.split("\\s+"); 97 CommandResult commandResult = new CommandResult(); 98 String interruptMessage = 99 mPythonRunnerHelper.runPythonRunner(cmd, commandResult, BASE_TIMEOUT); 100 if (commandResult == null || commandResult.getStatus() != CommandStatus.SUCCESS) { 101 CLog.e("Could not get coverage data."); 102 } 103 if (interruptMessage != null) { 104 throw new RunInterruptedException(interruptMessage); 105 } 106 } 107 } 108 109 @VisibleForTesting getGcoveResrouceDir(IBuildInfo buildInfo, ITestDevice device)110 String getGcoveResrouceDir(IBuildInfo buildInfo, ITestDevice device) { 111 File gcovDir = buildInfo.getFile(VtsCoveragePreparer.getGcovResourceDirKey(device)); 112 if (gcovDir != null) { 113 return gcovDir.getAbsolutePath(); 114 } 115 return null; 116 } 117 118 @VisibleForTesting setPythonRunnerHelper(VtsPythonRunnerHelper pythonRunnerHelper)119 void setPythonRunnerHelper(VtsPythonRunnerHelper pythonRunnerHelper) { 120 mPythonRunnerHelper = pythonRunnerHelper; 121 } 122 123 /** 124 * Creates a {@link VtsCompatibilityInvocationHelper} to get the working directory. 125 */ 126 @VisibleForTesting createInvocationHelper()127 protected VtsCompatibilityInvocationHelper createInvocationHelper() { 128 return new VtsCompatibilityInvocationHelper(); 129 } 130 } 131