Reapply "Fix TypeSwitch for enums"
This reverts commit 700298b73999005a05be4c3190a4d8aaa6690b9e.
Bug: b/336510513
Change-Id: I00b04b80e36750be6fc6404ae62d80ba05452d6a
diff --git a/src/test/examplesJava21/switchpatternmatching/EnumSwitchTest.java b/src/test/examplesJava21/switchpatternmatching/EnumSwitchTest.java
index 90001a5..e57e31c 100644
--- a/src/test/examplesJava21/switchpatternmatching/EnumSwitchTest.java
+++ b/src/test/examplesJava21/switchpatternmatching/EnumSwitchTest.java
@@ -4,11 +4,10 @@
package switchpatternmatching;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;
-import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
@@ -16,11 +15,13 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import org.junit.Assume;
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;
+import switchpatternmatching.StringSwitchTest.Main;
@RunWith(Parameterized.class)
public class EnumSwitchTest extends TestBase {
@@ -32,7 +33,8 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- public static String EXPECTED_OUTPUT = StringUtils.lines("null", "E1", "E2", "E3", "E4", "a C");
+ public static String EXPECTED_OUTPUT =
+ StringUtils.lines("null", "E1", "E2", "E3", "E4", "a C", "class %s");
@Test
public void testJvm() throws Exception {
@@ -68,36 +70,72 @@
parameters.assumeJvmTestParameters();
testForJvm(parameters)
- .addInnerClassesAndStrippedOuter(getClass())
+ .apply(this::addModifiedProgramClasses)
.run(parameters.getRuntime(), Main.class)
.applyIf(
parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21),
- r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
+ r ->
+ r.assertSuccessWithOutput(
+ String.format(EXPECTED_OUTPUT, "java.lang.MatchException")),
r -> r.assertFailureWithErrorThatThrows(UnsupportedClassVersionError.class));
}
+ private <T extends TestBuilder<?, T>> void addModifiedProgramClasses(
+ TestBuilder<?, T> testBuilder) throws Exception {
+ testBuilder
+ .addStrippedOuter(getClass())
+ .addProgramClasses(FakeI.class, E.class, C.class)
+ .addProgramClassFileData(
+ transformer(I.class)
+ .setPermittedSubclasses(I.class, E.class, C.class, D.class)
+ .transform())
+ .addProgramClassFileData(transformer(D.class).setImplements(I.class).transform())
+ .addProgramClassFileData(
+ transformer(Main.class)
+ .transformTypeInsnInMethod(
+ "getD",
+ (opcode, type, visitor) ->
+ visitor.visitTypeInsn(opcode, "switchpatternmatching/EnumSwitchTest$D"))
+ .transformMethodInsnInMethod(
+ "getD",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ assert name.equals("<init>");
+ visitor.visitMethodInsn(
+ opcode,
+ "switchpatternmatching/EnumSwitchTest$D",
+ name,
+ descriptor,
+ isInterface);
+ })
+ .transform());
+ }
+
@Test
public void testD8() throws Exception {
parameters.assumeDexRuntime();
- assertThrows(
- CompilationFailedException.class,
- () -> testForD8().addInnerClasses(getClass()).setMinApi(parameters).compile());
+ testForD8()
+ .apply(this::addModifiedProgramClasses)
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(String.format(EXPECTED_OUTPUT, "java.lang.RuntimeException"));
}
@Test
public void testR8() throws Exception {
- assertThrows(
- CompilationFailedException.class,
- () ->
- testForR8(parameters.getBackend())
- .addInnerClasses(getClass())
- .setMinApi(parameters)
- .addKeepMainRule(Main.class)
- .compile());
+ Assume.assumeTrue("For Cf we should compile with Jdk 21 library", parameters.isDexRuntime());
+ testForR8(parameters.getBackend())
+ .apply(this::addModifiedProgramClasses)
+ .setMinApi(parameters)
+ .addKeepMainRule(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(String.format(EXPECTED_OUTPUT, "java.lang.RuntimeException"));
}
+ // D is added to the list of permitted subclasses to reproduce the MatchException.
sealed interface I permits E, C {}
+ interface FakeI {}
+
public enum E implements I {
E1,
E2,
@@ -105,6 +143,9 @@
E4
}
+ // Replaced with I.
+ static final class D implements FakeI {}
+
static final class C implements I {}
static class Main {
@@ -140,6 +181,16 @@
enumSwitch(E.E3);
enumSwitch(E.E4);
enumSwitch(new C());
+ try {
+ enumSwitch(getD());
+ } catch (Throwable t) {
+ System.out.println(t.getClass());
+ }
+ }
+
+ public static I getD() {
+ // Replaced by new D();
+ return new C();
}
}
}