Add reproduction of rebinding to abstract method with invoke super

Bug: 213581039
Change-Id: I9228a1808d0bbfcd2098ca115ec91c6233b52df1
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
index b9cf537..581fca7 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
@@ -91,7 +91,7 @@
     };
   }
 
-  static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
+  public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForClass(Class<?> clazz, AndroidApiLevel apiLevel) {
     return compilerBuilder -> {
       compilerBuilder.addOptionsModification(
@@ -104,7 +104,8 @@
     };
   }
 
-  static void enableApiCallerIdentification(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
+  public static void enableApiCallerIdentification(
+      TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
         options -> {
           options.apiModelingOptions().enableApiCallerIdentification = true;
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingInvokeSuperAbstractTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingInvokeSuperAbstractTest.java
new file mode 100644
index 0000000..c4eb970
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingInvokeSuperAbstractTest.java
@@ -0,0 +1,109 @@
+// 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.memberrebinding;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForClass;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.apimodel.ApiModelingTestHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.CodeMatchers;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+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;
+
+// This is a reproduction of b/213581039.
+@RunWith(Parameterized.class)
+public class MemberRebindingInvokeSuperAbstractTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  private final List<Class<?>> libraryClasses =
+      ImmutableList.of(LibraryBase.class, LibrarySub.class, LibrarySubSub.class);
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addLibraryClasses(libraryClasses)
+        .addDefaultRuntimeLibrary(parameters)
+        .addProgramClasses(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
+        .enableInliningAnnotations()
+        .apply(ApiModelingTestHelper::enableApiCallerIdentification)
+        .apply(ApiModelingTestHelper::disableOutliningAndStubbing)
+        .apply(
+            builder ->
+                libraryClasses.forEach(clazz -> setMockApiLevelForClass(clazz, AndroidApiLevel.B)))
+        .apply(
+            setMockApiLevelForMethod(
+                LibraryBase.class.getDeclaredMethod("getSystemService"), AndroidApiLevel.B))
+        .apply(
+            setMockApiLevelForMethod(
+                LibrarySub.class.getDeclaredMethod("getSystemService"), AndroidApiLevel.B))
+        .compile()
+        .addRunClasspathClasses(libraryClasses)
+        .inspect(
+            inspector -> {
+              MethodSubject getSystemService =
+                  inspector.clazz(Main.class).uniqueMethodWithName("getSystemService");
+              assertThat(getSystemService, isPresent());
+              // We should never rebind this call to LibraryBase::getSystemService since this can
+              // cause errors when verifying the code on a device where the image has a definition
+              // but it is abstract. For more information, see b/213581039.
+              // TODO(b/213581039): We should not rebind to the abstract method.
+              assertThat(
+                  getSystemService,
+                  CodeMatchers.invokesMethodWithHolderAndName(
+                      typeName(LibraryBase.class), "getSystemService"));
+            })
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("LibrarySub::getSystemService");
+  }
+
+  public abstract static class LibraryBase {
+
+    public abstract void getSystemService();
+  }
+
+  public static class LibrarySub extends LibraryBase {
+
+    @Override
+    public void getSystemService() {
+      System.out.println("LibrarySub::getSystemService");
+    }
+  }
+
+  public static class LibrarySubSub extends LibrarySub {}
+
+  public static class Main extends LibrarySubSub {
+
+    public static void main(String[] args) {
+      new Main().getSystemService();
+    }
+
+    @Override
+    @NeverInline
+    public void getSystemService() {
+      super.getSystemService();
+    }
+  }
+}