Add test for incorrect handling of illegal access error

Bug: b/264523290
Bug: b/264522833
Change-Id: I52650592cfe884f3d40279a554d6c4ec3ca13e11
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateInitialResolutionHolderTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateInitialResolutionHolderTest.java
new file mode 100644
index 0000000..4d37079
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateInitialResolutionHolderTest.java
@@ -0,0 +1,144 @@
+// Copyright (c) 2023, 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.packageprivate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.LookupMethodTarget;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.OptionalBool;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.Collections;
+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 PackagePrivateInitialResolutionHolderTest extends TestBase {
+
+  private final String newCDescriptor = "La/C;";
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testResolution() throws Exception {
+    assumeTrue(parameters.isOrSimulateNoneRuntime());
+    AppView<AppInfoWithLiveness> appView =
+        computeAppViewWithLiveness(
+            buildClasses()
+                .addClassProgramData(getRewrittenResources())
+                .addLibraryFile(parameters.getDefaultRuntimeLibrary())
+                .build(),
+            Main.class);
+    AppInfoWithLiveness appInfo = appView.appInfo();
+    DexMethod method =
+        buildMethod(
+            Reference.method(
+                Reference.classFromDescriptor(newCDescriptor),
+                "foo",
+                Collections.emptyList(),
+                null),
+            appInfo.dexItemFactory());
+    MethodResolutionResult resolutionResult = appInfo.resolveMethodOnClassHolderLegacy(method);
+    assertTrue(resolutionResult.isSingleResolution());
+    DexProgramClass programClass =
+        appInfo.definitionForProgramType(
+            buildType(
+                Reference.classFromDescriptor(descriptor(Main.class)), appInfo.dexItemFactory()));
+    assertEquals(OptionalBool.FALSE, resolutionResult.isAccessibleFrom(programClass, appInfo));
+    DexType cType =
+        buildType(Reference.classFromDescriptor(newCDescriptor), appInfo.dexItemFactory());
+    DexProgramClass cClass = appView.definitionForProgramType(cType);
+    LookupMethodTarget lookupMethodTarget =
+        resolutionResult.lookupVirtualDispatchTarget(cClass, appInfo);
+    assertEquals(
+        "void " + typeName(B.class) + ".foo()",
+        lookupMethodTarget.getDefinition().toSourceString());
+  }
+
+  @Test
+  public void testRuntime() throws Exception {
+    boolean hasIllegalAccessError =
+        parameters.isCfRuntime() || parameters.getDexRuntimeVersion().isDalvik();
+    testForRuntime(parameters)
+        .addProgramClassFileData(getRewrittenResources())
+        .run(parameters.getRuntime(), Main.class)
+        .assertFailureWithErrorThatThrowsIf(hasIllegalAccessError, IllegalAccessError.class)
+        // TODO(b/264523290): Should be IllegalAccessError.
+        .assertSuccessWithOutputLinesIf(!hasIllegalAccessError, "B::foo");
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClassFileData(getRewrittenResources())
+        .addKeepMainRule(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .run(parameters.getRuntime(), Main.class)
+        // TODO(b/264522833): Should be IllegalAccessError.
+        .assertFailureWithErrorThatThrows(AbstractMethodError.class);
+  }
+
+  private Collection<byte[]> getRewrittenResources() throws Exception {
+    String newCBuilderDescriptor = "La/CBuilder;";
+    return ImmutableList.of(
+        transformer(B.class).transform(),
+        transformer(C.class).setClassDescriptor(newCDescriptor).transform(),
+        transformer(CBuilder.class)
+            .replaceClassDescriptorInMethodInstructions(descriptor(C.class), newCDescriptor)
+            .replaceClassDescriptorInMembers(descriptor(C.class), newCDescriptor)
+            .setClassDescriptor(newCBuilderDescriptor)
+            .transform(),
+        transformer(Main.class)
+            .replaceClassDescriptorInMembers(descriptor(C.class), newCDescriptor)
+            .replaceClassDescriptorInMethodInstructions(descriptor(C.class), newCDescriptor)
+            .replaceClassDescriptorInMethodInstructions(
+                descriptor(CBuilder.class), newCBuilderDescriptor)
+            .transform());
+  }
+
+  public static class Main {
+
+    public static void main(String[] args) {
+      CBuilder.build().foo();
+    }
+  }
+
+  public static class B {
+
+    public void foo() {
+      System.out.println("B::foo");
+    }
+  }
+
+  static class /* a. */ C extends B {}
+
+  public static class /* a. */ CBuilder {
+
+    public static C build() {
+      return new C();
+    }
+  }
+}