diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2020-10-23 23:31:38 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2020-10-23 23:31:38 +0000 |
commit | 8b905ac839c6eafff5648d8a5c0a015088af7c50 (patch) | |
tree | af5dfc1ad8b04ace97adbbfb96a8380f7b942dc7 | |
parent | 27137e33cd8d6b7a1e5e7d696994506197caa3e7 (diff) | |
parent | 44f81b26ebde4c60190edfa4332b554b00cc49bd (diff) | |
download | tradefederation-8b905ac839c6eafff5648d8a5c0a015088af7c50.tar.gz |
Merge cherrypicks of [12912917, 12912975, 12912918] into mainline-releaseandroid-mainline-11.0.0_r9android-mainline-11.0.0_r3android-mainline-11.0.0_r29android11-mainline-sparse-2020-dec-release
Change-Id: I3e21a2d117cfb8c760201f50897140719365946e
15 files changed, 295 insertions, 306 deletions
diff --git a/src/com/android/tradefed/device/metric/AutoLogCollector.java b/src/com/android/tradefed/device/metric/AutoLogCollector.java index d93b37736..e15de1180 100644 --- a/src/com/android/tradefed/device/metric/AutoLogCollector.java +++ b/src/com/android/tradefed/device/metric/AutoLogCollector.java @@ -20,7 +20,6 @@ import java.lang.reflect.InvocationTargetException; /** Enumeration describing which collector can automatically be handled by the harness. */ public enum AutoLogCollector { BUGREPORTZ_ON_FAILURE(BugreportzOnFailureCollector.class), - CLANG_COVERAGE(ClangCodeCoverageCollector.class), GCOV_COVERAGE(GcovCodeCoverageCollector.class), HOSTLOG_ON_FAILURE(DebugHostLogOnFailureCollector.class), JAVA_COVERAGE(JavaCodeCoverageCollector.class), diff --git a/src/com/android/tradefed/device/metric/GcovCodeCoverageCollector.java b/src/com/android/tradefed/device/metric/GcovCodeCoverageCollector.java index 0bd59e2e8..287b47dc9 100644 --- a/src/com/android/tradefed/device/metric/GcovCodeCoverageCollector.java +++ b/src/com/android/tradefed/device/metric/GcovCodeCoverageCollector.java @@ -17,23 +17,22 @@ package com.android.tradefed.device.metric; import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.GCOV; +import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import com.android.tradefed.config.IConfiguration; import com.android.tradefed.config.IConfigurationReceiver; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; import com.android.tradefed.result.FileInputStreamSource; -import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.result.LogDataType; -import com.android.tradefed.util.AdbRootElevator; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.NativeCodeCoverageFlusher; import com.android.tradefed.util.TarUtil; import com.android.tradefed.util.ZipUtil; + import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -66,33 +65,10 @@ public final class GcovCodeCoverageCollector extends BaseDeviceMetricCollector private IConfiguration mConfiguration; @Override - public ITestInvocationListener init( - IInvocationContext context, ITestInvocationListener listener) { - super.init(context, listener); - - if (isGcovCoverageEnabled()) { - // Clear coverage measurements on the device. - try (AdbRootElevator adbRoot = new AdbRootElevator(getDevices().get(0))) { - getCoverageFlusher().resetCoverage(); - } catch (DeviceNotAvailableException e) { - throw new RuntimeException(e); - } - } - - return this; - } - - @Override public void setConfiguration(IConfiguration config) { mConfiguration = config; } - private boolean isGcovCoverageEnabled() { - return mConfiguration != null - && mConfiguration.getCoverageOptions().isCoverageEnabled() - && mConfiguration.getCoverageOptions().getCoverageToolchains().contains(GCOV); - } - private NativeCodeCoverageFlusher getCoverageFlusher() { if (mFlusher == null) { mFlusher = @@ -115,23 +91,29 @@ public final class GcovCodeCoverageCollector extends BaseDeviceMetricCollector @Override public void onTestRunEnd(DeviceMetricData runData, final Map<String, Metric> runMetrics) { - if (!isGcovCoverageEnabled()) { + System.out.println("Native:onTestRunEnd"); + if (mConfiguration == null + || !mConfiguration.getCoverageOptions().isCoverageEnabled() + || !mConfiguration.getCoverageOptions().getCoverageToolchains().contains(GCOV)) { + System.out.println("Native:configuration issue?"); return; } - if (mCollectCoverageOnTestEnd) { + if (mCollectCoverageOnTestEnd) { logCoverageMeasurements(getRunName()); - } + } } /** Pulls native coverage measurements from the device and logs them. */ public void logCoverageMeasurements(String runName) { File coverageTar = null; File coverageZip = null; - ITestDevice device = getRealDevices().get(0); + try { + ITestDevice device = getRealDevices().get(0); + + // Enable abd root on the device, otherwise the following commands will fail. + verify(device.enableAdbRoot(), "Failed to enable adb root."); - // Enable abd root on the device, otherwise the following commands will fail. - try (AdbRootElevator adbRoot = new AdbRootElevator(device)) { // Flush cross-process coverage. if (mConfiguration.getCoverageOptions().isCoverageFlushEnabled()) { getCoverageFlusher().forceCoverageFlush(); diff --git a/src/com/android/tradefed/device/metric/JavaCodeCoverageCollector.java b/src/com/android/tradefed/device/metric/JavaCodeCoverageCollector.java index 385aed772..1b071ef56 100644 --- a/src/com/android/tradefed/device/metric/JavaCodeCoverageCollector.java +++ b/src/com/android/tradefed/device/metric/JavaCodeCoverageCollector.java @@ -24,16 +24,13 @@ import com.android.tradefed.config.IConfigurationReceiver; import com.android.tradefed.config.Option; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.invoker.logger.CurrentInvocation; import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; import com.android.tradefed.result.FailureDescription; import com.android.tradefed.result.FileInputStreamSource; import com.android.tradefed.result.LogDataType; -import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.result.error.InfraErrorIdentifier; import com.android.tradefed.testtype.coverage.CoverageOptions; -import com.android.tradefed.util.AdbRootElevator; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.JavaCodeCoverageFlusher; @@ -73,22 +70,6 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector private IConfiguration mConfiguration; @Override - public ITestInvocationListener init( - IInvocationContext context, ITestInvocationListener listener) { - super.init(context, listener); - - if (isJavaCoverageEnabled()) { - try (AdbRootElevator adbRoot = new AdbRootElevator(getDevices().get(0))) { - getCoverageFlusher().resetCoverage(); - } catch (DeviceNotAvailableException e) { - throw new RuntimeException(e); - } - } - - return this; - } - - @Override public void setConfiguration(IConfiguration configuration) { mConfiguration = configuration; } @@ -115,7 +96,12 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector @Override public void onTestRunEnd(DeviceMetricData runData, final Map<String, Metric> runMetrics) { - if (!isJavaCoverageEnabled()) { + if (mConfiguration == null + || !mConfiguration.getCoverageOptions().isCoverageEnabled() + || !mConfiguration + .getCoverageOptions() + .getCoverageToolchains() + .contains(CoverageOptions.Toolchain.JACOCO)) { return; } if (MERGE_COVERAGE_MEASUREMENTS_TEST_NAME.equals(getRunName())) { @@ -152,7 +138,7 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector ImmutableList.Builder<String> devicePaths = ImmutableList.builder(); devicePaths.add(testCoveragePath); - try (AdbRootElevator adbRoot = new AdbRootElevator(device)) { + try { if (mConfiguration.getCoverageOptions().isCoverageFlushEnabled()) { getCoverageFlusher().forceCoverageFlush(); } @@ -161,7 +147,7 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector String fileList = device.executeShellCommand(FIND_COVERAGE_FILES); devicePaths.addAll(Splitter.on('\n').omitEmptyStrings().split(fileList)); - collectAndLogCoverageMeasurements(device, devicePaths.build()); + collectAndLogCoverageMeasurementsAsRoot(device, devicePaths.build()); } catch (DeviceNotAvailableException | IOException e) { throw new RuntimeException(e); @@ -175,12 +161,39 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector } } + private void collectAndLogCoverageMeasurementsAsRoot( + ITestDevice device, List<String> devicePaths) + throws IOException, DeviceNotAvailableException { + + // We enable root before pulling files off the device since the coverage file of the test + // process is written in its private directory which is otherwise inaccessible. Coverage + // files of other processes should be accessible without root. Note that we also restore + // root status to what it was after we're done to not interfere with subsequent tests that + // run on the device. + boolean wasRoot = device.isAdbRoot(); + if (!wasRoot && !device.enableAdbRoot()) { + throw new RuntimeException( + "Failed to enable root before pulling Java code coverage files off device"); + } + + try { + collectAndLogCoverageMeasurements(device, devicePaths); + } finally { + for (String devicePath : devicePaths) { + device.deleteFile(devicePath); + } + if (!wasRoot && !device.disableAdbRoot()) { + throw new RuntimeException( + "Failed to disable root after pulling Java code coverage files off device"); + } + } + } + private void collectAndLogCoverageMeasurements(ITestDevice device, List<String> devicePaths) throws IOException, DeviceNotAvailableException { for (String devicePath : devicePaths) { File coverageFile = device.pullFile(devicePath); - device.deleteFile(devicePath); verifyNotNull( coverageFile, "Failed to pull the Java code coverage file from %s", devicePath); @@ -206,13 +219,4 @@ public final class JavaCodeCoverageCollector extends BaseDeviceMetricCollector private FailureDescription createCodeCoverageFailure(String message) { return CurrentInvocation.createFailure(message, InfraErrorIdentifier.CODE_COVERAGE_ERROR); } - - private boolean isJavaCoverageEnabled() { - return mConfiguration != null - && mConfiguration.getCoverageOptions().isCoverageEnabled() - && mConfiguration - .getCoverageOptions() - .getCoverageToolchains() - .contains(CoverageOptions.Toolchain.JACOCO); - } } diff --git a/src/com/android/tradefed/device/metric/ClangCodeCoverageCollector.java b/test_framework/com/android/tradefed/testtype/ClangCodeCoverageListener.java index 9e6304ad5..b0fb295fd 100644 --- a/src/com/android/tradefed/device/metric/ClangCodeCoverageCollector.java +++ b/test_framework/com/android/tradefed/testtype/ClangCodeCoverageListener.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.tradefed.device.metric; +package com.android.tradefed.testtype; -import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.CLANG; +import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import com.android.tradefed.build.BuildRetrievalError; @@ -25,13 +25,14 @@ import com.android.tradefed.config.IConfiguration; import com.android.tradefed.config.IConfigurationReceiver; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; import com.android.tradefed.result.FileInputStreamSource; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.result.LogDataType; -import com.android.tradefed.util.AdbRootElevator; +import com.android.tradefed.result.ResultForwarder; +import com.android.tradefed.testtype.coverage.CoverageOptions; +import com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain; import com.android.tradefed.util.CommandResult; import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; @@ -47,15 +48,15 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; /** - * A {@link com.android.tradefed.device.metric.BaseDeviceMetricCollector} that will pull Clang - * coverage measurements off of the device and log them as test artifacts. + * A {@link ResultForwarder} that will pull Clang coverage measurements off of the device and log + * them as test artifacts. */ -public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector +public final class ClangCodeCoverageListener extends ResultForwarder implements IConfigurationReceiver { private static final String NATIVE_COVERAGE_DEVICE_PATH = "/data/misc/trace"; @@ -73,27 +74,21 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector private static final String DELETE_COVERAGE_FILES_COMMAND = String.format("find %s -name '*.profraw' -delete", NATIVE_COVERAGE_DEVICE_PATH); + private final ITestDevice mDevice; + private IBuildInfo mBuildInfo; private IConfiguration mConfiguration; - private IRunUtil mRunUtil = RunUtil.getDefault(); + private IRunUtil mRunUtil; private NativeCodeCoverageFlusher mFlusher; - @Override - public ITestInvocationListener init( - IInvocationContext context, ITestInvocationListener listener) { - super.init(context, listener); - - if (isClangCoverageEnabled()) { - // Clear coverage measurements on the device. - try (AdbRootElevator adbRoot = new AdbRootElevator(getDevices().get(0))) { - getCoverageFlusher().resetCoverage(); - } catch (DeviceNotAvailableException e) { - throw new RuntimeException(e); - } - } + private File mLlvmProfdataTool; + private String mCurrentRunName; - return this; + public ClangCodeCoverageListener(ITestDevice device, ITestInvocationListener... listeners) { + super(listeners); + mDevice = device; + mRunUtil = RunUtil.getDefault(); } @Override @@ -107,26 +102,42 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector } @Override - public void onTestRunEnd( - DeviceMetricData runData, final Map<String, Metric> currentRunMetrics) { - if (!isClangCoverageEnabled()) { - return; - } + public void testRunStarted(String runName, int testCount) { + mCurrentRunName = runName; + super.testRunStarted(runName, testCount); + } - ITestDevice device = getRealDevices().get(0); - try (AdbRootElevator adbRoot = new AdbRootElevator(device)) { - if (mConfiguration.getCoverageOptions().isCoverageFlushEnabled()) { - getCoverageFlusher().forceCoverageFlush(); + @Override + public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) { + CoverageOptions options = mConfiguration.getCoverageOptions(); + try { + if (options.isCoverageEnabled() + && options.getCoverageToolchains().contains(Toolchain.CLANG)) { + // Enable abd root on the device, otherwise the following commands will fail. + verify(mDevice.enableAdbRoot(), "Failed to enable adb root."); + + if (options.isCoverageFlushEnabled()) { + getCoverageFlusher().forceCoverageFlush(); + } + logCoverageMeasurement(mCurrentRunName); + + // Delete coverage files on the device. + mDevice.executeShellCommand(DELETE_COVERAGE_FILES_COMMAND); } - logCoverageMeasurement(device, getRunName()); - - // Delete coverage files on the device. - device.executeShellCommand(DELETE_COVERAGE_FILES_COMMAND); } catch (DeviceNotAvailableException | IOException e) { throw new RuntimeException(e); + } finally { + super.testRunEnded(elapsedTime, runMetrics); } } + @Override + public void invocationEnded(long elapsedTime) { + // Clean up the llvm-profdata tool. + FileUtil.recursiveDelete(mLlvmProfdataTool); + super.invocationEnded(elapsedTime); + } + /** * Logs Clang coverage measurements from the device. * @@ -134,7 +145,7 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector * @throws DeviceNotAvailableException * @throws IOException */ - private void logCoverageMeasurement(ITestDevice device, String runName) + private void logCoverageMeasurement(String runName) throws DeviceNotAvailableException, IOException { File coverageTarGz = null; File untarDir = null; @@ -142,13 +153,13 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector File indexedProfileFile = null; try { // Compress coverage measurements on the device before pulling. - device.executeShellCommand(ZIP_CLANG_FILES_COMMAND); - coverageTarGz = device.pullFile(COVERAGE_TAR_PATH); + mDevice.executeShellCommand(ZIP_CLANG_FILES_COMMAND); + coverageTarGz = mDevice.pullFile(COVERAGE_TAR_PATH); verifyNotNull( coverageTarGz, "Failed to pull the Clang code coverage file %s", COVERAGE_TAR_PATH); - device.deleteFile(COVERAGE_TAR_PATH); + mDevice.deleteFile(COVERAGE_TAR_PATH); untarDir = FileUtil.createTempDir("clang_coverage"); TarUtil.unTar(coverageTarGz, untarDir); @@ -197,7 +208,6 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector } finally { FileUtil.deleteFile(coverageTarGz); FileUtil.recursiveDelete(untarDir); - FileUtil.recursiveDelete(profileTool); FileUtil.deleteFile(indexedProfileFile); } } @@ -210,26 +220,25 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector private NativeCodeCoverageFlusher getCoverageFlusher() { if (mFlusher == null) { verifyNotNull(mConfiguration); + verifyNotNull(mDevice); mFlusher = new NativeCodeCoverageFlusher( - getDevices().get(0), - mConfiguration.getCoverageOptions().getCoverageProcesses()); + mDevice, mConfiguration.getCoverageOptions().getCoverageProcesses()); } return mFlusher; } - private boolean isClangCoverageEnabled() { - return mConfiguration != null - && mConfiguration.getCoverageOptions().isCoverageEnabled() - && mConfiguration.getCoverageOptions().getCoverageToolchains().contains(CLANG); - } - /** * Retrieves the profile tool and dependencies from the build, and extracts them. * * @return the directory containing the profile tool and dependencies */ private File getProfileTool() throws IOException { + // If we have a cached version of the profile tool already, use it. + if (mLlvmProfdataTool != null) { + return mLlvmProfdataTool; + } + // If llvm-profdata-path was set in the Configuration, pass it through. Don't save the path // locally since the parent process is responsible for cleaning it up. File configurationTool = mConfiguration.getCoverageOptions().getLlvmProfdataPath(); @@ -245,7 +254,8 @@ public final class ClangCodeCoverageCollector extends BaseDeviceMetricCollector verifyNotNull( buildInfo.getFile("llvm-profdata.zip"), "Could not get llvm-profdata.zip from the build."); - return ZipUtil.extractZipToTemp(profileToolZip, "llvm-profdata"); + mLlvmProfdataTool = ZipUtil.extractZipToTemp(profileToolZip, "llvm-profdata"); + return mLlvmProfdataTool; } catch (BuildRetrievalError e) { throw new RuntimeException(e); } finally { diff --git a/test_framework/com/android/tradefed/testtype/GTest.java b/test_framework/com/android/tradefed/testtype/GTest.java index 71b326bc1..70beba964 100644 --- a/test_framework/com/android/tradefed/testtype/GTest.java +++ b/test_framework/com/android/tradefed/testtype/GTest.java @@ -19,6 +19,8 @@ package com.android.tradefed.testtype; import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.CLANG; import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.GCOV; +import static com.google.common.base.Verify.verify; + import com.android.ddmlib.FileListingService; import com.android.ddmlib.IShellOutputReceiver; import com.android.tradefed.config.Option; @@ -26,7 +28,6 @@ import com.android.tradefed.config.OptionClass; import com.android.tradefed.device.CollectingOutputReceiver; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.device.metric.ClangCodeCoverageCollector; import com.android.tradefed.device.metric.GcovCodeCoverageCollector; import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.invoker.TestInformation; @@ -35,6 +36,7 @@ import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.testtype.coverage.CoverageOptions; import com.android.tradefed.util.AbiUtils; import com.android.tradefed.util.FileUtil; +import com.android.tradefed.util.NativeCodeCoverageFlusher; import com.google.common.annotations.VisibleForTesting; @@ -429,11 +431,25 @@ public class GTest extends GTestBase implements IDeviceTest { } // Insert the coverage listener if code coverage collection is enabled. listener = addGcovCoverageListenerIfEnabled(testInfo.getContext(), listener); - listener = addClangCoverageListenerIfEnabled(testInfo.getContext(), listener); + listener = addClangCoverageListenerIfEnabled(listener); listener = getGTestListener(listener); + NativeCodeCoverageFlusher flusher = + new NativeCodeCoverageFlusher( + mDevice, getConfiguration().getCoverageOptions().getCoverageProcesses()); Throwable throwable = null; try { + if (getConfiguration().getCoverageOptions().isCoverageEnabled()) { + // Enable abd root on the device, otherwise the following commands will fail. + verify(mDevice.enableAdbRoot(), "Failed to enable adb root."); + + flusher.resetCoverage(); + + // Clang will no longer create directories that are part of the GCOV_PREFIX + // environment variable. Force create the /data/misc/trace/testcoverage dir to + // prevent "No such file or directory" errors when writing test coverage to disk. + mDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage"); + } doRunAllTestsInSubdirectory(testPath, mDevice, listener); } catch (Throwable t) { throwable = t; @@ -475,13 +491,14 @@ public class GTest extends GTestBase implements IDeviceTest { * @return a native coverage listener if coverage is enabled, otherwise the original listener */ private ITestInvocationListener addClangCoverageListenerIfEnabled( - IInvocationContext context, ITestInvocationListener listener) { + ITestInvocationListener listener) { CoverageOptions options = getConfiguration().getCoverageOptions(); if (options.isCoverageEnabled() && options.getCoverageToolchains().contains(CLANG)) { - ClangCodeCoverageCollector clangListener = new ClangCodeCoverageCollector(); + ClangCodeCoverageListener clangListener = + new ClangCodeCoverageListener(mDevice, listener); clangListener.setConfiguration(getConfiguration()); - listener = clangListener.init(context, listener); + return clangListener; } return listener; } diff --git a/test_framework/com/android/tradefed/testtype/GTestBase.java b/test_framework/com/android/tradefed/testtype/GTestBase.java index ace4c00a0..316d2f957 100644 --- a/test_framework/com/android/tradefed/testtype/GTestBase.java +++ b/test_framework/com/android/tradefed/testtype/GTestBase.java @@ -559,6 +559,10 @@ public abstract class GTestBase gTestCmdLine.append(String.format("LD_LIBRARY_PATH=%s ", mLdLibraryPath)); } + if (getConfiguration().getCoverageOptions().isCoverageEnabled()) { + gTestCmdLine.append("GCOV_PREFIX=/data/misc/trace/testcoverage "); + } + // su to requested user if (mRunTestAs != null) { gTestCmdLine.append(String.format("su %s ", mRunTestAs)); diff --git a/test_framework/com/android/tradefed/testtype/InstrumentationTest.java b/test_framework/com/android/tradefed/testtype/InstrumentationTest.java index 00040953e..bba5fa39b 100644 --- a/test_framework/com/android/tradefed/testtype/InstrumentationTest.java +++ b/test_framework/com/android/tradefed/testtype/InstrumentationTest.java @@ -22,6 +22,7 @@ import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.J import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Verify.verify; import com.android.ddmlib.IDevice; import com.android.ddmlib.Log; @@ -36,7 +37,6 @@ import com.android.tradefed.config.Option.Importance; import com.android.tradefed.config.OptionClass; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.device.metric.ClangCodeCoverageCollector; import com.android.tradefed.device.metric.GcovCodeCoverageCollector; import com.android.tradefed.device.metric.IMetricCollector; import com.android.tradefed.device.metric.IMetricCollectorReceiver; @@ -54,10 +54,13 @@ import com.android.tradefed.result.ddmlib.DefaultRemoteAndroidTestRunner; import com.android.tradefed.result.proto.TestRecordProto.FailureStatus; import com.android.tradefed.retry.IRetryDecision; import com.android.tradefed.retry.RetryStrategy; +import com.android.tradefed.testtype.coverage.CoverageOptions; import com.android.tradefed.util.AbiFormatter; import com.android.tradefed.util.ArrayUtil; +import com.android.tradefed.util.JavaCodeCoverageFlusher; import com.android.tradefed.util.ListInstrumentationParser; import com.android.tradefed.util.ListInstrumentationParser.InstrumentationTarget; +import com.android.tradefed.util.NativeCodeCoverageFlusher; import com.android.tradefed.util.StringEscapeUtils; import com.google.common.annotations.VisibleForTesting; @@ -912,7 +915,29 @@ public class InstrumentationTest listener = addBugreportListenerIfEnabled(listener); listener = addJavaCoverageListenerIfEnabled(testInfo, listener); listener = addGcovCoverageListenerIfEnabled(testInfo, listener); - listener = addClangCoverageListenerIfEnabled(testInfo, listener); + listener = addClangCoverageListenerIfEnabled(listener); + + // Clear coverage measurements on the device before running. + if (mConfiguration != null + && mConfiguration.getCoverageOptions().isCoverageFlushEnabled()) { + CoverageOptions options = mConfiguration.getCoverageOptions(); + + if (options.getCoverageToolchains().contains(GCOV) + || options.getCoverageToolchains().contains(CLANG)) { + // Enable abd root on the device, otherwise the following commands will fail. + verify(mDevice.enableAdbRoot(), "Failed to enable adb root."); + + NativeCodeCoverageFlusher flusher = + new NativeCodeCoverageFlusher(mDevice, options.getCoverageProcesses()); + flusher.resetCoverage(); + } + + if (options.getCoverageToolchains().contains(JACOCO)) { + JavaCodeCoverageFlusher flusher = + new JavaCodeCoverageFlusher(mDevice, options.getCoverageProcesses()); + flusher.resetCoverage(); + } + } // TODO: Convert to device-side collectors when possible. for (IMetricCollector collector : mCollectors) { @@ -1010,16 +1035,16 @@ public class InstrumentationTest * Returns a listener that will collect Clang coverage measurements, or the original {@code * listener} if this feature is disabled. */ - ITestInvocationListener addClangCoverageListenerIfEnabled( - TestInformation testInfo, ITestInvocationListener listener) { + ITestInvocationListener addClangCoverageListenerIfEnabled(ITestInvocationListener listener) { if (mConfiguration == null) { return listener; } if (mConfiguration.getCoverageOptions().isCoverageEnabled() && mConfiguration.getCoverageOptions().getCoverageToolchains().contains(CLANG)) { - ClangCodeCoverageCollector clangListener = new ClangCodeCoverageCollector(); + ClangCodeCoverageListener clangListener = + new ClangCodeCoverageListener(getDevice(), listener); clangListener.setConfiguration(mConfiguration); - listener = clangListener.init(testInfo.getContext(), listener); + return clangListener; } return listener; } diff --git a/test_framework/com/android/tradefed/testtype/rust/RustBinaryTest.java b/test_framework/com/android/tradefed/testtype/rust/RustBinaryTest.java index e15d5c446..76bd20439 100644 --- a/test_framework/com/android/tradefed/testtype/rust/RustBinaryTest.java +++ b/test_framework/com/android/tradefed/testtype/rust/RustBinaryTest.java @@ -18,6 +18,7 @@ package com.android.tradefed.testtype.rust; import static com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain.GCOV; +import static com.google.common.base.Verify.verify; import com.android.ddmlib.FileListingService; import com.android.ddmlib.IShellOutputReceiver; @@ -35,6 +36,7 @@ import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.testtype.IDeviceTest; import com.android.tradefed.testtype.coverage.CoverageOptions; +import com.android.tradefed.util.NativeCodeCoverageFlusher; import java.io.File; import java.util.HashMap; @@ -157,8 +159,12 @@ public class RustBinaryTest extends RustTestBase implements IDeviceTest, IConfig final String fullPath) throws DeviceNotAvailableException { CLog.d("RustBinaryTest runTest: " + fullPath); - String cmd = fullPath; - + String cmd; + if (getCoverageOptions().isCoverageEnabled()) { + cmd = "GCOV_PREFIX=/data/misc/trace/testcoverage " + fullPath; + } else { + cmd = fullPath; + } // Rust binary does not support multiple inclusion filters, // so we run the test once for each include filter. List<String> includeFilters = getListOfIncludeFilters(); @@ -222,6 +228,21 @@ public class RustBinaryTest extends RustTestBase implements IDeviceTest, IConfig // Insert the coverage listener if code coverage collection is enabled. listener = addGcovCoverageListenerIfEnabled(testInfo.getContext(), listener); + NativeCodeCoverageFlusher flusher = + new NativeCodeCoverageFlusher(mDevice, getCoverageOptions().getCoverageProcesses()); + + if (getCoverageOptions().isCoverageEnabled()) { + // Enable abd root on the device, otherwise the following commands will fail. + // TODO(b/159843590): Restore adb root state later. + verify(mDevice.enableAdbRoot(), "Failed to enable adb root."); + + flusher.resetCoverage(); + + // Clang will no longer create directories that are part of the GCOV_PREFIX + // environment variable. Force create the /data/misc/trace/testcoverage dir to + // prevent "No such file or directory" errors when writing test coverage to disk. + mDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage"); + } CLog.d("To run tests in directory " + testPath); diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java index 60bc4bfb6..897aacef3 100644 --- a/tests/src/com/android/tradefed/UnitTests.java +++ b/tests/src/com/android/tradefed/UnitTests.java @@ -99,7 +99,6 @@ import com.android.tradefed.device.metric.BaseDeviceMetricCollectorTest; import com.android.tradefed.device.metric.BuddyInfoMetricCollectorTest; import com.android.tradefed.device.metric.BugreportzMetricCollectorTest; import com.android.tradefed.device.metric.BugreportzOnFailureCollectorTest; -import com.android.tradefed.device.metric.ClangCodeCoverageCollectorTest; import com.android.tradefed.device.metric.DebugHostLogOnFailureCollectorTest; import com.android.tradefed.device.metric.DeviceMetricDataTest; import com.android.tradefed.device.metric.DumpHeapCollectorTest; @@ -262,6 +261,7 @@ import com.android.tradefed.targetprep.multi.MixImageZipPreparerTest; import com.android.tradefed.targetprep.suite.SuiteApkInstallerTest; import com.android.tradefed.testtype.AndroidJUnitTestTest; import com.android.tradefed.testtype.ArtRunTestTest; +import com.android.tradefed.testtype.ClangCodeCoverageListenerTest; import com.android.tradefed.testtype.DeviceBatteryLevelCheckerTest; import com.android.tradefed.testtype.DeviceJUnit4ClassRunnerTest; import com.android.tradefed.testtype.DeviceSuiteTest; @@ -536,7 +536,6 @@ import org.junit.runners.Suite.SuiteClasses; BuddyInfoMetricCollectorTest.class, BugreportzMetricCollectorTest.class, BugreportzOnFailureCollectorTest.class, - ClangCodeCoverageCollectorTest.class, DebugHostLogOnFailureCollectorTest.class, DeviceMetricDataTest.class, DumpHeapCollectorTest.class, @@ -756,6 +755,7 @@ import org.junit.runners.Suite.SuiteClasses; // testtype AndroidJUnitTestTest.class, ArtRunTestTest.class, + ClangCodeCoverageListenerTest.class, CoverageMeasurementForwarderTest.class, DeviceBatteryLevelCheckerTest.class, DeviceJUnit4ClassRunnerTest.class, diff --git a/tests/src/com/android/tradefed/device/metric/GcovCodeCoverageCollectorTest.java b/tests/src/com/android/tradefed/device/metric/GcovCodeCoverageCollectorTest.java index 6ce6c5891..56744e6be 100644 --- a/tests/src/com/android/tradefed/device/metric/GcovCodeCoverageCollectorTest.java +++ b/tests/src/com/android/tradefed/device/metric/GcovCodeCoverageCollectorTest.java @@ -20,9 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import com.android.tradefed.config.ConfigurationException; import com.android.tradefed.config.IConfiguration; @@ -47,9 +45,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.io.File; @@ -104,13 +100,14 @@ public class GcovCodeCoverageCollectorTest { mCodeCoverageListener = new GcovCodeCoverageCollector(); mCodeCoverageListener.setConfiguration(mMockConfiguration); + mCodeCoverageListener.init(mMockContext, mFakeListener); } @Test public void test_logsCoverageZip() throws Exception { enableGcovCoverage(); // Setup mocks to write the coverage measurement to the file. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tar = createTar( ImmutableMap.of( @@ -121,7 +118,6 @@ public class GcovCodeCoverageCollectorTest { doReturn(tar).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); mCodeCoverageListener.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); @@ -149,11 +145,10 @@ public class GcovCodeCoverageCollectorTest { @Test public void testNoCoverageFiles_logsEmptyZip() throws Exception { enableGcovCoverage(); - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); doReturn(createTar(ImmutableMap.of())).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); mCodeCoverageListener.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); @@ -176,18 +171,17 @@ public class GcovCodeCoverageCollectorTest { enableGcovCoverage(); mCoverageOptionsSetter.setOptionValue("coverage-flush", "true"); + doReturn(true).when(mMockDevice).enableAdbRoot(); doReturn(true).when(mMockDevice).isAdbRoot(); doReturn(createTar(ImmutableMap.of())).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); mCodeCoverageListener.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); - // Verify the flush-all-coverage command was called twice - once on init(...) and once - // on test run end. - verify(mMockDevice, times(2)).executeShellCommand("kill -37 -1"); + // Verify the flush-all-coverage command was called. + verify(mMockDevice).executeShellCommand("kill -37 -1"); } @Test @@ -197,30 +191,28 @@ public class GcovCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("coverage-processes", "mediaserver"); mCoverageOptionsSetter.setOptionValue("coverage-processes", "adbd"); + doReturn(true).when(mMockDevice).enableAdbRoot(); doReturn(true).when(mMockDevice).isAdbRoot(); doReturn("123").when(mMockDevice).getProcessPid("mediaserver"); doReturn("56789").when(mMockDevice).getProcessPid("adbd"); doReturn(createTar(ImmutableMap.of())).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); mCodeCoverageListener.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); - // Verify the flush-coverage command was called with the specific pids twice - once on - // init(...) and once on test run end. - verify(mMockDevice, times(2)).executeShellCommand("kill -37 123 56789"); + // Verify the flush-coverage command was called with the specific pids. + verify(mMockDevice).executeShellCommand("kill -37 123 56789"); } @Test public void testFailure_unableToPullFile() throws Exception { enableGcovCoverage(); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); @@ -236,11 +228,7 @@ public class GcovCodeCoverageCollectorTest { enableGcovCoverage(); mCodeCoverageListener.setCollectOnTestEnd(false); - // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); - - // Simulate a test run. - mCodeCoverageListener.init(mMockContext, mFakeListener); + // Simute a test run. mCodeCoverageListener.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); mCodeCoverageListener.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); @@ -275,25 +263,6 @@ public class GcovCodeCoverageCollectorTest { } } - @Test - public void testInit_adbRootAndCoverageFlushed() throws Exception { - enableGcovCoverage(); - - // Setup mocks. - when(mMockDevice.isAdbRoot()).thenReturn(false).thenReturn(true); - when(mMockDevice.enableAdbRoot()).thenReturn(true); - - // Test init(...). - mCodeCoverageListener.init(mMockContext, mFakeListener); - - InOrder inOrder = Mockito.inOrder(mMockDevice); - inOrder.verify(mMockDevice).isAdbRoot(); - inOrder.verify(mMockDevice).enableAdbRoot(); - inOrder.verify(mMockDevice).executeShellCommand("kill -37 -1"); - inOrder.verify(mMockDevice).executeShellCommand(anyString()); - inOrder.verify(mMockDevice).disableAdbRoot(); - } - /** An {@link ITestInvocationListener} which reads test log data streams for verification. */ private static class LogFileReader implements ITestInvocationListener { private List<ByteString> mLogs = new ArrayList<>(); diff --git a/tests/src/com/android/tradefed/device/metric/JavaCodeCoverageCollectorTest.java b/tests/src/com/android/tradefed/device/metric/JavaCodeCoverageCollectorTest.java index 855e5989f..164e536d3 100644 --- a/tests/src/com/android/tradefed/device/metric/JavaCodeCoverageCollectorTest.java +++ b/tests/src/com/android/tradefed/device/metric/JavaCodeCoverageCollectorTest.java @@ -20,7 +20,6 @@ import static com.android.tradefed.device.metric.JavaCodeCoverageCollector.MERGE import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -123,6 +122,7 @@ public class JavaCodeCoverageCollectorTest { mCodeCoverageCollector = new JavaCodeCoverageCollector(); mCodeCoverageCollector.setConfiguration(mMockConfiguration); + mCodeCoverageCollector.init(mMockContext, mFakeListener); } @Test @@ -131,7 +131,6 @@ public class JavaCodeCoverageCollectorTest { HashMap<String, Metric> runMetrics = new HashMap<>(); // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); @@ -151,7 +150,6 @@ public class JavaCodeCoverageCollectorTest { doReturn("").when(mMockDevice).executeShellCommand(anyString()); // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); @@ -167,12 +165,7 @@ public class JavaCodeCoverageCollectorTest { public void testFailure_noCoverageMetric() throws Exception { enableJavaCoverage(); - // Setup mocks. - when(mMockDevice.executeShellCommand("ps -e")).thenReturn(""); - when(mMockDevice.executeShellCommand("pm list packages -a")).thenReturn(""); - // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, new HashMap<String, Metric>()); @@ -192,7 +185,6 @@ public class JavaCodeCoverageCollectorTest { doReturn(null).when(mMockDevice).pullFile(DEVICE_PATH); // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); @@ -208,8 +200,6 @@ public class JavaCodeCoverageCollectorTest { when(mMockDevice.isAdbRoot()).thenReturn(false); doReturn("").when(mMockDevice).executeShellCommand(anyString()); - // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); @@ -227,13 +217,8 @@ public class JavaCodeCoverageCollectorTest { when(mMockDevice.isAdbRoot()).thenReturn(false); when(mMockDevice.enableAdbRoot()).thenReturn(false); - // Simulate a test run. - try { - mCodeCoverageCollector.init(mMockContext, mFakeListener); - fail("An exception should have been thrown."); - } catch (RuntimeException e) { - // Expected. - } + mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); + mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); verify(mFakeListener, never()) .testLog(anyString(), eq(LogDataType.COVERAGE), any(InputStreamSource.class)); @@ -247,8 +232,6 @@ public class JavaCodeCoverageCollectorTest { when(mMockDevice.isAdbRoot()).thenReturn(false); doReturn("").when(mMockDevice).executeShellCommand(anyString()); - // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); @@ -259,6 +242,21 @@ public class JavaCodeCoverageCollectorTest { } @Test + public void testRunEnded_rootDisabled_noLogIfCannotDisableRoot() throws Exception { + enableJavaCoverage(); + HashMap<String, Metric> runMetrics = createMetricsWithCoverageMeasurement(DEVICE_PATH); + mockCoverageFileOnDevice(DEVICE_PATH); + when(mMockDevice.isAdbRoot()).thenReturn(false); + when(mMockDevice.disableAdbRoot()).thenReturn(false); + + mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); + mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, runMetrics); + + verify(mFakeListener, never()) + .testLog(anyString(), eq(LogDataType.COVERAGE), any(InputStreamSource.class)); + } + + @Test public void testMerge_producesSingleMeasurement() throws Exception { enableJavaCoverage(); @@ -287,7 +285,6 @@ public class JavaCodeCoverageCollectorTest { doReturn("").when(mMockDevice).executeShellCommand(anyString()); doReturn(coverageFile1).doReturn(coverageFile2).when(mMockDevice).pullFile(DEVICE_PATH); - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); mCodeCoverageCollector.testRunEnded(ELAPSED_TIME, TfMetricProtoUtil.upgradeConvert(metric)); mCodeCoverageCollector.testRunStarted(RUN_NAME + "2", TEST_COUNT); @@ -344,7 +341,6 @@ public class JavaCodeCoverageCollectorTest { mCodeCoverageCollector.setCoverageFlusher(mMockFlusher); // Simulate a test run. - mCodeCoverageCollector.init(mMockContext, mFakeListener); mCodeCoverageCollector.testRunStarted(RUN_NAME, TEST_COUNT); Map<String, String> metric = new HashMap<>(); metric.put("coverageFilePath", DEVICE_PATH); diff --git a/tests/src/com/android/tradefed/device/metric/ClangCodeCoverageCollectorTest.java b/tests/src/com/android/tradefed/testtype/ClangCodeCoverageListenerTest.java index c354f03a0..69f60fd52 100644 --- a/tests/src/com/android/tradefed/device/metric/ClangCodeCoverageCollectorTest.java +++ b/tests/src/com/android/tradefed/testtype/ClangCodeCoverageListenerTest.java @@ -14,23 +14,20 @@ * limitations under the License. */ -package com.android.tradefed.device.metric; +package com.android.tradefed.testtype; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import com.android.tradefed.build.IBuildInfo; import com.android.tradefed.build.IBuildProvider; import com.android.tradefed.config.IConfiguration; import com.android.tradefed.config.OptionSetter; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.metrics.proto.MetricMeasurement; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.result.InputStreamSource; @@ -41,6 +38,7 @@ import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.IRunUtil; import com.android.tradefed.util.proto.TfMetricProtoUtil; +import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.protobuf.ByteString; @@ -53,9 +51,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @@ -74,7 +70,7 @@ import java.util.zip.ZipOutputStream; /** Unit tests for {@link ClangCodeCoverageListener}. */ @RunWith(JUnit4.class) -public class ClangCodeCoverageCollectorTest { +public class ClangCodeCoverageListenerTest { private static final String RUN_NAME = "SomeTest"; private static final int TEST_COUNT = 5; @@ -90,7 +86,6 @@ public class ClangCodeCoverageCollectorTest { @Mock IConfiguration mMockConfiguration; @Mock IBuildProvider mMockBuildProvider; @Mock ITestDevice mMockDevice; - @Mock IInvocationContext mMockContext; @Spy CommandArgumentCaptor mCommandArgumentCaptor; LogFileReader mFakeListener = new LogFileReader(); @@ -100,7 +95,7 @@ public class ClangCodeCoverageCollectorTest { OptionSetter mCoverageOptionsSetter = null; /** Object under test. */ - ClangCodeCoverageCollector mListener; + ClangCodeCoverageListener mListener; @Before public void setUp() throws Exception { @@ -116,17 +111,13 @@ public class ClangCodeCoverageCollectorTest { doReturn(mMockBuildProvider).when(mMockConfiguration).getBuildProvider(); doReturn(mMockBuildInfo).when(mMockBuildProvider).getBuild(); - doReturn(ImmutableList.of(mMockDevice)).when(mMockContext).getDevices(); - - mListener = new ClangCodeCoverageCollector(); + mListener = new ClangCodeCoverageListener(mMockDevice, mFakeListener); mListener.setConfiguration(mMockConfiguration); mListener.setRunUtil(mCommandArgumentCaptor); } @Test public void coverageDisabled_noCoverageLog() { - mListener.init(mMockContext, mFakeListener); - // Simulate a test run. mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); @@ -140,8 +131,6 @@ public class ClangCodeCoverageCollectorTest { public void clangCoverageDisabled_noCoverageLog() throws Exception { mCoverageOptionsSetter.setOptionValue("coverage", "true"); - mListener.init(mMockContext, mFakeListener); - // Simulate a test run. mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); @@ -158,18 +147,17 @@ public class ClangCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("coverage-flush", "true"); // Setup mocks. + doReturn(true).when(mMockDevice).enableAdbRoot(); doReturn(true).when(mMockDevice).isAdbRoot(); doReturn(createTar(ImmutableMap.of())).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); mListener.invocationEnded(ELAPSED_TIME); - // Verify the flush-all-coverage command was called twice - once on init() and once during - // the end of the test run. - verify(mMockDevice, times(2)).executeShellCommand("kill -37 -1"); + // Verify the flush-all-coverage command was called. + verify(mMockDevice).executeShellCommand("kill -37 -1"); } @Test @@ -178,7 +166,7 @@ public class ClangCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tarGz = createTar( ImmutableMap.of( @@ -191,7 +179,6 @@ public class ClangCodeCoverageCollectorTest { doReturn(createProfileToolZip()).when(mMockBuildInfo).getFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); mListener.invocationEnded(ELAPSED_TIME); @@ -216,7 +203,7 @@ public class ClangCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tarGz = createTar( ImmutableMap.of( @@ -229,7 +216,6 @@ public class ClangCodeCoverageCollectorTest { doReturn(createProfileToolZip()).when(mMockBuildInfo).getFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); mListener.invocationEnded(ELAPSED_TIME); @@ -251,11 +237,10 @@ public class ClangCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); doReturn(createTar(ImmutableMap.of())).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); mListener.invocationEnded(ELAPSED_TIME); @@ -271,7 +256,7 @@ public class ClangCodeCoverageCollectorTest { mCoverageOptionsSetter.setOptionValue("llvm-profdata-path", "/path/to/some/directory"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tarGz = createTar( ImmutableMap.of( @@ -282,7 +267,6 @@ public class ClangCodeCoverageCollectorTest { doReturn(tarGz).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); mListener.testRunStarted(RUN_NAME, TEST_COUNT); mListener.testRunEnded(ELAPSED_TIME, mMetrics); mListener.invocationEnded(ELAPSED_TIME); @@ -293,12 +277,12 @@ public class ClangCodeCoverageCollectorTest { } @Test - public void testProfileToolNotFound_noLog() throws Exception { + public void testProfileToolNotFound_throwsException() throws Exception { mCoverageOptionsSetter.setOptionValue("coverage", "true"); mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tarGz = createTar( ImmutableMap.of( @@ -309,22 +293,27 @@ public class ClangCodeCoverageCollectorTest { doReturn(tarGz).when(mMockDevice).pullFile(anyString()); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); - mListener.testRunStarted(RUN_NAME, TEST_COUNT); - mListener.testRunEnded(ELAPSED_TIME, mMetrics); - mListener.invocationEnded(ELAPSED_TIME); + try { + mListener.testRunStarted(RUN_NAME, TEST_COUNT); + mListener.testRunEnded(ELAPSED_TIME, mMetrics); + mListener.invocationEnded(ELAPSED_TIME); + fail("an exception should have been thrown"); + } catch (VerifyException e) { + // Expected. + assertThat(e).hasMessageThat().contains("llvm-profdata"); + } // Verify testLog(..) was never called. assertThat(mFakeListener.getLogs()).isEmpty(); } @Test - public void testProfileToolFailed_noLog() throws Exception { + public void testProfileToolFailed_throwsException() throws Exception { mCoverageOptionsSetter.setOptionValue("coverage", "true"); mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); // Setup mocks. - doReturn(true).when(mMockDevice).isAdbRoot(); + doReturn(true).when(mMockDevice).enableAdbRoot(); File tarGz = createTar( ImmutableMap.of( @@ -338,36 +327,20 @@ public class ClangCodeCoverageCollectorTest { mCommandArgumentCaptor.setResult(CommandStatus.FAILED); // Simulate a test run. - mListener.init(mMockContext, mFakeListener); - mListener.testRunStarted(RUN_NAME, TEST_COUNT); - mListener.testRunEnded(ELAPSED_TIME, mMetrics); + try { + mListener.testRunStarted(RUN_NAME, TEST_COUNT); + mListener.testRunEnded(ELAPSED_TIME, mMetrics); + fail("an exception should have been thrown"); + } catch (RuntimeException e) { + // Expected. + assertThat(e).hasMessageThat().contains("merge Clang profile data"); + } mListener.invocationEnded(ELAPSED_TIME); // Verify testLog(..) was never called. assertThat(mFakeListener.getLogs()).isEmpty(); } - @Test - public void testInit_adbRootAndCoverageFlush() throws Exception { - mCoverageOptionsSetter.setOptionValue("coverage", "true"); - mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "CLANG"); - - // Setup mocks. - when(mMockDevice.isAdbRoot()).thenReturn(false).thenReturn(true); - doReturn(true).when(mMockDevice).enableAdbRoot(); - - // Call init(...). - mListener.init(mMockContext, mFakeListener); - - // Verify. - InOrder inOrder = Mockito.inOrder(mMockDevice); - inOrder.verify(mMockDevice).isAdbRoot(); - inOrder.verify(mMockDevice).enableAdbRoot(); - inOrder.verify(mMockDevice).executeShellCommand("kill -37 -1"); - inOrder.verify(mMockDevice).executeShellCommand(anyString()); - inOrder.verify(mMockDevice).disableAdbRoot(); - } - abstract static class CommandArgumentCaptor implements IRunUtil { private List<String> mCommand; private CommandResult mResult = new CommandResult(CommandStatus.SUCCESS); diff --git a/tests/src/com/android/tradefed/testtype/GTestTest.java b/tests/src/com/android/tradefed/testtype/GTestTest.java index 2d70915a7..b4dbe2d79 100644 --- a/tests/src/com/android/tradefed/testtype/GTestTest.java +++ b/tests/src/com/android/tradefed/testtype/GTestTest.java @@ -28,13 +28,10 @@ import com.android.tradefed.device.CollectingOutputReceiver; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.device.MockFileUtil; -import com.android.tradefed.invoker.IInvocationContext; import com.android.tradefed.invoker.TestInformation; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.testtype.coverage.CoverageOptions; -import com.google.common.collect.ImmutableList; - import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; @@ -51,7 +48,6 @@ import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public class GTestTest { private static final String GTEST_FLAG_FILTER = "--gtest_filter"; - private IInvocationContext mMockContext = null; private ITestInvocationListener mMockInvocationListener = null; private IShellOutputReceiver mMockReceiver = null; private ITestDevice mMockITestDevice = null; @@ -66,15 +62,12 @@ public class GTestTest { /** Helper to initialize the various EasyMocks we'll need. */ @Before public void setUp() throws Exception { - mMockContext = EasyMock.createMock(IInvocationContext.class); mMockInvocationListener = EasyMock.createMock(ITestInvocationListener.class); mMockReceiver = EasyMock.createMock(IShellOutputReceiver.class); mMockITestDevice = EasyMock.createMock(ITestDevice.class); mMockReceiver.flush(); EasyMock.expectLastCall().anyTimes(); EasyMock.expect(mMockITestDevice.getSerialNumber()).andStubReturn("serial"); - EasyMock.expect(mMockContext.getDevices()) - .andStubReturn(ImmutableList.of(mMockITestDevice)); mGTest = new GTest() { @Override @@ -105,21 +98,21 @@ public class GTestTest { mConfiguration.setCoverageOptions(mCoverageOptions); mGTest.setConfiguration(mConfiguration); - mTestInfo = TestInformation.newBuilder().setInvocationContext(mMockContext).build(); + mTestInfo = TestInformation.newBuilder().build(); } /** * Helper that replays all mocks. */ private void replayMocks() { - EasyMock.replay(mMockContext, mMockInvocationListener, mMockITestDevice, mMockReceiver); + EasyMock.replay(mMockInvocationListener, mMockITestDevice, mMockReceiver); } /** * Helper that verifies all mocks. */ private void verifyMocks() { - EasyMock.verify(mMockContext, mMockInvocationListener, mMockITestDevice, mMockReceiver); + EasyMock.verify(mMockInvocationListener, mMockITestDevice, mMockReceiver); } /** Test run when the test dir is not found on the device. */ @@ -510,7 +503,9 @@ public class GTestTest { final String testPath2 = String.format("%s/%s", nativeTestPath, test2); MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage")) + .andReturn(""); EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); // Wait up to 5 minutes for the device to be available after flushing coverage data. @@ -568,7 +563,9 @@ public class GTestTest { final String testPath2 = String.format("%s/%s", nativeTestPath, test2); MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage")) + .andReturn(""); // Get the pids to flush coverage data. EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(0))).andReturn("1"); diff --git a/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java b/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java index 682759bfc..d9e1e3e81 100644 --- a/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java +++ b/tests/src/com/android/tradefed/testtype/InstrumentationTestTest.java @@ -164,7 +164,6 @@ public class InstrumentationTestTest { mConfig.setCoverageOptions(mCoverageOptions); mInstrumentationTest.setConfiguration(mConfig); mContext = new InvocationContext(); - mContext.addAllocatedDevice("main", mMockTestDevice); mTestInfo = TestInformation.newBuilder().setInvocationContext(mContext).build(); } @@ -1093,24 +1092,17 @@ public class InstrumentationTestTest { } @Test - public void testAddCoverageListener_enabledAndFlushes() throws Exception { + public void testAddCoverageListener_enabled() throws ConfigurationException { mCoverageOptionsSetter.setOptionValue("coverage", "true"); mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "GCOV"); mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "JACOCO"); - doReturn(true).when(mMockTestDevice).isAdbRoot(); - doReturn("").when(mMockTestDevice).executeShellCommand("ps -e"); - doReturn("").when(mMockTestDevice).executeShellCommand("pm list packages -a"); - ITestInvocationListener listener = mInstrumentationTest.addJavaCoverageListenerIfEnabled(mTestInfo, mMockListener); assertThat(listener).isInstanceOf(JavaCodeCoverageCollector.class); listener = mInstrumentationTest.addGcovCoverageListenerIfEnabled(mTestInfo, mMockListener); assertThat(listener).isInstanceOf(GcovCodeCoverageCollector.class); - - // Ensure that a native coverage flush was executed. - verify(mMockTestDevice).executeShellCommand("kill -37 -1"); } @Test diff --git a/tests/src/com/android/tradefed/testtype/rust/RustBinaryTestTest.java b/tests/src/com/android/tradefed/testtype/rust/RustBinaryTestTest.java index 4dd90369e..1f0a0b688 100644 --- a/tests/src/com/android/tradefed/testtype/rust/RustBinaryTestTest.java +++ b/tests/src/com/android/tradefed/testtype/rust/RustBinaryTestTest.java @@ -312,11 +312,19 @@ public class RustBinaryTestTest { MockFileUtil.setMockDirContents(mMockITestDevice, testPath, test1, test2); EasyMock.expect(mMockITestDevice.getIDevice()).andReturn(null); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage")) + .andReturn(""); EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); + EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); + EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); // Wait up to 5 minutes for the device to be available after flushing coverage data. mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000); + mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000); + mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000); EasyMock.expect(mMockITestDevice.executeShellCommand("rm -rf /data/misc/trace/*")) .andReturn(""); EasyMock.expect(mMockITestDevice.doesFileExist(testPath)).andReturn(true); @@ -327,42 +335,26 @@ public class RustBinaryTestTest { EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false); // report the file as executable EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true); - - // End of test1 - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); - mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000); EasyMock.expect( mMockITestDevice.executeShellCommand( "find /data/misc/trace -name '*.gcda' | tar -cvf" + " /data/misc/trace/coverage.tar -T -")) .andReturn(""); - File tmpFile1 = FileUtil.createTempFile("coverage", ".tar"); - EasyMock.expect(mMockITestDevice.pullFile(coverageTarPath)).andReturn(tmpFile1); - mMockITestDevice.deleteFile(coverageTarPath); - mMockInvocationListener.testLog( - EasyMock.eq("test1_native_runtime_coverage"), - EasyMock.eq(LogDataType.NATIVE_COVERAGE), - EasyMock.anyObject()); - EasyMock.expect( - mMockITestDevice.executeShellCommand( - "find /data/misc/trace -name '*.gcda' -delete")) - .andReturn(""); - - // End of test2 - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn(""); - mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000); EasyMock.expect( mMockITestDevice.executeShellCommand( "find /data/misc/trace -name '*.gcda' | tar -cvf" + " /data/misc/trace/coverage.tar -T -")) .andReturn(""); + File tmpFile1 = FileUtil.createTempFile("coverage", ".tar"); + EasyMock.expect(mMockITestDevice.pullFile(coverageTarPath)).andReturn(tmpFile1); File tmpFile2 = FileUtil.createTempFile("coverage", ".tar"); EasyMock.expect(mMockITestDevice.pullFile(coverageTarPath)).andReturn(tmpFile2); mMockITestDevice.deleteFile(coverageTarPath); + mMockITestDevice.deleteFile(coverageTarPath); + mMockInvocationListener.testLog( + EasyMock.eq("test1_native_runtime_coverage"), + EasyMock.eq(LogDataType.NATIVE_COVERAGE), + EasyMock.anyObject()); mMockInvocationListener.testLog( EasyMock.eq("test2_native_runtime_coverage"), EasyMock.eq(LogDataType.NATIVE_COVERAGE), @@ -371,15 +363,21 @@ public class RustBinaryTestTest { mMockITestDevice.executeShellCommand( "find /data/misc/trace -name '*.gcda' -delete")) .andReturn(""); + EasyMock.expect( + mMockITestDevice.executeShellCommand( + "find /data/misc/trace -name '*.gcda' -delete")) + .andReturn(""); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); String[] files = new String[] {"test1", "test2"}; EasyMock.expect(mMockITestDevice.getChildren(testPath)).andReturn(files); - mockCountTests(testPath1, runListOutput(1)); + mockCountTests("GCOV_PREFIX=/data/misc/trace/testcoverage " + testPath1, runListOutput(1)); mockTestRunStarted("test1", 1); mockShellCommand(test1); mockTestRunEnded(); - mockCountTests(testPath2, runListOutput(1)); + mockCountTests("GCOV_PREFIX=/data/misc/trace/testcoverage " + testPath2, runListOutput(1)); mockTestRunStarted("test2", 1); mockShellCommand(test2); mockTestRunEnded(); @@ -409,13 +407,13 @@ public class RustBinaryTestTest { MockFileUtil.setMockDirContents(mMockITestDevice, testPath, test1, test2); EasyMock.expect(mMockITestDevice.getIDevice()).andReturn(null); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage")) + .andReturn(""); // Get the pids to flush coverage data. EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); - EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(0))).andReturn("1"); EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(0))).andReturn("1"); EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(0))).andReturn("1"); @@ -471,15 +469,17 @@ public class RustBinaryTestTest { mMockITestDevice.executeShellCommand( "find /data/misc/trace -name '*.gcda' -delete")) .andReturn(""); + EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true); + EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true); String[] files = new String[] {"test1", "test2"}; EasyMock.expect(mMockITestDevice.getChildren(testPath)).andReturn(files); - mockCountTests(testPath1, runListOutput(1)); + mockCountTests("GCOV_PREFIX=/data/misc/trace/testcoverage " + testPath1, runListOutput(1)); mockTestRunStarted("test1", 1); mockShellCommand(test1); mockTestRunEnded(); - mockCountTests(testPath2, runListOutput(1)); + mockCountTests("GCOV_PREFIX=/data/misc/trace/testcoverage " + testPath2, runListOutput(1)); mockTestRunStarted("test2", 1); mockShellCommand(test2); mockTestRunEnded(); |