blob: 11c52850e0fa9840a358e60ea12ceebdb2b32d9e [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.accessrelaxation;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
class L1 {
private final String x;
private L1(String x) {
this.x = x;
}
private L1() {
this("private_x");
}
static L1 create() {
return new L1();
}
L1(int i) {
this(String.valueOf(i));
}
@Override
public String toString() {
return x;
}
}
class L2_1 extends L1 {
private String y;
private L2_1() {
this(21);
this.y = "private_L2_1_y";
}
L2_1(int i) {
super(i);
this.y = "L2_1_y";
}
private L2_1(String y) {
this(21);
this.y = y;
}
static L2_1 create(String y) {
return new L2_1(y);
}
@Override
public String toString() {
return super.toString() + "_" + y;
}
}
class L2_2 extends L1 {
private String y;
private L2_2(int i) {
super(i);
this.y = "private_L2_2_y";
}
L2_2(String y) {
this(22);
this.y = y;
}
static L2_1 create() {
return new L2_1(22);
}
@Override
public String toString() {
return super.toString() + "_" + y;
}
}
class L3_1 extends L2_1 {
private final String z;
private L3_1(int i) {
this(String.valueOf(i));
}
private L3_1(String z) {
super(31);
this.z = z;
}
static L3_1 create(int i) {
return new L3_1(i);
}
@Override
public String toString() {
return super.toString() + "_" + z;
}
}
class L3_2 extends L2_2 {
private String z;
private L3_2() {
super("private_L3_2_y");
this.z = "private_L3_2_z";
}
private L3_2(int i) {
super(String.valueOf(i));
this.z = "private_L3_2_z" + "_" + i;
}
L3_2(String z) {
this(32);
this.z = z;
}
static L3_2 create(String z) {
return new L3_2(z);
}
@Override
public String toString() {
return super.toString() + "_" + z;
}
}
class CtorTestMain {
public static void main(String[] args) {
System.out.println(L1.create());
System.out.println(L2_1.create("main_y"));
System.out.println(L2_2.create());
System.out.println(L3_1.create(41));
System.out.println(L3_2.create("main_z"));
}
}
@RunWith(Parameterized.class)
public final class ConstructorRelaxationTest extends AccessRelaxationTestBase {
private static final Class<?>[] CLASSES = {
L1.class, L2_1.class, L2_2.class, L3_1.class, L3_2.class
};
@Parameterized.Parameters(name = "Backend: {0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimes().build();
}
public ConstructorRelaxationTest(TestParameters parameters) {
super(parameters);
}
@Test
public void test() throws Exception {
String expectedOutput =
StringUtils.lines(
"private_x",
"21_main_y",
"22_L2_1_y",
"31_L2_1_y_41",
"22_32_main_z");
Class mainClass = CtorTestMain.class;
R8TestRunResult result =
testForR8(parameters.getBackend())
.addProgramClasses(mainClass)
.addProgramClasses(CLASSES)
.addOptionsModification(
o -> {
o.enableInlining = false;
o.enableVerticalClassMerging = false;
})
.noMinification()
.addKeepMainRule(mainClass)
.allowAccessModification()
.setMinApi(parameters.getRuntime())
.run(parameters.getRuntime(), mainClass);
assertEquals(
expectedOutput,
result
.getStdOut()
.replace("java.lang.IncompatibleClassChangeError", "java.lang.IllegalAccessError"));
CodeInspector codeInspector = result.inspector();
for (Class clazz : CLASSES) {
ClassSubject classSubject = codeInspector.clazz(clazz);
assertThat(classSubject, isPresent());
classSubject.getDexClass().forEachMethod(m -> {
assertTrue(!m.isInstanceInitializer() || m.isPublicMethod());
});
}
}
}