blob: 9c33f50ce33236ff210aed8daa4cd63fde4dea88 [file] [log] [blame]
// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.constantdynamic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.jacoco.JacocoClasses;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class JacocoConstantDynamicTest extends TestBase {
@Parameter() public TestParameters parameters;
@Parameter(1)
public boolean useConstantDynamic;
@Parameters(name = "{0}, useConstantDynamic: {1}")
public static List<Object[]> data() {
return buildParameters(
getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
BooleanUtils.values());
}
public static JacocoClasses testClassesNoConstantDynamic;
public static JacocoClasses testClassesConstantDynamic;
public JacocoClasses testClasses;
private static final String MAIN_CLASS = TestRunner.class.getTypeName();
private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");
@BeforeClass
public static void setUpInput() throws IOException {
testClassesNoConstantDynamic = testClasses(getStaticTemp(), CfVersion.V1_8);
testClassesConstantDynamic = testClasses(getStaticTemp(), CfVersion.V11);
}
@Before
public void setUp() throws IOException {
testClasses = useConstantDynamic ? testClassesConstantDynamic : testClassesNoConstantDynamic;
}
@Test
public void testJvm() throws Exception {
assumeTrue(
parameters.isCfRuntime()
&& (parameters.getRuntime().asCf().isNewerThanOrEqual(CfVm.JDK11)
|| !useConstantDynamic));
// Run non-instrumented code.
testForRuntime(parameters)
.addProgramFiles(testClasses.getOriginal())
.run(parameters.getRuntime(), MAIN_CLASS)
.assertSuccessWithOutput(EXPECTED_OUTPUT);
// Run non-instrumented code with an agent causing on the fly instrumentation on the JVM.
Path output = temp.newFolder().toPath();
Path agentOutputOnTheFly = output.resolve("on-the-fly");
testForJvm()
.addProgramFiles(testClasses.getOriginal())
.enableJaCoCoAgent(ToolHelper.JACOCO_AGENT, agentOutputOnTheFly)
.run(parameters.getRuntime(), MAIN_CLASS)
.assertSuccessWithOutput(EXPECTED_OUTPUT);
List<String> onTheFlyReport = testClasses.generateReport(agentOutputOnTheFly);
assertEquals(2, onTheFlyReport.size());
// Run the instrumented code.
Path agentOutputOffline = output.resolve("offline");
testForJvm()
.addProgramFiles(testClasses.getInstrumented())
.configureJaCoCoAgentForOfflineInstrumentedCode(ToolHelper.JACOCO_AGENT, agentOutputOffline)
.run(parameters.getRuntime(), MAIN_CLASS)
.assertSuccessWithOutput(EXPECTED_OUTPUT);
List<String> offlineReport = testClasses.generateReport(agentOutputOffline);
assertEquals(onTheFlyReport, offlineReport);
}
@Test
public void testD8() throws Exception {
assumeTrue(parameters.getRuntime().isDex());
if (!useConstantDynamic) {
Path output = temp.newFolder().toPath();
Path agentOutput = output.resolve("jacoco.exec");
testForD8(parameters.getBackend())
.addProgramFiles(testClasses.getInstrumented())
.addProgramFiles(ToolHelper.JACOCO_AGENT)
.setMinApi(parameters.getApiLevel())
.compile()
.runWithJaCoCo(agentOutput, parameters.getRuntime(), MAIN_CLASS)
.assertSuccessWithOutput(EXPECTED_OUTPUT);
// TODO(sgjesse): Need to figure out why there is no instrumentation output for newer VMs.
if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
List<String> report = testClasses.generateReport(agentOutput);
assertEquals(2, report.size());
} else {
assertFalse(Files.exists(agentOutput));
}
} else {
testForD8(parameters.getBackend())
.addProgramFiles(testClasses.getInstrumented())
.addProgramFiles(ToolHelper.JACOCO_AGENT)
.setMinApi(parameters.getApiLevel())
.compile();
}
}
private static JacocoClasses testClasses(TemporaryFolder temp, CfVersion version)
throws IOException {
return new JacocoClasses(
transformer(TestRunner.class)
.setVersion(version) /*.setClassDescriptor("LTestRunner;")*/
.transform(),
temp);
}
static class TestRunner {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
}