Add a test for inlining of methods with nullable receivers
Bug: 130202534
Change-Id: I398fd65b837fef835f8ac0b744442d282063bd7c
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 106cfac..2137c84 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -78,6 +78,11 @@
return run(runtime, mainClass.getTypeName());
}
+ public RR run(TestRuntime runtime, Class<?> mainClass, String... args)
+ throws ExecutionException, IOException {
+ return run(runtime, mainClass.getTypeName(), args);
+ }
+
public RR run(TestRuntime runtime, String mainClass) throws ExecutionException, IOException {
return run(runtime, mainClass, new String[] {});
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineInvokeWithNullableReceiverTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineInvokeWithNullableReceiverTest.java
new file mode 100644
index 0000000..fa613a7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineInvokeWithNullableReceiverTest.java
@@ -0,0 +1,90 @@
+// 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 com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestBase;
+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 com.android.tools.r8.utils.codeinspector.InstructionSubject;
+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 for b/130202534. */
+@RunWith(Parameterized.class)
+public class InlineInvokeWithNullableReceiverTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection params() {
+ return getTestParameters().withAllRuntimes().build();
+ }
+
+ public InlineInvokeWithNullableReceiverTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ R8TestCompileResult result =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InlineInvokeWithNullableReceiverTest.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(parameters.getRuntime())
+ .compile()
+ .inspect(this::verifyMethodHasBeenInlined);
+
+ result
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(StringUtils.lines("Hello world!"));
+
+ // Invoking main() with a non-zero argument list should cause the program to throw.
+ result
+ .run(parameters.getRuntime(), TestClass.class, "42")
+ .assertFailureWithErrorThatMatches(containsString("NullPointerException"));
+ }
+
+ private void verifyMethodHasBeenInlined(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ assertThat(classSubject, isPresent());
+
+ MethodSubject methodSubject = classSubject.mainMethod();
+ assertThat(methodSubject, isPresent());
+
+ // TODO(b/130202534): A `throw` instruction should have been synthesized into main().
+ assertTrue(methodSubject.streamInstructions().noneMatch(InstructionSubject::isThrow));
+
+ // TODO(b/130202534): Class A should be absent.
+ ClassSubject otherClassSubject = inspector.clazz(A.class);
+ assertThat(otherClassSubject, isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ A obj = args.length == 0 ? new A() : null;
+ obj.m();
+ }
+ }
+
+ static class A {
+
+ public void m() {
+ System.out.println("Hello world!");
+ }
+ }
+}