Add test to verify inlining of single-target library interface methods.
This feature is yet to be implemented, we expect the test to fail.
Bug: 129044633
Change-Id: I9e46162f396460ee47fd583fcaedb8a05ee648e5
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java
new file mode 100644
index 0000000..892a096
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineLibraryInterfaceMethodTest.java
@@ -0,0 +1,131 @@
+// 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.ir.optimize.inliner;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
+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;
+
+// Test whether a single-caller method, called through a single-target library interface,
+// is inlined.
+@RunWith(Parameterized.class)
+public class InlineLibraryInterfaceMethodTest extends TestBase {
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntime(DexVm.ART_DEFAULT.getVersion()).build();
+ }
+
+ private final TestParameters testParameters;
+
+ public InlineLibraryInterfaceMethodTest(TestParameters testParameters) {
+ this.testParameters = testParameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ class Counts {
+ private long run = 0;
+ private long println = 0;
+ }
+ Counts counts = new Counts();
+ TestRuntime testRuntime = testParameters.getRuntime();
+ testForR8(Backend.DEX)
+ .addInnerClasses(InlineLibraryInterfaceMethodTest.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(testRuntime.asDex().getMinApiLevel())
+ .noMinification()
+ .run(testRuntime, TestClass.class)
+ .assertSuccess()
+ .inspect(
+ inspector -> {
+ MethodSubject methodSubject =
+ inspector.clazz(TestClass.class).uniqueMethodWithName("main").asMethodSubject();
+
+ counts.run = countInvokesWithName(methodSubject, "run");
+ counts.println = countInvokesWithName(methodSubject, "println");
+ });
+
+ // TODO(b/129044633) We expect 0 x run and 2 x println after we can inline those methods.
+ assertEquals(2, counts.run);
+ assertEquals(0, counts.println);
+ // TODO(b/126323172) After this issue has been fixed, add test here to check the same with
+ // desugared lambdas.
+ }
+
+ private static long countInvokesWithName(MethodSubject methodSubject, String name) {
+ return methodSubject
+ .streamInstructions()
+ .filter(
+ instruction ->
+ instruction.isInvoke()
+ && ((InvokeInstructionSubject) instruction)
+ .invokedMethod()
+ .name
+ .toString()
+ .equals(name))
+ .count();
+ }
+
+ // The test classes imitate desugared lambda classes.
+ static class StatelessLambdaClass implements Runnable {
+ public static final StatelessLambdaClass instance = new StatelessLambdaClass();
+
+ @Override
+ public void run() {
+ TestClass.statelessLambdaImpl();
+ }
+ }
+
+ static class StatefulLambdaClass implements Runnable {
+ final String s;
+
+ StatefulLambdaClass(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public void run() {
+ TestClass.statefulLambdaImpl(s);
+ }
+ }
+
+ static class TestClass {
+ public static int counter = 0;
+
+ static void statelessLambdaImpl() {
+ System.out.println("Running stateless lambda.");
+ ++counter;
+ }
+
+ static void statefulLambdaImpl(String s) {
+ System.out.println("Running stateful lambda: " + s + ".");
+ counter += 10;
+ }
+
+ public static void main(String[] args) {
+ Runnable runnable = StatelessLambdaClass.instance;
+ runnable.run();
+
+ String s = "lambda-state";
+ runnable = new StatefulLambdaClass(s);
+ runnable.run();
+
+ if (counter != 11) {
+ throw new RuntimeException("Counter is " + counter + ", expected: 11.");
+ }
+ }
+ }
+}