blob: 698cf50f010b1323147977a901404ef5230d02fb [file] [log] [blame]
// Copyright (c) 2019, 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.desugaring.interfacemethods;
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.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.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest extends TestBase {
private final boolean includeInterfaceMethodOnJ;
@Parameterized.Parameters(name = "Include interface method on J: {0}")
public static Boolean[] data() {
return BooleanUtils.values();
}
public InvokeSuperInDefaultInterfaceMethodToNonImmediateInterfaceTest(
boolean includeInterfaceMethodOnJ) {
this.includeInterfaceMethodOnJ = includeInterfaceMethodOnJ;
}
@Test
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);
}
// Using Smali instead of Jasmin because interfaces are broken in Jasmin.
private byte[] buildProgramDexFileData() throws Exception {
SmaliBuilder smaliBuilder = new SmaliBuilder();
smaliBuilder.setMinApi(AndroidApiLevel.N);
smaliBuilder.addClass("TestClass");
// 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");
smaliBuilder.addInterface("I");
// 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");
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");
}
smaliBuilder.addClass("JImpl", "java.lang.Object", ImmutableList.of("J"));
smaliBuilder.addDefaultConstructor();
// 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");
return smaliBuilder.compile();
}
}