Add test for bug when accessing public fields on non-public ancestor

Bug: 76191597
Change-Id: I5c23a1f852d2135da5b7009f6b22c97316ff50a0
diff --git a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java
new file mode 100644
index 0000000..7733339
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTest.java
@@ -0,0 +1,70 @@
+// Copyright (c) 2018, 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.resolution;
+
+public class PublicFieldInnerClassTest {
+  public static final Class<?>[] CLASSES = {
+      PrivateBase.class,
+      PrivateSubclass.class,
+      PackageBase.class,
+      PackageSubclass.class,
+      ProtectedBase.class,
+      ProtectedSubclass.class,
+      PublicBase.class,
+      PublicSubclass.class,
+      PublicFieldInnerClassTest.class
+  };
+
+  private static class PrivateBase {
+    public int value;
+  }
+
+  private static class PrivateSubclass extends PrivateBase {
+  }
+
+  static class PackageBase {
+    public int value;
+  }
+
+  private static class PackageSubclass extends PackageBase {
+  }
+
+  protected static class ProtectedBase {
+    public int value;
+  }
+
+  private static class ProtectedSubclass extends ProtectedBase {
+  }
+
+  public static class PublicBase {
+    public int value;
+  }
+
+  private static class PublicSubclass extends PublicBase {
+  }
+
+  private static int getPrivate(PrivateSubclass instance) {
+    return instance.value;
+  }
+
+  private static int getPackage(PackageSubclass instance) {
+    return instance.value;
+  }
+
+  private static int getProtected(ProtectedSubclass instance) {
+    return instance.value;
+  }
+
+  private static int getPublic(PublicSubclass instance) {
+    return instance.value;
+  }
+
+  public static void main(String[] args) {
+    System.out.println(getPrivate(new PrivateSubclass()));
+    System.out.println(getPackage(new PackageSubclass()));
+    System.out.println(getProtected(new ProtectedSubclass()));
+    System.out.println(getPublic(new PublicSubclass()));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java
new file mode 100644
index 0000000..b10e5f8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/PublicFieldInnerClassTestRunner.java
@@ -0,0 +1,81 @@
+// Copyright (c) 2018, 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.resolution;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.ProgramConsumer;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.R8Command.Builder;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.origin.Origin;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+
+public class PublicFieldInnerClassTestRunner extends TestBase {
+  static final Class CLASS = PublicFieldInnerClassTest.class;
+  static final Class<?>[] CLASSES = PublicFieldInnerClassTest.CLASSES;
+
+  @Test
+  public void testCf() throws Exception {
+    ProcessResult runInput =
+        ToolHelper.runJava(ToolHelper.getClassPathForTests(), CLASS.getCanonicalName());
+    assertEquals(0, runInput.exitCode);
+    Path outCf = temp.getRoot().toPath().resolve("cf.jar");
+    build(new ClassFileConsumer.ArchiveConsumer(outCf));
+    ProcessResult runCf = ToolHelper.runJava(outCf, CLASS.getCanonicalName());
+    // TODO(b/76191597): Change to assertEquals when bug is fixed
+    assertNotEquals(runInput.toString(), runCf.toString());
+    assertNotEquals(
+        -1,
+        runCf.stderr.indexOf("Exception in thread \"main\" java.lang.NoSuchFieldError:"));
+  }
+
+  @Test
+  public void testDex() throws Exception {
+    ProcessResult runInput =
+        ToolHelper.runJava(ToolHelper.getClassPathForTests(), CLASS.getCanonicalName());
+    assertEquals(0, runInput.exitCode);
+    Path outDex = temp.getRoot().toPath().resolve("dex.zip");
+    build(new DexIndexedConsumer.ArchiveConsumer(outDex));
+    // TODO(b/76191597): Change to runArtNoVerificationErrors + assertEquals when bug is fixed
+    ProcessResult runDex = ToolHelper.runArtRaw(
+        outDex.toString(), CLASS.getCanonicalName());
+    assertNotEquals(runInput.stdout, runDex.stdout);
+    assertNotEquals(runInput.exitCode, runDex.exitCode);
+    assertNotEquals(
+        -1,
+        runDex.stderr.indexOf("Exception in thread \"main\" java.lang.NoSuchFieldError:"));
+  }
+
+  private void build(ProgramConsumer consumer) throws Exception {
+    List<String> config = Arrays.asList(
+        "-keep public class " + CLASS.getCanonicalName() + " {",
+        "  public static void main(...);",
+        "}"
+    );
+    Builder builder = R8Command.builder()
+        .setMode(CompilationMode.DEBUG)
+        .addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()))
+        .setProgramConsumer(consumer)
+        .addProguardConfiguration(config, Origin.unknown());
+    for (Class<?> c : CLASSES) {
+      builder.addClassProgramData(ToolHelper.getClassAsBytes(c), Origin.unknown());
+    }
+    if (consumer instanceof ClassFileConsumer) {
+      // TODO(b/75997473): Enable inlining when supported by CF.
+      ToolHelper.runR8(builder.build(), options -> options.enableInlining = false);
+    } else {
+      ToolHelper.runR8(builder.build());
+    }
+  }
+}