Add some more tests for member lookup.

Bug: 69101406, 69152228
Change-Id: Icae6bbeb28dfb23f8b0b416b9f24fa4e9158c58f
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 139ee1f..ce46885 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -748,12 +748,25 @@
     return runJava(ImmutableList.of(path.toString()), main);
   }
 
+  public static ProcessResult runJavaNoVerify(Class clazz) throws Exception {
+    String main = clazz.getCanonicalName();
+    Path path = getClassPathForTests();
+    return runJavaNoVerify(ImmutableList.of(path.toString()), main);
+  }
+
   public static ProcessResult runJava(List<String> classpath, String mainClass) throws IOException {
     ProcessBuilder builder = new ProcessBuilder(
         getJavaExecutable(), "-cp", String.join(PATH_SEPARATOR, classpath), mainClass);
     return runProcess(builder);
   }
 
+  public static ProcessResult runJavaNoVerify(List<String> classpath, String mainClass)
+      throws IOException {
+    ProcessBuilder builder = new ProcessBuilder(
+        getJavaExecutable(), "-cp", String.join(PATH_SEPARATOR, classpath), "-noverify", mainClass);
+    return runProcess(builder);
+  }
+
   public static ProcessResult forkD8(Path dir, String... args)
       throws IOException, InterruptedException {
     return forkJava(dir, D8.class, args);
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
index 964f004..d44b460 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminBuilder.java
@@ -55,6 +55,13 @@
       public int getMajorVersion() {
         return 48;
       }
+    },
+    /** JSE 5 is not fully supported by Jasmin. Interfaces will not work. */
+    JSE_5 {
+      @Override
+      public int getMajorVersion() {
+        return 49;
+      }
     };
 
     public abstract int getMajorVersion();
@@ -71,6 +78,7 @@
     private final List<String> methods = new ArrayList<>();
     private final List<String> fields = new ArrayList<>();
     private boolean makeInit = false;
+    private boolean hasInit = false;
     private boolean isInterface = false;
 
     private ClassBuilder(String name) {
@@ -180,7 +188,7 @@
       for (String iface : interfaces) {
         builder.append(".implements ").append(iface).append('\n');
       }
-      if (makeInit) {
+      if (makeInit && !hasInit) {
         builder
             .append(".method public <init>()V\n")
             .append(".limit locals 1\n")
@@ -204,6 +212,8 @@
     }
 
     public MethodSignature addDefaultConstructor() {
+      assert !hasInit;
+      hasInit = true;
       return addMethod("public", "<init>", Collections.emptyList(), "V",
           ".limit stack 1",
           ".limit locals 1",
@@ -245,6 +255,9 @@
   }
 
   public ClassBuilder addInterface(String name, String... interfaces) {
+    // Interfaces are broken in Jasmin (the ACC_SUPER access flag is set) and the JSE_5 and later
+    // will not load corresponding classes.
+    assert majorVersion <= ClassFileVersion.JDK_1_4.getMajorVersion();
     ClassBuilder builder = new ClassBuilder(name, "java/lang/Object", interfaces);
     builder.setIsInterface();
     classes.add(builder);
diff --git a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
index 6d4a501..84b413a 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JasminTestBase.java
@@ -55,7 +55,7 @@
         ByteStreams.copy(input, output);
       }
     }
-    return ToolHelper.runJava(ImmutableList.of(out.getPath()), main);
+    return ToolHelper.runJavaNoVerify(ImmutableList.of(out.getPath()), main);
   }
 
   protected String runOnJava(JasminBuilder builder, String main) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java b/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
index 15d2a08..fb3c067 100644
--- a/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
+++ b/src/test/java/com/android/tools/r8/jasmin/MemberResolutionTest.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.jasmin;
 
+import static java.util.Collections.emptyList;
+
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassFileVersion;
@@ -118,6 +120,189 @@
     ensureICCE(builder);
   }
 
+  @Test
+  @Ignore("b/69101406")
+  public void lookupVirtualMethodWithConflictingPrivate() throws Exception {
+    JasminBuilder builder = new JasminBuilder();
+
+    ClassBuilder superClass = builder.addClass("SuperClass");
+    superClass.addDefaultConstructor();
+    superClass.addVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 42",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
+    subClass.addDefaultConstructor();
+    subClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 123",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
+    mainClass.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  new SubClass",
+        "  dup",
+        "  invokespecial SubClass/<init>()V",
+        "  invokevirtual SubClass/aMethod()V",
+        "  return");
+    ensureIAEExceptJava(builder);
+  }
+
+  @Test
+  @Ignore("b/69152228")
+  public void lookupDirectMethodFromWrongContext() throws Exception {
+    JasminBuilder builder = new JasminBuilder();
+
+    ClassBuilder superClass = builder.addClass("SuperClass");
+    superClass.addDefaultConstructor();
+    superClass.addVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 42",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
+    subClass.addDefaultConstructor();
+    subClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 123",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
+    mainClass.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  new SubClass",
+        "  dup",
+        "  invokespecial SubClass/<init>()V",
+        "  invokespecial SubClass/aMethod()V",
+        "  return");
+    ensureIAEExceptJava(builder);
+  }
+
+  @Test
+  public void lookupPrivateSuperFromSubClass() throws Exception {
+    JasminBuilder builder = new JasminBuilder(ClassFileVersion.JSE_5);
+
+    ClassBuilder superClass = builder.addClass("SuperClass");
+    superClass.addDefaultConstructor();
+    superClass.addPrivateVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 42",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
+    subClass.addDefaultConstructor();
+    subClass.addVirtualMethod("callAMethod", emptyList(), "V",
+        ".limit stack 1",
+        ".limit locals 1",
+        "  aload 0",
+        "  invokespecial SuperClass/aMethod()V",
+        "  return");
+
+    ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
+    mainClass.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  new SubClass",
+        "  dup",
+        "  invokespecial SubClass/<init>()V",
+        "  invokevirtual SubClass/callAMethod()V",
+        "  return");
+
+    ensureIAEExceptJava(builder);
+  }
+
+  @Test
+  @Ignore("b/69101406")
+  public void lookupStaticMethodWithConflictingVirtual() throws Exception {
+    JasminBuilder builder = new JasminBuilder();
+
+    ClassBuilder superClass = builder.addClass("SuperClass");
+    superClass.addDefaultConstructor();
+    superClass.addStaticMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 42",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
+    subClass.addDefaultConstructor();
+    subClass.addVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 123",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
+    mainClass.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  new SubClass",
+        "  dup",
+        "  invokespecial SubClass/<init>()V",
+        "  invokestatic SubClass/aMethod()V",
+        "  return");
+    ensureICCE(builder);
+  }
+
+  @Test
+  @Ignore("b/69101406")
+  public void lookupVirtualMethodWithConflictingStatic() throws Exception {
+    JasminBuilder builder = new JasminBuilder();
+
+    ClassBuilder superClass = builder.addClass("SuperClass");
+    superClass.addDefaultConstructor();
+    superClass.addVirtualMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 42",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder subClass = builder.addClass("SubClass", "SuperClass");
+    subClass.addDefaultConstructor();
+    subClass.addStaticMethod("aMethod", emptyList(), "V",
+        ".limit stack 2",
+        ".limit locals 1",
+        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
+        "  bipush 123",
+        "  invokevirtual java/io/PrintStream/println(I)V",
+        "  return");
+
+    ClassBuilder mainClass = builder.addClass(MAIN_CLASS);
+    mainClass.addMainMethod(
+        ".limit stack 2",
+        ".limit locals 1",
+        "  new SubClass",
+        "  dup",
+        "  invokespecial SubClass/<init>()V",
+        "  invokevirtual SubClass/aMethod()V",
+        "  return");
+    ensureICCE(builder);
+  }
 
   private void ensureSameOutput(JasminBuilder app) throws Exception {
     String dxOutput = runOnArtDx(app, MAIN_CLASS);
@@ -130,13 +315,23 @@
   }
 
   private void ensureICCE(JasminBuilder app) throws Exception {
+    ensureRuntimeException(app, IncompatibleClassChangeError.class);
+  }
+
+  private void ensureIAEExceptJava(JasminBuilder app)
+      throws Exception {
+    ensureRuntimeException(app, IllegalAccessError.class);
+  }
+
+  private void ensureRuntimeException(JasminBuilder app, Class exception) throws Exception {
+    String name = exception.getSimpleName();
     ProcessResult dxOutput = runOnArtDxRaw(app, MAIN_CLASS);
-    Assert.assertTrue(dxOutput.stderr.contains("IncompatibleClassChangeError"));
+    Assert.assertTrue(dxOutput.stderr.contains(name));
     ProcessResult d8Output = runOnArtD8Raw(app, MAIN_CLASS);
-    Assert.assertTrue(d8Output.stderr.contains("IncompatibleClassChangeError"));
+    Assert.assertTrue(d8Output.stderr.contains(name));
     ProcessResult r8Output = runOnArtR8Raw(app, MAIN_CLASS, null);
-    Assert.assertTrue(r8Output.stderr.contains("IncompatibleClassChangeError"));
+    Assert.assertTrue(r8Output.stderr.contains(name));
     ProcessResult javaOutput = runOnJavaRaw(app, MAIN_CLASS);
-    Assert.assertTrue(javaOutput.stderr.contains("IncompatibleClassChangeError"));
+    Assert.assertTrue(javaOutput.stderr.contains(name));
   }
 }