Update R8 on DEX compilation test.
Change-Id: I6e76efb1d0c8d4183a6c2e6f8045344f0b00df42
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
index b61e9d8..bb66f2e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/R8CompiledThroughDexTest.java
@@ -7,7 +7,11 @@
import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertTrue;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
@@ -16,10 +20,15 @@
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.cf.bootstrap.BootstrapCurrentEqualityTest;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import java.io.File;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.Pair;
+import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -29,18 +38,16 @@
@RunWith(Parameterized.class)
public class R8CompiledThroughDexTest extends DesugaredLibraryTestBase {
- private static final boolean testExternal = true;
+ private static final boolean minify = false;
private final TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- // We do not use withDexRuntimesStartingAtIncluding to exclude dex-default and therefore
- // avoid this 2 * 8 minutes test running on tools/test.py.
+ // We only run this test with ART 8 and with full desugaring to avoid the large runtime on ART.
return getTestParameters()
.withDexRuntime(Version.V8_1_0)
- .withDexRuntime(Version.V9_0_0)
- .withAllApiLevels()
+ .withApiLevel(AndroidApiLevel.B)
.build();
}
@@ -49,13 +56,61 @@
}
private static String commandLinePathFor(String string) {
+ return commandLinePathFor(Paths.get(string));
+ }
+
+ private static String commandLinePathFor(Path path) {
// We switch to absolute path due to the art frameworks requiring to run the command in a
// different folder.
- return Paths.get(string).toAbsolutePath().toString();
+ return path.toAbsolutePath().toString();
}
private static final String R8_KEEP = Paths.get("src/main/keep.txt").toAbsolutePath().toString();
+ private Pair<List<String>, Consumer<Builder>> buildArguments() {
+ ImmutableList.Builder<String> arguments = ImmutableList.builder();
+ List<Consumer<Builder>> buildup = new ArrayList<>();
+
+ arguments.add(commandLinePathFor(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR));
+ buildup.add(b -> b.addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR));
+
+ arguments.add("--release");
+ buildup.add(b -> b.setMode(CompilationMode.RELEASE));
+
+ arguments.add("--min-api").add(Integer.toString(parameters.getApiLevel().getLevel()));
+ buildup.add(b -> b.setMinApiLevel(parameters.getApiLevel().getLevel()));
+
+ arguments.add("--lib").add(commandLinePathFor(ToolHelper.JAVA_8_RUNTIME));
+ buildup.add(b -> b.addLibraryFiles(ToolHelper.getJava8RuntimeJar()));
+
+ arguments.add("--pg-conf").add(commandLinePathFor(R8_KEEP));
+ buildup.add(b -> b.addProguardConfigurationFiles(Paths.get(R8_KEEP)));
+
+ if (!minify) {
+ arguments.add("--no-minification");
+ buildup.add(b -> b.setDisableMinification(true));
+ }
+
+ Consumer<Builder> consumer = b -> {};
+ for (Consumer<Builder> step : buildup) {
+ consumer = consumer.andThen(step);
+ }
+
+ return new Pair<>(arguments.build(), consumer);
+ }
+
+ private List<String> getSharedArguments() {
+ return buildArguments().getFirst();
+ }
+
+ private Consumer<Builder> getSharedBuilder() {
+ return buildArguments().getSecond();
+ }
+
+ private void printTime(String title, long start) {
+ System.out.println(title + ": " + ((System.nanoTime() - start) / 1000000000) + "s");
+ }
+
@Test
public void testR8CompiledWithR8Dex() throws Exception {
// Compile once R8_WITH_RELOCATED_DEPS_JAR using normal R8_WITH_RELOCATED_DEPS_JAR to dex,
@@ -66,67 +121,80 @@
// We use extra VM parameters for memory. The command parameters should look like:
// -Xmx512m com...R8 --release --min-api 1 --output path/to/folder --lib rt.jar
// --pg-conf R8KeepRules r8.jar
- // The 512m memory is required to make it work on ART since default is lower.
+ // The 512m memory is required to run on ART but any higher and the runtime will fail too.
- File ouputFolder = temp.newFolder("output");
+ Path outputFolder = temp.newFolder("output").toPath();
+ Path outputThroughCf = outputFolder.resolve("outThroughCf.zip");
- // Compile R8 to dex on the JVM.
- Path outputThroughCf = ouputFolder.toPath().resolve("outThroughCf.zip").toAbsolutePath();
- if (testExternal) {
+ // First run compiles with R8 in process and thus with assertions.
+ {
+ long start = System.nanoTime();
+ // Manually construct the R8 command as the test builder will change defaults compared
+ // to the CLI invocation (eg, compressed and pg-map output).
+ Builder builder = R8Command.builder().setOutput(outputThroughCf, OutputMode.DexIndexed);
+ getSharedBuilder().accept(builder);
+ R8.run(builder.build());
+ printTime("R8/JVM in-process", start);
+ }
+
+ // Second run compiles with R8 externally checking it to be equal with the first compilation.
+ // If this fails, likely due to non-determinism, then that is much faster than waiting for the
+ // Art run compilation to finish if the same error can be found directly.
+ {
+ long start = System.nanoTime();
+ Path outputThroughCfExternal = outputFolder.resolve("outThroughCf_external.zip");
+ Path r8jar = ToolHelper.R8_WITH_RELOCATED_DEPS_JAR;
ProcessResult javaProcessResult =
ToolHelper.runJava(
TestRuntime.getCheckedInJdk9(),
- Collections.singletonList(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR),
- "-Xmx512m",
- R8.class.getTypeName(),
- "--release",
- "--min-api",
- Integer.toString(parameters.getApiLevel().getLevel()),
- "--output",
- outputThroughCf.toString(),
- "--lib",
- ToolHelper.JAVA_8_RUNTIME,
- "--pg-conf",
- R8_KEEP,
- ToolHelper.R8_WITH_RELOCATED_DEPS_JAR.toAbsolutePath().toString());
+ Collections.singletonList(r8jar),
+ ImmutableList.builder()
+ .add("-Xmx1g")
+ .add(R8.class.getTypeName())
+ .add("--output")
+ .add(commandLinePathFor(outputThroughCfExternal))
+ .addAll(getSharedArguments())
+ .build()
+ .toArray(new String[0]));
+ printTime("R8/JVM external", start);
assertEquals(javaProcessResult.toString(), 0, javaProcessResult.exitCode);
- } else {
- testForR8(parameters.getBackend())
- .addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR)
- .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
- .addKeepRuleFiles(Paths.get(R8_KEEP))
- .setMinApi(parameters.getApiLevel())
- .compile()
- .writeToZip(outputThroughCf);
+ assertTrue(
+ "The output of R8/JVM in-process and R8/JVM external differ."
+ + " Make sure you have an up-to-date compilation of "
+ + r8jar
+ + ". If not, that could very likely cause the in-process run (eg, via intellij) to"
+ + " differ from the external run which uses "
+ + r8jar
+ + ". If up-to-date, the likely cause of this error is that R8 is non-deterministic.",
+ BootstrapCurrentEqualityTest.filesAreEqual(outputThroughCf, outputThroughCfExternal));
}
- // Compile R8 to Dex on Dex, using the previous dex artifact.
+ // Finally compile R8 on the ART runtime using the already compiled DEX version of R8.
// We need the extra parameter --64 to use 64 bits frameworks.
- Path ouputThroughDex = ouputFolder.toPath().resolve("outThroughDex.zip").toAbsolutePath();
- ProcessResult artProcessResult =
- ToolHelper.runArtRaw(
- Collections.singletonList(outputThroughCf.toAbsolutePath().toString()),
- R8.class.getTypeName(),
- (ToolHelper.ArtCommandBuilder builder) ->
- builder.appendArtOption("--64").appendArtOption("-Xmx512m"),
- parameters.getRuntime().asDex().getVm(),
- true,
- "--release",
- "--min-api",
- Integer.toString(parameters.getApiLevel().getLevel()),
- "--output",
- ouputThroughDex.toString(),
- "--lib",
- commandLinePathFor(ToolHelper.JAVA_8_RUNTIME),
- "--pg-conf",
- commandLinePathFor(R8_KEEP),
- ToolHelper.R8_WITH_RELOCATED_DEPS_JAR.toAbsolutePath().toString());
- if (artProcessResult.exitCode != 0) {
- System.out.println(artProcessResult);
+ {
+ long start = System.nanoTime();
+ Path outputThroughDex = outputFolder.resolve("outThroughDex.zip");
+ ProcessResult artProcessResult =
+ ToolHelper.runArtRaw(
+ Collections.singletonList(commandLinePathFor(outputThroughCf)),
+ R8.class.getTypeName(),
+ builder -> builder.appendArtOption("--64").appendArtOption("-Xmx512m"),
+ parameters.getRuntime().asDex().getVm(),
+ true,
+ ImmutableList.builder()
+ .add("--output")
+ .add(commandLinePathFor(outputThroughDex))
+ .addAll(getSharedArguments())
+ .build()
+ .toArray(new String[0]));
+ printTime("R8/ART", start);
+ if (artProcessResult.exitCode != 0) {
+ System.out.println(artProcessResult);
+ }
+ assertEquals(0, artProcessResult.exitCode);
+ assertTrue(
+ "The output of R8/JVM in-process and R8/ART external differ.",
+ BootstrapCurrentEqualityTest.filesAreEqual(outputThroughCf, outputThroughDex));
}
- assertEquals(0, artProcessResult.exitCode);
-
- // Ensure both generated artifacts are equal.
- assertTrue(BootstrapCurrentEqualityTest.filesAreEqual(outputThroughCf, ouputThroughDex));
}
}