Update disabled test after move of interface method desugaring
Bug: b/197494749
Change-Id: I1a3f75239cd044651253cd2cd6c5d12de6aea0a6
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
index f4fec42..d743010 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest.java
@@ -7,117 +7,132 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.smali.SmaliBuilder;
+import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
-import org.junit.Ignore;
+import java.io.IOException;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
public class InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest extends TestBase {
+ private final TestParameters parameters;
private final boolean includeInterfaceMethodOnJ;
- @Parameterized.Parameters(name = "Include interface method on J: {0}")
- public static Boolean[] data() {
- return BooleanUtils.values();
+ // Note that the expected output is independent of the presence of J.m().
+ private static final String EXPECTED = StringUtils.lines("I.m()", "JImpl.m()");
+
+ @Parameterized.Parameters(name = "{0}, J.m(): {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ TestParameters.builder()
+ .withCfRuntimes()
+ .enableApiLevelsForCf()
+ .withDexRuntimes()
+ .withApiLevel(AndroidApiLevel.B)
+ .build(),
+ BooleanUtils.values());
}
public InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest(
- boolean includeInterfaceMethodOnJ) {
+ TestParameters parameters, boolean includeInterfaceMethodOnJ) {
+ this.parameters = parameters;
this.includeInterfaceMethodOnJ = includeInterfaceMethodOnJ;
}
@Test
- @Ignore("b/197494749 and b/120130831")
- // TODO(b/197494749): Update this test now that desugaring is moved up. In particular this must
- // be rewritten with CF based transformers as R8 does not support interface desugaring on DEX.
- // TODO(b/120130831): With the move of desugaring this issue should be resolved. The bug indicates
- // that a workaround for issues related to the IR implementation can now be reverted.
- public void test() throws Exception {
- // Note that the expected output is independent of the presence of J.m().
- String expectedOutput = StringUtils.lines("I.m()", "JImpl.m()");
-
- byte[] dex = buildProgramDexFileData();
- if (ToolHelper.getDexVm().getVersion().isNewerThan(Version.V6_0_1)) {
- AndroidApp app =
- AndroidApp.builder()
- .addDexProgramData(buildProgramDexFileData(), Origin.unknown())
- .build();
- assertEquals(expectedOutput, runOnArt(app, "TestClass"));
- }
-
- testForR8(Backend.DEX)
- .addProgramDexFileData(dex)
- .addKeepMainRule("TestClass")
- .setMinApi(AndroidApiLevel.M)
- .run("TestClass")
- .assertSuccessWithOutput(expectedOutput);
+ public void testJvm() throws Exception {
+ // The rewritten input is invalid on JVM.
+ parameters.assumeJvmTestParameters();
+ testForJvm(parameters)
+ .addProgramClasses(getClasses())
+ .addProgramClassFileData(getTransformedClasses())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertFailureWithErrorThatThrows(VerifyError.class);
}
- // Using Smali instead of Jasmin because interfaces are broken in Jasmin.
- private byte[] buildProgramDexFileData() throws Exception {
- SmaliBuilder smaliBuilder = new SmaliBuilder();
- smaliBuilder.setMinApi(AndroidApiLevel.N);
+ @Test
+ public void testD8() throws Exception {
+ // Notice that desugaring will map out of the invalid invoke.
+ testForD8(parameters.getBackend())
+ .addProgramClasses(getClasses())
+ .addProgramClassFileData(getTransformedClasses())
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
- smaliBuilder.addClass("TestClass");
+ @Test
+ public void testR8() throws Exception {
+ // Notice that desugaring will map out of the invalid invoke.
+ testForR8(parameters.getBackend())
+ .addProgramClasses(getClasses())
+ .addProgramClassFileData(getTransformedClasses())
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(parameters)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
- // public void main(String[] args) { new JImpl().m(); }
- smaliBuilder.addMainMethod(
- 1,
- "new-instance v0, LJImpl;",
- "invoke-direct {v0}, LJImpl;-><init>()V",
- "invoke-virtual {v0}, LJImpl;->m()V",
- "return-void");
+ private List<Class<?>> getClasses() {
+ return ImmutableList.of(TestClass.class, I.class);
+ }
- smaliBuilder.addInterface("I");
+ private List<byte[]> getTransformedClasses() throws IOException {
+ return ImmutableList.of(
+ transformer(JImpl.class)
+ .transformMethodInsnInMethod(
+ "m",
+ (opcode, owner, name, descriptor, isInterface, visitor) -> {
+ if (opcode == Opcodes.INVOKESPECIAL) {
+ assertEquals(owner, binaryName(J.class));
+ owner = binaryName(I.class);
+ }
+ visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+ })
+ .transform(),
+ transformer(J.class)
+ .removeMethods(
+ (access, name, descriptor, signature, exceptions) ->
+ !includeInterfaceMethodOnJ && name.equals("m"))
+ .transform());
+ }
- // default void m() { System.out.println("In I.m()"); }
- smaliBuilder.addInstanceMethod(
- "void",
- "m",
- 2,
- "sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
- "const-string v1, \"I.m()\"",
- "invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V",
- "return-void");
+ static class TestClass {
- smaliBuilder.addInterface("J", "java.lang.Object", ImmutableList.of("I"));
- if (includeInterfaceMethodOnJ) {
- smaliBuilder.addInstanceMethod(
- "void",
- "m",
- 2,
- "invoke-super {p0}, LI;->m()V",
- "sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
- "const-string v1, \"J.m()\"",
- "invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V",
- "return-void");
+ public static void main(String[] args) {
+ new JImpl().m();
}
+ }
- smaliBuilder.addClass("JImpl", "java.lang.Object", ImmutableList.of("J"));
- smaliBuilder.addDefaultConstructor();
+ interface I {
- // default void m() { I.super.m(); System.out.println("In JImpl.m()"); }
- smaliBuilder.addInstanceMethod(
- "void",
- "m",
- 2,
- // Note: invoke-super instruction to the non-immediate interface I.
- "invoke-super {p0}, LI;->m()V",
- "sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
- "const-string v1, \"JImpl.m()\"",
- "invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V",
- "return-void");
+ default void m() {
+ System.out.println("I.m()");
+ }
+ }
- return smaliBuilder.compile();
+ interface J extends I {
+
+ @Override
+ default void m() {
+ I.super.m();
+ System.out.println("J.m()");
+ }
+ }
+
+ static class JImpl implements J {
+
+ @Override
+ public void m() {
+ J.super.m(); // Will be rewritten to non-immediate interface: I.super.m();
+ System.out.println("JImpl.m()");
+ }
}
}