Add retrace test for existing partitioned mapping file format
These tests should be extended each time the format is changed or
extended to ensure we continue to support previous formats.
Change-Id: I94a9dca752fb468d9ec0ab121fbab16e16063433
diff --git a/.gitignore b/.gitignore
index 4008f3e..5b8ffd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -286,8 +286,10 @@
third_party/r8mappings.tar.gz
third_party/remapper
third_party/remapper.tar.gz
-third_party/retrace
-third_party/retrace.tar.gz
+third_party/retrace/binary_compatibility
+third_party/retrace/binary_compatibility.tar.gz
+third_party/retrace/partition_formats
+third_party/retrace/partition_formats.tar.gz
third_party/retrace_benchmark
third_party/retrace_benchmark.tar.gz
third_party/retrace_internal
diff --git a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
index e2d1fd8..e7510c6 100644
--- a/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
+++ b/d8_r8/commonBuildSrc/src/main/kotlin/DependenciesPlugin.kt
@@ -542,6 +542,10 @@
"retrace-binary-compatibility",
Paths.get("third_party", "retrace", "binary_compatibility").toFile(),
Paths.get("third_party", "retrace", "binary_compatibility.tar.gz.sha1").toFile())
+ val retracePartitionFormats = ThirdPartyDependency(
+ "retrace-partition-formats",
+ Paths.get("third_party", "retrace", "partition_formats").toFile(),
+ Paths.get("third_party", "retrace", "partition_formats.tar.gz.sha1").toFile())
val retraceInternal = ThirdPartyDependency(
"retrace-internal",
Paths.get("third_party", "retrace_internal").toFile(),
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 0341252..d7dee5a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -537,6 +537,10 @@
options.testing.irModifier.accept(code, appView);
}
+ if (options.testing.forceThrowInConvert) {
+ throw new RuntimeException("Forcing compilation failure for testing");
+ }
+
if (lensCodeRewriter != null) {
timing.begin("Lens rewrite");
lensCodeRewriter.rewrite(code, context, methodProcessor);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 38bb45b..1367e23 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2235,6 +2235,9 @@
public boolean forceInvokeRangeForInvokeCustom = false;
+ public boolean forceThrowInConvert =
+ System.getProperty("com.android.tools.r8.testing.forceThrowInConvert") != null;
+
private DeterminismChecker getDeterminismChecker() {
// Lazily read the env-var so that it can be set after options init.
if (determinismChecker == null && !hasReadCheckDeterminism) {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 8cacb48..8563271 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -268,6 +268,7 @@
Paths.get(LIBS_DIR, "r8_with_relocated_deps_17.jar");
public static final Path R8LIB_JAR = Paths.get(LIBS_DIR, "r8lib.jar");
public static final Path R8LIB_MAP = Paths.get(LIBS_DIR, "r8lib.jar.map");
+ public static final Path R8LIB_MAP_PARTITIONED = Paths.get(LIBS_DIR, "r8lib.jar_map.zip");
public static final Path R8LIB_EXCLUDE_DEPS_JAR = Paths.get(LIBS_DIR, "r8lib-exclude-deps.jar");
public static final Path R8LIB_EXCLUDE_DEPS_MAP =
Paths.get(LIBS_DIR, "r8lib-exclude-deps.jar.map");
diff --git a/src/test/java/com/android/tools/r8/retrace/partition/RetracePartitionFormatsTest.java b/src/test/java/com/android/tools/r8/retrace/partition/RetracePartitionFormatsTest.java
new file mode 100644
index 0000000..f7a29d8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/partition/RetracePartitionFormatsTest.java
@@ -0,0 +1,154 @@
+// Copyright (c) 2023, 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.retrace.partition;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.retrace.Retrace;
+import com.android.tools.r8.retrace.RetraceCommand;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.PartitionMapZipContainer;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.function.Consumer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/** Test to ensure that old formats of the partitioned mapping file continue to work. */
+@RunWith(Parameterized.class)
+public class RetracePartitionFormatsTest extends TestBase {
+
+ private static final List<String> MAPPING_DIRECTORIES = ImmutableList.of("20231012");
+
+ @Parameters(name = "{1}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withNoneRuntime().build(), MAPPING_DIRECTORIES);
+ }
+
+ private final String directory;
+
+ public RetracePartitionFormatsTest(TestParameters parameters, String directory) {
+ parameters.assertNoneRuntime();
+ this.directory = directory;
+ }
+
+ private static Path getPartitionDataRoot() {
+ return Paths.get(ToolHelper.THIRD_PARTY_DIR, "retrace", "partition_formats");
+ }
+
+ private static Path getRetracedStacktracePath(Path directory) {
+ return directory.resolve("retraced-stacktrace.txt");
+ }
+
+ private static Path getRawStacktracePath(Path directory) {
+ return directory.resolve("raw-stacktrace.txt");
+ }
+
+ private static Path getPartitionedMapPath(Path directory) {
+ return directory.resolve("partitioned-map.zip");
+ }
+
+ private Path getDirectoryPath() {
+ return getPartitionDataRoot().resolve(directory);
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path directory = getDirectoryPath();
+ Path mapping = getPartitionedMapPath(directory);
+ List<String> expected = FileUtils.readAllLines(getRetracedStacktracePath(directory));
+ retrace(
+ mapping,
+ getRawStacktracePath(directory),
+ retraced -> assertEquals(String.join("\n", expected), String.join("\n", retraced)));
+ }
+
+ private static void retrace(Path mapping, Path stacktrace, Consumer<List<String>> retraced)
+ throws Exception {
+ Retrace.run(
+ RetraceCommand.builder()
+ .setMappingSupplier(
+ PartitionMapZipContainer.createPartitionMapZipContainerSupplier(mapping))
+ .setStackTrace(FileUtils.readAllLines(stacktrace))
+ .setRetracedStackTraceConsumer(retraced)
+ .build());
+ }
+
+ /**
+ * Generate a snapshot of the R8 partitioned mapping file.
+ *
+ * <p>NOTE: Remember to compile r8lib before running this command!
+ */
+ public static void main(String[] args) throws Exception {
+ // Run r8lib with r8lib as input and force it to throw an exception.
+ ProcessResult result =
+ ToolHelper.runJava(
+ CfRuntime.getSystemRuntime(),
+ ImmutableList.of("-Dcom.android.tools.r8.testing.forceThrowInConvert"),
+ ImmutableList.of(ToolHelper.R8LIB_JAR),
+ "com.android.tools.r8.R8",
+ "--no-tree-shaking",
+ "--lib",
+ ToolHelper.getJava8RuntimeJar().toString(),
+ ToolHelper.R8LIB_JAR.toString());
+ assertEquals("Expected compilation to fail: " + result, result.exitCode, 1);
+
+ LocalDate now = LocalDate.now();
+ String datePrefix = "" + now.getYear() + now.getMonthValue() + now.getDayOfMonth();
+ Path directory = getPartitionDataRoot().resolve(datePrefix);
+ Path mapping = getPartitionedMapPath(directory);
+ Path rawStacktrace = getRawStacktracePath(directory);
+ Path retracedStacktrace = getRetracedStacktracePath(directory);
+
+ Files.createDirectory(directory);
+ Files.copy(ToolHelper.R8LIB_MAP_PARTITIONED, mapping);
+ FileUtils.writeTextFile(rawStacktrace, result.stderr);
+ retrace(
+ mapping,
+ rawStacktrace,
+ retraced -> {
+ try {
+ FileUtils.writeTextFile(retracedStacktrace, retraced);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ System.out.println("Generated new testing files in: " + directory);
+
+ // Check that the raw and retraced files looks reasonable.
+ String raw = FileUtils.readTextFile(rawStacktrace, StandardCharsets.UTF_8);
+ String retraced = FileUtils.readTextFile(retracedStacktrace, StandardCharsets.UTF_8);
+ // Both files should throw the expected error.
+ assertThat(raw, containsString("Forcing compilation failure for testing"));
+ assertThat(retraced, containsString("Forcing compilation failure for testing"));
+ // The raw file should have R8 source file markers and the retraced file should not.
+ assertThat(raw, containsString("(R8_"));
+ assertThat(retraced, not(containsString("(R8_")));
+
+ System.out.println("==========================");
+ System.out.println("Remember to upload changes to cloud storage:");
+ System.out.println(
+ "(cd "
+ + getPartitionDataRoot().getParent()
+ + "; upload_to_google_storage.py -a --bucket r8-deps partition_formats)");
+ System.out.println("==========================");
+ }
+}
diff --git a/third_party/retrace/partition_formats.tar.gz.sha1 b/third_party/retrace/partition_formats.tar.gz.sha1
new file mode 100644
index 0000000..2746d9f
--- /dev/null
+++ b/third_party/retrace/partition_formats.tar.gz.sha1
@@ -0,0 +1 @@
+59d1d142c1eedd4cf2183f4fecc3c0c6ed18acba
\ No newline at end of file