Test synthetic sharing of outlines from different intermediate builds

Bug: b/434769547
Change-Id: Iebf1dbeeba20422dd9034ef71164d33f9aa1bd10
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSyntheticSharingTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSyntheticSharingTest.java
new file mode 100644
index 0000000..7e80747
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/exceptions/ThrowBlockOutlinerSyntheticSharingTest.java
@@ -0,0 +1,95 @@
+// Copyright (c) 2025, 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.ir.optimize.outliner.exceptions;
+
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestCompileResult;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import java.util.Collection;
+import org.junit.Test;
+
+public class ThrowBlockOutlinerSyntheticSharingTest extends ThrowBlockOutlinerTestBase {
+
+  @Test
+  public void test() throws Exception {
+    TestCompileResult<?, ?> compileResult =
+        testForD8(parameters.getBackend())
+            .addProgramClasses(Main.class)
+            .apply(this::configure)
+            .release()
+            .setIntermediate(true)
+            .setMinApi(parameters)
+            .compile();
+    TestCompileResult<?, ?> otherCompileResult =
+        testForD8(parameters.getBackend())
+            .addProgramClasses(OtherMain.class)
+            .apply(this::configure)
+            .release()
+            .setIntermediate(true)
+            .setMinApi(parameters)
+            .compile();
+    testForD8(parameters.getBackend())
+        .addProgramFiles(compileResult.writeToZip(), otherCompileResult.writeToZip())
+        .release()
+        .setMinApi(parameters)
+        .compile()
+        .inspect(
+            inspector -> {
+              // The output should contain Main, OtherMain, and a *single* synthetic class.
+              assertEquals(3, inspector.allClasses().size());
+              ClassSubject syntheticClassSubject =
+                  inspector.clazz(
+                      SyntheticItemsTestUtils.syntheticThrowBlockOutlineClass(Main.class, 0));
+              assertThat(syntheticClassSubject, isPresent());
+              assertEquals(1, syntheticClassSubject.allMethods().size());
+
+              ClassSubject mainClassSubject = inspector.clazz(Main.class);
+              assertThat(mainClassSubject, isPresent());
+              assertThat(
+                  mainClassSubject.mainMethod(),
+                  invokesMethod(syntheticClassSubject.uniqueMethod()));
+
+              ClassSubject otherMainClassSubject = inspector.clazz(OtherMain.class);
+              assertThat(otherMainClassSubject, isPresent());
+              assertThat(
+                  otherMainClassSubject.mainMethod(),
+                  invokesMethod(syntheticClassSubject.uniqueMethod()));
+            });
+  }
+
+  @Override
+  public void inspectOutlines(Collection<ThrowBlockOutline> outlines, DexItemFactory factory) {
+    // Verify that a single outline was created in each intermediate build.
+    assertEquals(1, outlines.size());
+  }
+
+  @Override
+  public boolean shouldOutline(ThrowBlockOutline outline) {
+    return true;
+  }
+
+  static class Main {
+
+    public static void main(String[] args) {
+      if (args == null) {
+        throw new IllegalArgumentException();
+      }
+    }
+  }
+
+  static class OtherMain {
+
+    public static void main(String[] args) {
+      if (args == null) {
+        throw new IllegalArgumentException();
+      }
+    }
+  }
+}