Add a test of class initialzation of an interface from implementor
This is a variant of b/379241435. Also update the original test for
b/379241435 with more clarity of the order of class initialization.
Bug: b/379241435
Change-Id: I949482969e4c822468151a5c459a794e08b40548
diff --git a/src/test/java/com/android/tools/r8/B379241435Test.java b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedAftertInstantiatingImplementorTest.java
similarity index 83%
rename from src/test/java/com/android/tools/r8/B379241435Test.java
rename to src/test/java/com/android/tools/r8/B379241435InterfaceInitializedAftertInstantiatingImplementorTest.java
index 3647f0a..9fb3f4f 100644
--- a/src/test/java/com/android/tools/r8/B379241435Test.java
+++ b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedAftertInstantiatingImplementorTest.java
@@ -12,7 +12,7 @@
// Regression test for b/379241435.
@RunWith(Parameterized.class)
-public class B379241435Test extends TestBase {
+public class B379241435InterfaceInitializedAftertInstantiatingImplementorTest extends TestBase {
@Parameter(0)
public TestParameters parameters;
@@ -22,7 +22,7 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- private static final String EXPECTED_OUTPUT = StringUtils.lines("A.A()", "I.f()");
+ private static final String EXPECTED_OUTPUT = StringUtils.lines("B.B()", "A.A()", "I.f()");
@Test
public void testJvm() throws Exception {
@@ -56,12 +56,14 @@
.getApiLevel()
.isLessThan(apiLevelWithDefaultInterfaceMethodsSupport()),
r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
- r -> r.assertSuccessWithOutputLines("I.f()"));
+ r -> r.assertSuccessWithOutputLines("B.B()", "I.f()"));
}
public static class TestClass {
public static void main(String[] args) {
+ // Instantiating B does not trigger class initialization of I.
I b = new B();
+ // Invoking the static method on I trigger class initialization of I.
I.f();
}
}
@@ -80,5 +82,9 @@
}
}
- static class B implements I {}
+ static class B implements I {
+ B() {
+ System.out.println("B.B()");
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/B379241435Test.java b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorStaticMethodTest.java
similarity index 75%
copy from src/test/java/com/android/tools/r8/B379241435Test.java
copy to src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorStaticMethodTest.java
index 3647f0a..bb43551 100644
--- a/src/test/java/com/android/tools/r8/B379241435Test.java
+++ b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorStaticMethodTest.java
@@ -10,9 +10,9 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
-// Regression test for b/379241435.
+// Regression test for a variant of b/379241435.
@RunWith(Parameterized.class)
-public class B379241435Test extends TestBase {
+public class B379241435InterfaceInitializedFromImplementorStaticMethodTest extends TestBase {
@Parameter(0)
public TestParameters parameters;
@@ -22,7 +22,7 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- private static final String EXPECTED_OUTPUT = StringUtils.lines("A.A()", "I.f()");
+ private static final String EXPECTED_OUTPUT = StringUtils.lines("B.B()", "A.A()", "I.f()");
@Test
public void testJvm() throws Exception {
@@ -49,6 +49,8 @@
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
.setMinApi(parameters)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
.run(parameters.getRuntime(), TestClass.class)
.applyIf(
parameters.isDexRuntime()
@@ -56,13 +58,15 @@
.getApiLevel()
.isLessThan(apiLevelWithDefaultInterfaceMethodsSupport()),
r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
- r -> r.assertSuccessWithOutputLines("I.f()"));
+ r -> r.assertSuccessWithOutputLines("B.B()", "I.f()"));
}
public static class TestClass {
public static void main(String[] args) {
- I b = new B();
- I.f();
+ // Instantiating B does not trigger class initialization of I.
+ B b = new B();
+ // Invoking m indirectly trigger class initialization of I as it calls a static method on I.
+ B.m();
}
}
@@ -80,5 +84,15 @@
}
}
- static class B implements I {}
+ @NeverClassInline
+ static class B implements I {
+ B() {
+ System.out.println("B.B()");
+ }
+
+ @NeverInline
+ static void m() {
+ I.f();
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/B379241435Test.java b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorVirtualMethodTest.java
similarity index 74%
copy from src/test/java/com/android/tools/r8/B379241435Test.java
copy to src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorVirtualMethodTest.java
index 3647f0a..bdb3b3b 100644
--- a/src/test/java/com/android/tools/r8/B379241435Test.java
+++ b/src/test/java/com/android/tools/r8/B379241435InterfaceInitializedFromImplementorVirtualMethodTest.java
@@ -10,9 +10,9 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
-// Regression test for b/379241435.
+// Regression test for a variant of b/379241435.
@RunWith(Parameterized.class)
-public class B379241435Test extends TestBase {
+public class B379241435InterfaceInitializedFromImplementorVirtualMethodTest extends TestBase {
@Parameter(0)
public TestParameters parameters;
@@ -22,7 +22,7 @@
return getTestParameters().withAllRuntimesAndApiLevels().build();
}
- private static final String EXPECTED_OUTPUT = StringUtils.lines("A.A()", "I.f()");
+ private static final String EXPECTED_OUTPUT = StringUtils.lines("B.B()", "A.A()", "I.f()");
@Test
public void testJvm() throws Exception {
@@ -49,6 +49,9 @@
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
.setMinApi(parameters)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .enableNoMethodStaticizingAnnotations()
.run(parameters.getRuntime(), TestClass.class)
.applyIf(
parameters.isDexRuntime()
@@ -56,13 +59,15 @@
.getApiLevel()
.isLessThan(apiLevelWithDefaultInterfaceMethodsSupport()),
r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
- r -> r.assertSuccessWithOutputLines("I.f()"));
+ r -> r.assertSuccessWithOutputLines("B.B()", "I.f()"));
}
public static class TestClass {
public static void main(String[] args) {
- I b = new B();
- I.f();
+ // Instantiating B does not trigger class initialization of I.
+ B b = new B();
+ // Invoking m indirectly trigger class initialization of I as it calls a static method on I.
+ b.m();
}
}
@@ -80,5 +85,16 @@
}
}
- static class B implements I {}
+ @NeverClassInline
+ static class B implements I {
+ B() {
+ System.out.println("B.B()");
+ }
+
+ @NeverInline
+ @NoMethodStaticizing
+ void m() {
+ I.f();
+ }
+ }
}