[Retrace] Add test for using MappingSupplier in Retrace

Bug: b/277673018
Change-Id: Ifb3feb975a120e18f97d74dc7d48f97bc787e7bc
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index 3d2740a..75d03af 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -160,16 +160,19 @@
 
   private final StackTraceLineParser<T, ST> stackTraceLineParser;
   private final StackTraceElementProxyRetracer<T, ST> proxyRetracer;
+  private final MappingSupplier<?> mappingSupplier;
   private final DiagnosticsHandler diagnosticsHandler;
   protected final boolean isVerbose;
 
   Retrace(
       StackTraceLineParser<T, ST> stackTraceLineParser,
       StackTraceElementProxyRetracer<T, ST> proxyRetracer,
+      MappingSupplier<?> mappingSupplier,
       DiagnosticsHandler diagnosticsHandler,
       boolean isVerbose) {
     this.stackTraceLineParser = stackTraceLineParser;
     this.proxyRetracer = proxyRetracer;
+    this.mappingSupplier = mappingSupplier;
     this.diagnosticsHandler = diagnosticsHandler;
     this.isVerbose = isVerbose;
   }
@@ -503,6 +506,7 @@
 
     private StackTraceLineParser<T, ST> stackTraceLineParser;
     private StackTraceElementProxyRetracer<T, ST> proxyRetracer;
+    private MappingSupplier<?> mappingSupplier;
     private DiagnosticsHandler diagnosticsHandler;
     protected boolean isVerbose;
 
@@ -512,15 +516,30 @@
       return this;
     }
 
+    /***
+     * Set a final constructed retracer where discovery of keys has been done.
+     */
     public Builder<T, ST> setRetracer(Retracer retracer) {
       return setProxyRetracer(StackTraceElementProxyRetracer.createDefault(retracer));
     }
 
+    /***
+     * Set a final constructed proxy retracer where discovery of keys has been done.
+     */
     public Builder<T, ST> setProxyRetracer(StackTraceElementProxyRetracer<T, ST> proxyRetracer) {
       this.proxyRetracer = proxyRetracer;
       return this;
     }
 
+    /***
+     * Set a mapping supplier to be used for retracing where keys needed will be discovered when
+     * performing the actual retracing.
+     */
+    public Builder<T, ST> setMappingSupplier(MappingSupplier<?> mappingSupplier) {
+      this.mappingSupplier = mappingSupplier;
+      return this;
+    }
+
     public Builder<T, ST> setDiagnosticsHandler(DiagnosticsHandler diagnosticsHandler) {
       this.diagnosticsHandler = diagnosticsHandler;
       return this;
@@ -532,7 +551,8 @@
     }
 
     public Retrace<T, ST> build() {
-      return new Retrace<>(stackTraceLineParser, proxyRetracer, diagnosticsHandler, isVerbose);
+      return new Retrace<>(
+          stackTraceLineParser, proxyRetracer, mappingSupplier, diagnosticsHandler, isVerbose);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
index 5a7a797..4cbe9e7 100644
--- a/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/StringRetrace.java
@@ -30,7 +30,7 @@
       StackTraceElementProxyRetracer<String, StackTraceElementStringProxy> proxyRetracer,
       DiagnosticsHandler diagnosticsHandler,
       boolean isVerbose) {
-    super(stackTraceLineParser, proxyRetracer, diagnosticsHandler, isVerbose);
+    super(stackTraceLineParser, proxyRetracer, null, diagnosticsHandler, isVerbose);
   }
 
   /**
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetracePartitionStackTraceTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetracePartitionStackTraceTest.java
new file mode 100644
index 0000000..801a369
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetracePartitionStackTraceTest.java
@@ -0,0 +1,211 @@
+// 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.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.retrace.StackTrace;
+import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingPartitionMetadata;
+import com.android.tools.r8.retrace.PartitionMappingSupplier;
+import com.android.tools.r8.retrace.ProguardMapPartitioner;
+import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.Retrace;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import com.android.tools.r8.retrace.RetraceStackTraceElementProxy;
+import com.android.tools.r8.retrace.RetracedMethodReference.KnownRetracedMethodReference;
+import com.android.tools.r8.retrace.StackTraceElementProxy;
+import com.android.tools.r8.retrace.StackTraceLineParser;
+import com.android.tools.r8.utils.BooleanBox;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RetracePartitionStackTraceTest extends TestBase {
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  public RetracePartitionStackTraceTest(TestParameters parameters) {
+    parameters.assertNoneRuntime();
+  }
+
+  private final String MAPPING =
+      StringUtils.unixLines(
+          "com.Foo -> a:",
+          "  1:1:void m1():42:42 -> a",
+          "com.Bar -> b:",
+          "  2:2:void m2():43:43 -> b",
+          "com.Baz -> c:",
+          "  3:3:void m3():44:44 -> c");
+
+  @Test
+  public void testRetrace() throws Exception {
+    TestDiagnosticMessagesImpl diagnosticMessages = new TestDiagnosticMessagesImpl();
+    Map<String, byte[]> partitions = new HashMap<>();
+    MappingPartitionMetadata metadata =
+        ProguardMapPartitioner.builder(diagnosticMessages)
+            .setProguardMapProducer(ProguardMapProducer.fromString(MAPPING))
+            .setPartitionConsumer(
+                partition -> partitions.put(partition.getKey(), partition.getPayload()))
+            .build()
+            .run();
+
+    Set<String> requestedKeys = new HashSet<>();
+    BooleanBox setPartitionCallBack = new BooleanBox();
+    PartitionMappingSupplier mappingSupplier =
+        PartitionMappingSupplier.builder()
+            .setMetadata(metadata.getBytes())
+            .setRegisterMappingPartitionCallback(requestedKeys::add)
+            .setPrepareMappingPartitionsCallback(setPartitionCallBack::set)
+            .setMappingPartitionFromKeySupplier(partitions::get)
+            .build();
+
+    Retrace<StackTraceLine, StackTraceLineProxy> retrace =
+        Retrace.<StackTraceLine, StackTraceLineProxy>builder()
+            .setMappingSupplier(mappingSupplier)
+            .setStackTraceLineParser(StackTraceLineProxy::new)
+            .setDiagnosticsHandler(diagnosticMessages)
+            .build();
+
+    List<StackTraceLine> minifiedStackTrace = new ArrayList<>();
+    minifiedStackTrace.add(StackTraceLine.parse("at a.a(SourceFile:1)"));
+    minifiedStackTrace.add(StackTraceLine.parse("at b.b(SourceFile:2)"));
+    minifiedStackTrace.add(StackTraceLine.parse("at c.c(SourceFile:3)"));
+    StackTrace.Builder retraceStackTraceBuilder = StackTrace.builder();
+    // TODO(b/277673018): Ensure that we can use a mapping supplier directly.
+    assertThrows(
+        NullPointerException.class,
+        () ->
+            retrace
+                .retraceStackTrace(minifiedStackTrace, RetraceStackTraceContext.empty())
+                .forEach(
+                    stackTraceLines -> {
+                      assertEquals(1, stackTraceLines.size());
+                      stackTraceLines.get(0).forEach(retraceStackTraceBuilder::add);
+                    }));
+  }
+
+  public static class IdentityStackTraceLineParser
+      implements StackTraceLineParser<StackTraceLine, StackTraceLineProxy> {
+
+    @Override
+    public StackTraceLineProxy parse(StackTraceLine stackTraceLine) {
+      return new StackTraceLineProxy(stackTraceLine);
+    }
+  }
+
+  public static class StackTraceLineProxy
+      extends StackTraceElementProxy<StackTraceLine, StackTraceLineProxy> {
+
+    private final StackTraceLine stackTraceLine;
+
+    public StackTraceLineProxy(StackTraceLine stackTraceLine) {
+      this.stackTraceLine = stackTraceLine;
+    }
+
+    @Override
+    public boolean hasClassName() {
+      return true;
+    }
+
+    @Override
+    public boolean hasMethodName() {
+      return true;
+    }
+
+    @Override
+    public boolean hasSourceFile() {
+      return true;
+    }
+
+    @Override
+    public boolean hasLineNumber() {
+      return true;
+    }
+
+    @Override
+    public boolean hasFieldName() {
+      return false;
+    }
+
+    @Override
+    public boolean hasFieldOrReturnType() {
+      return false;
+    }
+
+    @Override
+    public boolean hasMethodArguments() {
+      return false;
+    }
+
+    @Override
+    public ClassReference getClassReference() {
+      return Reference.classFromTypeName(stackTraceLine.className);
+    }
+
+    @Override
+    public String getMethodName() {
+      return stackTraceLine.methodName;
+    }
+
+    @Override
+    public String getSourceFile() {
+      return stackTraceLine.fileName;
+    }
+
+    @Override
+    public int getLineNumber() {
+      return stackTraceLine.lineNumber;
+    }
+
+    @Override
+    public String getFieldName() {
+      return null;
+    }
+
+    @Override
+    public String getFieldOrReturnType() {
+      return null;
+    }
+
+    @Override
+    public String getMethodArguments() {
+      return null;
+    }
+
+    @Override
+    public StackTraceLine toRetracedItem(
+        RetraceStackTraceElementProxy<StackTraceLine, StackTraceLineProxy> retracedProxy,
+        boolean verbose) {
+      KnownRetracedMethodReference knownRetracedMethodReference =
+          retracedProxy.getRetracedMethod().asKnown();
+      return new StackTraceLine(
+          stackTraceLine.toString(),
+          knownRetracedMethodReference.getMethodReference().getHolderClass().getTypeName(),
+          knownRetracedMethodReference.getMethodName(),
+          retracedProxy.getSourceFile(),
+          knownRetracedMethodReference.getOriginalPositionOrDefault(0));
+    }
+  }
+}