blob: 7ba5334f8e33e3ca1cd0a01ac5de845bcc1b07f9 [file] [log] [blame]
// 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.naming;
import static com.android.tools.r8.utils.DexInspectorMatchers.isRenamed;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
interface SuperInterface {
Super foo();
}
interface SubInterface extends SuperInterface {
@Override
Sub foo();
}
class Super {
protected int bar() {
return 0;
}
}
class Sub extends Super {
@Override
protected int bar() {
return 1;
}
}
class SuperImplementer implements SuperInterface {
@Override
public Super foo() {
return new Sub();
}
}
class SubImplementer extends SuperImplementer implements SubInterface {
@Override
public Sub foo() {
return (Sub) super.foo();
}
}
class TestMain {
public static void main(String[] args) {
SubImplementer subImplementer = new SubImplementer();
Super sup = subImplementer.foo();
System.out.print(sup.bar());
}
}
@RunWith(VmTestRunner.class)
public class CovariantReturnTypeInSubInterfaceTest extends TestBase {
private void test(boolean overloadAggressively) throws Exception {
String mainName = TestMain.class.getCanonicalName();
String aggressive =
overloadAggressively ? "-overloadaggressively" : "# Not overload aggressively";
List<String> config = ImmutableList.of(
"-printmapping",
"-useuniqueclassmembernames",
aggressive,
"-keep class " + mainName + " {",
" public void main(...);",
"}",
"-keep,allowobfuscation class **.Super* {",
" <methods>;",
"}",
"-keep,allowobfuscation class **.Sub* {",
" <methods>;",
"}"
);
AndroidApp app = readClasses(
SuperInterface.class,
SubInterface.class,
Super.class,
Sub.class,
SuperImplementer.class,
SubImplementer.class,
TestMain.class
);
AndroidApp processedApp =
compileWithR8(app, String.join(System.lineSeparator(), config), options -> {
options.enableInlining = false;
});
DexInspector inspector = new DexInspector(processedApp);
ClassSubject superInterface = inspector.clazz(SuperInterface.class);
assertThat(superInterface, isRenamed());
MethodSubject foo1 = superInterface.method(
Super.class.getCanonicalName(), "foo", ImmutableList.of());
assertThat(foo1, isRenamed());
ClassSubject subInterface = inspector.clazz(SubInterface.class);
assertThat(subInterface, isRenamed());
MethodSubject foo2 = subInterface.method(
Sub.class.getCanonicalName(), "foo", ImmutableList.of());
assertThat(foo2, isRenamed());
assertEquals(foo1.getFinalName(), foo2.getFinalName());
ProcessResult javaResult = ToolHelper.runJava(ToolHelper.getClassPathForTests(), mainName);
assertEquals(0, javaResult.exitCode);
Path outDex = temp.getRoot().toPath().resolve("dex.zip");
processedApp.writeToZip(outDex, OutputMode.DexIndexed);
ProcessResult artResult = ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), mainName);
assertEquals(0, artResult.exitCode);
assertEquals(javaResult.stdout, artResult.stdout);
}
@Test
public void test_notAggressively() throws Exception {
test(false);
}
@Test
public void test_aggressively() throws Exception {
test(true);
}
}