[Compose] Add tests for composing of mapping information

Bug: b/241763080
Change-Id: I0b1194de6cb2add85487f42b73f57adfad3d4d7e
diff --git a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
index 2fcbd3d..cbb4955 100644
--- a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
+++ b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
@@ -195,7 +195,8 @@
         // Otherwise break if we see a signature that is not equal to the current one and it
         // has another minified range meaning it is not an inlinee.
         if (!thisMappedRange.signature.equals(lastSeen.signature)
-            && !thisMappedRange.minifiedRange.equals(lastSeen.minifiedRange)) {
+            && !thisMappedRange.minifiedRange.equals(lastSeen.minifiedRange)
+            && !isInlineMappedRange(mappedRanges, i)) {
           break;
         }
         seenMappedRanges.add(thisMappedRange);
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeMapVersionTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMapVersionTest.java
new file mode 100644
index 0000000..1774246
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMapVersionTest.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+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 ComposeMapVersionTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  private static final String mappingFoo =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '1.0' }", "com.foo -> a:");
+  private static final String mappingBar =
+      StringUtils.unixLines("# { id: 'com.android.tools.r8.mapping', version: '2.0' }", "a -> b:");
+  private static final String mappingResult =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }", "com.bar -> b:");
+
+  @Test
+  public void testCompose() throws Exception {
+    ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+    ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+    String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+    // TODO(b/241763080): Support mapping information.
+    assertNotEquals(mappingResult, composed);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineTest.java
new file mode 100644
index 0000000..2f89df6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineTest.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+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 ComposeOutlineTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  private static final String mappingFoo =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }",
+          "outline.Class -> a:",
+          "    1:2:int some.inlinee():75:76 -> a",
+          "    1:2:int outline():0 -> a",
+          "    # { 'id':'com.android.tools.r8.outline' }",
+          "outline.Callsite -> x:",
+          "    4:4:int outlineCaller(int):23 -> s",
+          "    5:5:int foo.bar.baz.outlineCaller(int):98:98 -> s",
+          "    5:5:int outlineCaller(int):24 -> s",
+          "    27:27:int outlineCaller(int):0:0 -> s",
+          "    # { 'id':'com.android.tools.r8.outlineCallsite', 'positions': { '1': 4, '2': 5 } }");
+  private static final String mappingBar =
+      StringUtils.unixLines(
+          "a -> b:",
+          "    4:5:int a():1:2 -> m",
+          "x -> c:",
+          "    8:9:int s(int):4:5 -> o",
+          "    42:42:int s(int):27:27 -> o");
+  private static final String mappingResult =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }",
+          "outline.Class -> b:",
+          "    4:5:int some.inlinee():75:76 -> a",
+          "    4:5:int outline():0 -> a",
+          "    # { 'id':'com.android.tools.r8.outline' }",
+          "outline.Callsite -> c:",
+          "    8:8:int outlineCaller(int):23 -> o",
+          "    9:9:int foo.bar.baz.outlineCaller(int):98:98 -> o",
+          "    9:9:int outlineCaller(int):24 -> o",
+          "    42:42:int outlineCaller(int):0:0 -> o",
+          "    # { 'id':'com.android.tools.r8.outlineCallsite', 'positions': { '4': 8, '5': 9 } }");
+
+  @Test
+  public void testCompose() throws Exception {
+    ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+    ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+    String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+    // TODO(b/241763080): Support mapping information.
+    assertNotEquals(mappingResult, composed);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeRewriteFrameTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeRewriteFrameTest.java
new file mode 100644
index 0000000..b6a93a6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeRewriteFrameTest.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+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 ComposeRewriteFrameTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  private static final String mappingFoo =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }",
+          "my.CustomException -> a:",
+          "foo.Bar -> x:",
+          "    4:4:void other.Class.inlinee():23:23 -> a",
+          "    4:4:void caller(other.Class):7 -> a",
+          "    # { id: 'com.android.tools.r8.rewriteFrame', "
+              + "conditions: ['throws(La;)'], actions: ['removeInnerFrames(1)'] }");
+  private static final String mappingBar =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }",
+          "a -> b:",
+          "x -> c:",
+          "    void a(Other.Class) -> m");
+  private static final String mappingResult =
+      StringUtils.unixLines(
+          "# { id: 'com.android.tools.r8.mapping', version: '2.0' }",
+          "my.CustomException -> b:",
+          "foo.Bar -> c:",
+          "    4:4:void other.Class.inlinee():23:23 -> m",
+          "    4:4:void caller(other.Class):7 -> m",
+          "    # { id: 'com.android.tools.r8.rewriteFrame', "
+              + "conditions: ['throws(Lb;)'], actions: ['removeInnerFrames(1)'] }");
+
+  @Test
+  public void testCompose() throws Exception {
+    ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+    ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+    String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+    // TODO(b/241763080): Support mapping information.
+    assertNotEquals(mappingResult, composed);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeSourceFileTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeSourceFileTest.java
new file mode 100644
index 0000000..9cd77f2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeSourceFileTest.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+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 ComposeSourceFileTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  private static final String mappingFoo =
+      StringUtils.unixLines("com.foo -> a:", "    # {'id':'sourceFile','fileName':'Foo.kt'}");
+  private static final String mappingBar =
+      StringUtils.unixLines(
+          "com.bar -> c:", "    # {'id':'sourceFile','fileName':'Bar.kt'}", "a -> b:");
+  private static final String mappingResult =
+      StringUtils.unixLines(
+          "com.bar -> c:",
+          "    # {'id':'sourceFile','fileName':'Bar.kt'}",
+          "com.foo -> b:",
+          "    # {'id':'sourceFile','fileName':'Foo.kt'}");
+
+  @Test
+  public void testCompose() throws Exception {
+    ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+    ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+    String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+    // TODO(b/241763080): Support mapping information.
+    assertNotEquals(mappingResult, composed);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeSyntheticTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeSyntheticTest.java
new file mode 100644
index 0000000..ad939a6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeSyntheticTest.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, 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.mappingcompose;
+
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+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 ComposeSyntheticTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withNoneRuntime().build();
+  }
+
+  private static final String mappingFoo =
+      StringUtils.unixLines(
+          "com.foo -> a:",
+          "# { id: 'com.android.tools.r8.synthesized' }",
+          "    int f -> a",
+          "    # { id: 'com.android.tools.r8.synthesized' }",
+          "    void m() -> b",
+          "    # { id: 'com.android.tools.r8.synthesized' }");
+  private static final String mappingBar =
+      StringUtils.unixLines(
+          "a -> b:",
+          "    int a -> b",
+          "com.bar -> c:",
+          "# { id: 'com.android.tools.r8.synthesized' }",
+          "    void bar() -> a",
+          "    # { id: 'com.android.tools.r8.synthesized' }");
+  private static final String mappingResult =
+      StringUtils.unixLines(
+          "com.foo -> b:",
+          "# { id: 'com.android.tools.r8.synthesized' }",
+          "    int f -> b",
+          "    # { id: 'com.android.tools.r8.synthesized' }",
+          "    void m() -> b",
+          "    # { id: 'com.android.tools.r8.synthesized' }",
+          "com.bar -> c:",
+          "# { id: 'com.android.tools.r8.synthesized' }",
+          "    void bar() -> a",
+          "    # { id: 'com.android.tools.r8.synthesized' }");
+
+  @Test
+  public void testCompose() throws Exception {
+    ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+    ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+    String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+    // TODO(b/241763080): Support mapping information.
+    assertNotEquals(mappingResult, composed);
+  }
+}