blob: 8c50aa73d284ba2fc30a3640eb80f7b324eb9bda [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.codeinspector.Matchers.isRenamed;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class CovariantReturnTypeInSubInterfaceTest extends TestBase {
interface SuperInterface {
Super foo();
}
interface SubInterface extends SuperInterface {
@Override
Sub foo();
}
static class Super {
protected int bar() {
return 0;
}
}
static class Sub extends Super {
@Override
protected int bar() {
return 1;
}
}
static class SuperImplementer implements SuperInterface {
@Override
public Super foo() {
return new Sub();
}
}
static class SubImplementer extends SuperImplementer implements SubInterface {
@Override
public Sub foo() {
return (Sub) super.foo();
}
}
static class TestMain {
public static void main(String[] args) {
SubImplementer subImplementer = new SubImplementer();
Super sup = subImplementer.foo();
System.out.print(sup.bar());
}
}
private final TestParameters parameters;
@Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public CovariantReturnTypeInSubInterfaceTest(TestParameters parameters) {
this.parameters = parameters;
}
private void test(boolean overloadAggressively) throws Exception {
testForR8(parameters.getBackend())
.addInnerClasses(CovariantReturnTypeInSubInterfaceTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(TestMain.class)
.addKeepRules(
"-keep,allowobfuscation class **.*$Super* { <methods>; }",
"-keep,allowobfuscation class **.*$Sub* { <methods>; }",
overloadAggressively ? "-overloadaggressively" : "# Not overload aggressively")
.addOptionsModification(internalOptions -> internalOptions.enableInlining = false)
.run(parameters.getRuntime(), TestMain.class)
.inspect(inspector -> inspect(inspector, overloadAggressively));
}
private void inspect(CodeInspector inspector, boolean overloadAggressively)
throws NoSuchMethodException {
ClassSubject superInterface = inspector.clazz(SuperInterface.class);
assertThat(superInterface, isRenamed());
MethodSubject foo1 = superInterface.uniqueMethodWithName("foo");
assertThat(foo1, isRenamed());
ClassSubject subInterface = inspector.clazz(SubInterface.class);
assertThat(subInterface, isRenamed());
MethodSubject foo2 = subInterface.method(SubInterface.class.getDeclaredMethod("foo"));
assertThat(foo2, isRenamed());
if (overloadAggressively && parameters.isDexRuntime()) {
assertNotEquals(foo1.getFinalName(), foo2.getFinalName());
} else {
assertEquals(foo1.getFinalName(), foo2.getFinalName());
}
}
@Test
public void test_notAggressively() throws Exception {
test(false);
}
@Test
public void test_aggressively() throws Exception {
test(true);
}
}