1 package android.platform.test.coverage; 2 3 import static com.google.common.base.Verify.verifyNotNull; 4 import static com.google.common.truth.Truth.assertThat; 5 6 import com.android.tradefed.build.IBuildInfo; 7 import com.android.tradefed.device.DeviceNotAvailableException; 8 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric; 9 import com.android.tradefed.result.TestRunResult; 10 import com.android.tradefed.targetprep.TargetSetupError; 11 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 12 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 13 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; 14 import com.android.tradefed.util.AdbRootElevator; 15 import com.android.tradefed.util.FileUtil; 16 import com.google.common.collect.ImmutableMap; 17 18 import java.io.File; 19 import java.io.FileInputStream; 20 import java.io.InputStream; 21 import java.io.IOException; 22 import java.net.URI; 23 import java.nio.file.Files; 24 import java.nio.file.FileSystem; 25 import java.nio.file.FileSystems; 26 27 import org.jacoco.core.analysis.Analyzer; 28 import org.jacoco.core.analysis.CoverageBuilder; 29 import org.jacoco.core.analysis.IBundleCoverage; 30 import org.jacoco.core.tools.ExecFileLoader; 31 import org.junit.Before; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 /** Runs an instrumentation test and verifies the coverage report. */ 36 @RunWith(DeviceJUnit4ClassRunner.class) 37 public final class CoverageSmokeTest extends BaseHostJUnit4Test { 38 39 private static final String COVERAGE_MEASUREMENT_KEY = "coverageFilePath"; 40 private static final String INNER_JAR_PATH = 41 "out/target/common/obj/APPS/CoverageInstrumentationSampleTest_intermediates/jacoco-report-classes.jar"; 42 43 @Before runCoverageDeviceTests()44 public void runCoverageDeviceTests() throws DeviceNotAvailableException, TargetSetupError { 45 installPackage("CoverageInstrumentationSampleTest.apk"); 46 DeviceTestRunOptions options = 47 new DeviceTestRunOptions("android.platform.test.coverage") 48 .setTestClassName( 49 "android.platform.test.coverage.CoverageInstrumentationTest") 50 .setTestMethodName("testCoveredMethod") 51 .setDisableHiddenApiCheck(true) 52 .addInstrumentationArg("coverage", "true"); 53 runDeviceTests(options); 54 } 55 56 @Test instrumentationTest_generatesJavaCoverage()57 public void instrumentationTest_generatesJavaCoverage() 58 throws DeviceNotAvailableException, IOException { 59 TestRunResult testRunResult = getLastDeviceRunResults(); 60 Metric devicePathMetric = testRunResult.getRunProtoMetrics().get(COVERAGE_MEASUREMENT_KEY); 61 String testCoveragePath = devicePathMetric.getMeasurements().getSingleString(); 62 ExecFileLoader execFileLoader = new ExecFileLoader(); 63 File coverageFile = null; 64 try (AdbRootElevator adbRoot = new AdbRootElevator(getDevice())) { 65 coverageFile = getDevice().pullFile(testCoveragePath); 66 execFileLoader.load(coverageFile); 67 } catch (DeviceNotAvailableException | IOException e) { 68 throw new RuntimeException(e); 69 } finally { 70 FileUtil.deleteFile(coverageFile); 71 } 72 CoverageBuilder builder = new CoverageBuilder(); 73 Analyzer analyzer = new Analyzer(execFileLoader.getExecutionDataStore(), builder); 74 IBuildInfo buildInfo = getBuild(); 75 File jacocoAllClassesJar = 76 verifyNotNull( 77 buildInfo.getFile("jacoco-report-classes-all.jar"), 78 "Could not get jacoco-report-classes-all.jar from the build."); 79 if (jacocoAllClassesJar.isDirectory()) { 80 // If we downloaded directly the subset of files, it will be a directory 81 File jacocoReport = FileUtil.findFile(jacocoAllClassesJar, "jacoco-report-classes.jar"); 82 verifyNotNull( 83 jacocoReport, 84 "jacoco-report-classes.jar missing from the directory downloaded."); 85 try (InputStream in = new FileInputStream(jacocoReport)) { 86 analyzer.analyzeAll(in, "jacoco-report-classes.jar"); 87 } 88 } else { 89 URI uri = URI.create("jar:file:" + jacocoAllClassesJar.getPath()); 90 try (FileSystem zip = FileSystems.newFileSystem(uri, ImmutableMap.of())) { 91 try (InputStream in = Files.newInputStream(zip.getPath(INNER_JAR_PATH))) { 92 analyzer.analyzeAll(in, "jacoco-report-classes.jar"); 93 } 94 } 95 } 96 IBundleCoverage coverage = builder.getBundle("JaCoCo Coverage Report"); 97 98 assertThat(coverage).isNotNull(); 99 assertThat(coverage.getPackages()).isNotEmpty(); 100 } 101 } 102