Prerequisite test cleanups for call site optimization info propagation.

These tests have call sites that always pass either null or non-null
instances. Their expectations will be updated (towards better results.)

Bug: 139246447
Change-Id: I13e42f48f9b3361de6d38ff6ecb2095c00011836
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
index 893e20d..71063f4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetClassTest.java
@@ -140,20 +140,19 @@
   }
 
   private void test(
-      TestRunResult result,
-      int expectedGetClassCount,
-      int expectedConstClassCount,
-      int expectedGetClassCountForCall,
-      int expectedConstClassCountForCall) throws Exception {
+      TestRunResult<?> result, boolean isR8, boolean isRelease) throws Exception {
     CodeInspector codeInspector = result.inspector();
     ClassSubject mainClass = codeInspector.clazz(MAIN);
     MethodSubject mainMethod = mainClass.mainMethod();
     assertThat(mainMethod, isPresent());
-    assertEquals(expectedGetClassCount, countGetClass(mainMethod));
-    assertEquals(expectedConstClassCount, countConstClass(mainMethod));
+    int expectedCount = isR8 ? (isRelease ? 0 : 5) : 6;
+    assertEquals(expectedCount, countGetClass(mainMethod));
+    expectedCount = isR8 ? (isRelease ? (parameters.isCfRuntime() ? 7 : 5) : 1) : 0;
+    assertEquals(expectedCount, countConstClass(mainMethod));
 
-    MethodSubject getMainClass = mainClass.method(
-        "java.lang.Class", "getMainClass", ImmutableList.of(MAIN.getCanonicalName()));
+    boolean expectToBeOptimized = isR8 && isRelease;
+
+    MethodSubject getMainClass = mainClass.uniqueMethodWithName("getMainClass");
     assertThat(getMainClass, isPresent());
     // Because of nullable argument, getClass() should remain.
     assertEquals(1, countGetClass(getMainClass));
@@ -162,8 +161,8 @@
     MethodSubject call = mainClass.method("java.lang.Class", "call", ImmutableList.of());
     assertThat(call, isPresent());
     // Because of local, only R8 release mode can rewrite getClass() to const-class.
-    assertEquals(expectedGetClassCountForCall, countGetClass(call));
-    assertEquals(expectedConstClassCountForCall, countConstClass(call));
+    assertEquals(expectToBeOptimized ? 0 : 1, countGetClass(call));
+    assertEquals(expectToBeOptimized ? 1 : 0, countConstClass(call));
   }
 
   @Test
@@ -178,7 +177,7 @@
             .setMinApi(parameters.getRuntime())
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    test(result, 6, 0, 1, 0);
+    test(result, false, false);
 
     // D8 release.
     result =
@@ -188,7 +187,7 @@
             .setMinApi(parameters.getRuntime())
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    test(result, 6, 0, 1, 0);
+    test(result, false, true);
   }
 
   @Test
@@ -203,7 +202,7 @@
             .noMinification()
             .setMinApi(parameters.getRuntime())
             .run(parameters.getRuntime(), MAIN);
-    test(result, 5, 1, 1, 0);
+    test(result, true, false);
 
     // The number of expected const-class instructions differs because constant canonicalization is
     // only enabled for the DEX backend.
@@ -219,7 +218,7 @@
             .setMinApi(parameters.getRuntime())
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    test(result, 0, expectedConstClassCount, 0, 1);
+    test(result, true, true);
 
     // R8 release, minification.
     result =
@@ -230,6 +229,6 @@
             .setMinApi(parameters.getRuntime())
             // We are not checking output because it can't be matched due to minification. Just run.
             .run(parameters.getRuntime(), MAIN);
-    test(result, 0, expectedConstClassCount, 0, 1);
+    test(result, true, true);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
index e92d393..b07d8f1 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/StringValueOfTest.java
@@ -76,21 +76,18 @@
         instructionSubject.isConstString("null", JumboStringMode.ALLOW)).count();
   }
 
-  private void test(
-      TestRunResult result,
-      int expectedStringValueOfCountInMain,
-      int expectedNullCount,
-      int expectedNullStringCountInMain,
-      int expectedStringValueOfCountInConsumer,
-      int expectedNullStringCountInConsumer)
-      throws Exception {
+  private void test(TestRunResult<?> result, boolean isR8, boolean isRelease) throws Exception {
     CodeInspector codeInspector = result.inspector();
     ClassSubject mainClass = codeInspector.clazz(MAIN);
     MethodSubject mainMethod = mainClass.mainMethod();
     assertThat(mainMethod, isPresent());
-    assertEquals(expectedStringValueOfCountInMain, countCall(mainMethod, "String", "valueOf"));
-    assertEquals(expectedNullCount, countConstNullNumber(mainMethod));
-    assertEquals(expectedNullStringCountInMain, countNullStringNumber(mainMethod));
+    int expectedCount = isR8 ? 3 : (isRelease ? 5 : 7);
+    assertEquals(expectedCount, countCall(mainMethod, "String", "valueOf"));
+    // Due to the different behavior regarding constant canonicalization.
+    expectedCount = isR8 ? (parameters.isCfRuntime() ? 2 : 1) : 1;
+    assertEquals(expectedCount, countConstNullNumber(mainMethod));
+    expectedCount = isR8 ? (parameters.isCfRuntime() ? 2 : 1) : (isRelease ? 1 : 0);
+    assertEquals(expectedCount, countNullStringNumber(mainMethod));
 
     MethodSubject hideNPE = mainClass.uniqueMethodWithName("hideNPE");
     assertThat(hideNPE, isPresent());
@@ -99,8 +96,10 @@
 
     MethodSubject uninit = mainClass.uniqueMethodWithName("consumeUninitialized");
     assertThat(uninit, isPresent());
-    assertEquals(expectedStringValueOfCountInConsumer, countCall(uninit, "String", "valueOf"));
-    assertEquals(expectedNullStringCountInConsumer, countNullStringNumber(uninit));
+    expectedCount = isR8 ? 0 : 1;
+    assertEquals(expectedCount, countCall(uninit, "String", "valueOf"));
+    expectedCount = isR8 ? 1 : 0;
+    assertEquals(expectedCount, countNullStringNumber(uninit));
   }
 
   @Test
@@ -115,7 +114,7 @@
             .addOptionsModification(options -> options.enableNonNullTracking = true)
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    test(result, 7, 1, 0, 1, 0);
+    test(result, false, false);
 
     result =
         testForD8()
@@ -125,7 +124,7 @@
             .addOptionsModification(options -> options.enableNonNullTracking = true)
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    test(result, 5, 1, 1, 1, 0);
+    test(result, false, true);
   }
 
   @Test
@@ -141,10 +140,7 @@
             .addOptionsModification(this::configure)
             .run(parameters.getRuntime(), MAIN)
             .assertSuccessWithOutput(JAVA_OUTPUT);
-    // Due to the different behavior regarding constant canonicalization.
-    int expectedNullCount = parameters.isCfRuntime() ? 2 : 1;
-    int expectedNullStringCount = parameters.isCfRuntime() ? 2 : 1;
-    test(result, 3, expectedNullCount, expectedNullStringCount, 0, 1);
+    test(result, true, true);
   }
 
   static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index e961c0e..a3ec1a2 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -28,6 +28,7 @@
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
+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.FieldSubject;
@@ -232,15 +233,31 @@
   }
 
   protected String keepAllMembers(String className) {
-    return "-keep class " + className + " {" + System.lineSeparator()
-        + "  *;" + System.lineSeparator()
-        + "}";
+    return StringUtils.lines(
+        "-keep class " + className + " {",
+        "  *;",
+        "}");
+  }
+
+  protected String keepMainMethod(String className) {
+    return StringUtils.lines(
+        "-keepclasseswithmembers class " + className + " {",
+        "  public static void main(...);",
+        "}");
   }
 
   protected String keepClassMethod(String className, MethodSignature methodSignature) {
-    return "-keep class " + className + " {" + System.lineSeparator()
-        + methodSignature.toString() + ";" + System.lineSeparator()
-        + "}";
+    return StringUtils.lines(
+        "-keep class " + className + " {",
+        methodSignature.toString() + ";",
+        "}");
+  }
+
+  protected String neverInlineMethod(String className, MethodSignature methodSignature) {
+    return StringUtils.lines(
+        "-neverinline class " + className + " {",
+        methodSignature.toString() + ";",
+        "}");
   }
 
   protected void runTest(String folder, String mainClass,
diff --git a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
index b4b0c06..97ec186 100644
--- a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Streams;
 import org.junit.Test;
 
 public class SimplifyIfNotNullKotlinTest extends AbstractR8KotlinTestBase {
@@ -32,14 +31,15 @@
             ImmutableList.of("java.util.Collection", STRING, STRING, "java.lang.Integer"));
 
     final String mainClassName = ex1.getClassName();
-    final String extraRules = keepAllMembers(mainClassName);
+    final String extraRules =
+        keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules, app -> {
       CodeInspector codeInspector = new CodeInspector(app);
       ClassSubject clazz = checkClassIsKept(codeInspector, ex1.getClassName());
 
       MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
-      long ifzCount = Streams.stream(testMethod.iterateInstructions())
-          .filter(i -> i.isIfEqz() || i.isIfNez()).count();
+      long ifzCount =
+          testMethod.streamInstructions().filter(i -> i.isIfEqz() || i.isIfNez()).count();
       long paramNullCheckCount =
           countCall(testMethod, "ArrayIteratorKt", "checkParameterIsNotNull");
       if (allowAccessModification) {
@@ -61,14 +61,14 @@
         new MethodSignature("aOrDefault", STRING, ImmutableList.of(STRING, STRING));
 
     final String mainClassName = ex2.getClassName();
-    final String extraRules = keepAllMembers(mainClassName);
+    final String extraRules =
+        keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules, app -> {
       CodeInspector codeInspector = new CodeInspector(app);
       ClassSubject clazz = checkClassIsKept(codeInspector, ex2.getClassName());
 
       MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
-      long ifzCount = Streams.stream(testMethod.iterateInstructions())
-          .filter(InstructionSubject::isIfEqz).count();
+      long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count();
       long paramNullCheckCount =
           countCall(testMethod, "Intrinsics", "checkParameterIsNotNull");
       if (allowAccessModification) {
@@ -90,18 +90,17 @@
         new MethodSignature("neverThrowNPE", "void", ImmutableList.of("non_null.Foo"));
 
     final String mainClassName = ex3.getClassName();
-    final String extraRules = keepAllMembers(mainClassName);
+    final String extraRules =
+        keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature);
     runTest(FOLDER, mainClassName, extraRules, app -> {
       CodeInspector codeInspector = new CodeInspector(app);
       ClassSubject clazz = checkClassIsKept(codeInspector, ex3.getClassName());
 
       MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature);
-      long ifzCount = Streams.stream(testMethod.iterateInstructions())
-          .filter(InstructionSubject::isIfEqz).count();
+      long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count();
       // !! operator inside explicit null check should be gone.
       // One explicit null-check as well as 4 bar? accesses.
       assertEquals(5, ifzCount);
     });
   }
-
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java
index 0cc2128..244199e 100644
--- a/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ReturnTypeTest.java
@@ -5,26 +5,17 @@
 package com.android.tools.r8.shaking;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
-import static junit.framework.TestCase.assertEquals;
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.OutputMode;
-import com.android.tools.r8.R8Command;
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.VmTestRunner;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApp;
+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.google.common.collect.ImmutableList;
-import java.nio.file.Path;
-import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 class B112517039ReturnType extends Exception {
 }
@@ -52,42 +43,49 @@
   }
 }
 
-@RunWith(VmTestRunner.class)
+@RunWith(Parameterized.class)
 public class ReturnTypeTest extends TestBase {
+  private static final String JAVA_OUTPUT = StringUtils.lines(
+      "Ewwo!",
+      "NullPointerException"
+  );
+  private static final Class<?> MAIN = B112517039Main.class;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimes().build();
+  }
+
+  private final TestParameters parameters;
+
+  public ReturnTypeTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
   @Test
-  public void testFromJavac() throws Exception {
-    String mainName = B112517039Main.class.getCanonicalName();
-    ProcessResult javaResult = ToolHelper.runJava(ToolHelper.getClassPathForTests(), mainName);
-    assertEquals(0, javaResult.exitCode);
-    assertThat(javaResult.stdout, containsString("Ewwo!"));
-    assertThat(javaResult.stdout, containsString("NullPointerException"));
+  public void testJVMOutput() throws Exception {
+    assumeTrue("Only run JVM reference on CF runtimes", parameters.isCfRuntime());
+    testForJvm()
+        .addTestClasspath()
+        .run(parameters.getRuntime(), MAIN)
+        .assertSuccessWithOutput(JAVA_OUTPUT);
+  }
 
-    List<String> config = ImmutableList.of(
-        "-printmapping",
-        "-keep class " + mainName + " {",
-        "  public static void main(...);",
-        "}"
-    );
-    R8Command.Builder builder = R8Command.builder();
-    builder.addProgramFiles(ToolHelper.getClassFilesForTestDirectory(
-        ToolHelper.getPackageDirectoryForTestPackage(B112517039Main.class.getPackage()),
-        path -> path.getFileName().toString().startsWith("B112517039")));
-    builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
-    builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel());
-    builder.addProguardConfiguration(config, Origin.unknown());
-    AndroidApp processedApp = ToolHelper.runR8(builder.build(), options -> {
-      options.enableInlining = false;
-    });
-
-    Path outDex = temp.getRoot().toPath().resolve("dex.zip");
-    processedApp.writeToZip(outDex, OutputMode.DexIndexed);
-    ProcessResult artResult = ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), mainName);
-    assertEquals(0, artResult.exitCode);
-    assertThat(javaResult.stdout, containsString("Ewwo!"));
-    assertThat(javaResult.stdout, containsString("NullPointerException"));
-
-    CodeInspector inspector = new CodeInspector(processedApp);
-    ClassSubject returnType = inspector.clazz(B112517039ReturnType.class);
-    assertThat(returnType, isRenamed());
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(
+            B112517039ReturnType.class, B112517039I.class, B112517039Caller.class, MAIN)
+        .addKeepMainRule(MAIN)
+        .setMinApi(parameters.getRuntime())
+        .addOptionsModification(o -> {
+          o.enableInlining = false;
+        })
+        .run(parameters.getRuntime(), MAIN)
+        .assertSuccessWithOutput(JAVA_OUTPUT)
+        .inspect(inspector -> {
+          ClassSubject returnType = inspector.clazz(B112517039ReturnType.class);
+          assertThat(returnType, isRenamed());
+        });
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java b/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
index 085ad52..3286e69 100644
--- a/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/array/DeadArrayLengthTest.java
@@ -4,10 +4,12 @@
 package com.android.tools.r8.shaking.array;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assume.assumeTrue;
 
+import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverPropagateValue;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -17,7 +19,6 @@
 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 com.google.common.collect.Streams;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -38,28 +39,31 @@
     this.parameters = parameters;
   }
 
-  private void inspect(CodeInspector inspector) {
+  private void inspect(CodeInspector inspector, boolean isR8) {
     ClassSubject main = inspector.clazz(MAIN);
     assertThat(main, isPresent());
 
     MethodSubject nonNull = main.uniqueMethodWithName("clearlyNonNull");
     assertThat(nonNull, isPresent());
-    assertEquals(
-        0,
-        Streams.stream(nonNull.iterateInstructions(InstructionSubject::isArrayLength)).count());
+    assertEquals(0, countArrayLength(nonNull));
 
     MethodSubject nullable = main.uniqueMethodWithName("isNullable");
-    assertThat(nullable, isPresent());
-    assertEquals(
-        1,
-        Streams.stream(nullable.iterateInstructions(InstructionSubject::isArrayLength)).count());
+    if (isR8) {
+      // Replaced with null-throwing code at the call site.
+      assertThat(nullable, not(isPresent()));
+    } else {
+      assertThat(nullable, isPresent());
+      assertEquals(1, countArrayLength(nullable));
+    }
 
     MethodSubject nullCheck = main.uniqueMethodWithName("afterNullCheck");
     assertThat(nullCheck, isPresent());
     // TODO(b/120920488): could be zero if we extend non-null to first dead code removal.
-    assertEquals(
-        1,
-        Streams.stream(nullCheck.iterateInstructions(InstructionSubject::isArrayLength)).count());
+    assertEquals(1, countArrayLength(nullCheck));
+  }
+
+  private long countArrayLength(MethodSubject method) {
+    return method.streamInstructions().filter(InstructionSubject::isArrayLength).count();
   }
 
   @Test
@@ -71,23 +75,25 @@
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutput(EXPECTED_OUTPUT)
-        .inspect(this::inspect);
+        .inspect(codeInspector -> inspect(codeInspector, false));
   }
 
   @Test
   public void testR8() throws Exception {
     testForR8(parameters.getBackend())
         .addProgramClasses(MAIN)
-        .addKeepClassAndMembersRules(MAIN)
+        .addKeepMainRule(MAIN)
+        .enableInliningAnnotations()
         .enableMemberValuePropagationAnnotations()
         .noMinification()
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
         .assertSuccessWithOutput(EXPECTED_OUTPUT)
-        .inspect(this::inspect);
+        .inspect(codeInspector -> inspect(codeInspector, true));
   }
 
   static class TestClass {
+    @NeverInline
     @NeverPropagateValue
     static int clearlyNonNull(int size) {
       int[] array = new int[size];
@@ -95,6 +101,7 @@
       return System.currentTimeMillis() > 0 ? 1 : -1;
     }
 
+    @NeverInline
     @NeverPropagateValue
     static int isNullable(int[] args) {
       // Not used, but can't be dead due to the potential NPE.
@@ -102,6 +109,7 @@
       return System.currentTimeMillis() > 0 ? 2 : -2;
     }
 
+    @NeverInline
     @NeverPropagateValue
     static int afterNullCheck(int[] args) {
       if (args != null) {