Fix performance of DesugaredLibContentTest

- Split test in 2 (InvokeAllResolve and content)
- Fix the repeated instantiation of DexItemFactory (15 seconds)

Bug: b/270029504
Change-Id: I9092751105c3ddc118628a27dc1204774baa5638
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
index 84592ab..387933f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryContentTest.java
@@ -15,42 +15,18 @@
 import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
 import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
-import com.android.tools.r8.dex.ApplicationReader;
-import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.graph.MethodResolutionResult;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
-import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
 import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidApp;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.Pair;
-import com.android.tools.r8.utils.ThreadUtils;
-import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import org.hamcrest.CoreMatchers;
 import org.junit.Assume;
 import org.junit.Test;
@@ -61,34 +37,6 @@
 @RunWith(Parameterized.class)
 public class DesugaredLibraryContentTest extends DesugaredLibraryTestBase {
 
-  // The class sun.misc.Unsafe is runnable on Android despite not being in android.jar.
-  private static final Set<String> ALLOWED_MISSING_HOLDER = ImmutableSet.of("sun.misc.Unsafe");
-  private static final Set<String> ALLOWED_MISSING_METHOD =
-      ImmutableSet.of(
-          // The takeWhile/dropWhile methods are present in the wrappers but not yet present on
-          // android.jar
-          // leading to NoSuchMethod errors, yet, we keep them for subsequent android versions.
-          "java.util.stream.IntStream"
-              + " java.util.stream.IntStream.dropWhile(java.util.function.IntPredicate)",
-          "java.util.stream.Stream java.util.stream.Stream.takeWhile(java.util.function.Predicate)",
-          "java.util.stream.LongStream"
-              + " java.util.stream.LongStream.dropWhile(java.util.function.LongPredicate)",
-          "java.util.stream.DoubleStream"
-              + " java.util.stream.DoubleStream.takeWhile(java.util.function.DoublePredicate)",
-          "java.util.stream.IntStream"
-              + " java.util.stream.IntStream.takeWhile(java.util.function.IntPredicate)",
-          "java.util.stream.Stream java.util.stream.Stream.dropWhile(java.util.function.Predicate)",
-          "java.util.stream.LongStream"
-              + " java.util.stream.LongStream.takeWhile(java.util.function.LongPredicate)",
-          "java.util.stream.DoubleStream"
-              + " java.util.stream.DoubleStream.dropWhile(java.util.function.DoublePredicate)",
-          // FileStore.getBlockSize() was added in 33 which confuses the required library (30).
-          "long java.nio.file.FileStore.getBlockSize()",
-          // The call is present but unreachable above 26.
-          "java.nio.channels.FileChannel"
-              + " java.nio.channels.DesugarChannels.openEmulatedFileChannel(java.nio.file.Path,"
-              + " java.util.Set, java.nio.file.attribute.FileAttribute[])");
-
   private final TestParameters parameters;
   private final CompilationSpecification compilationSpecification;
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
@@ -117,83 +65,15 @@
         .apply(libraryDesugaringSpecification::configureL8TestBuilder)
         .compile()
         .assertNoMessages()
-        .inspect(this::assertCorrect)
-        .inspect(this::assertAllInvokeResolve);
-  }
-
-  private void assertAllInvokeResolve(CodeInspector inspector) throws IOException {
-    AndroidApp build =
-        AndroidApp.builder()
-            .addLibraryFiles(libraryDesugaringSpecification.getLibraryFiles())
-            .build();
-    InternalOptions options = inspector.getApplication().options;
-    DirectMappedDexApplication libHolder =
-        new ApplicationReader(build, options, Timing.empty()).read().toDirect();
-    DirectMappedDexApplication finalApp =
-        inspector
-            .getApplication()
-            .toDirect()
-            .builder()
-            .replaceLibraryClasses(libHolder.libraryClasses())
-            .build();
-    AppInfoWithClassHierarchy appInfo =
-        AppView.createForD8(
-                AppInfo.createInitialAppInfo(
-                    finalApp, GlobalSyntheticsStrategy.forNonSynthesizing()))
-            .appInfoForDesugaring();
-    List<DexMethod> backports =
-        BackportedMethodRewriter.generateListOfBackportedMethods(
-            build, options, ThreadUtils.getExecutorService(1));
-    Map<DexMethod, Object> failures = new IdentityHashMap<>();
-    for (FoundClassSubject clazz : inspector.allClasses()) {
-      if (clazz.toString().startsWith("j$.sun.nio.cs.UTF_8")
-          && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)) {
-        // At high API level, the class UTF_8 is there just for resolution, the field access is
-        // retargeted and the code is unused so it's ok if it does not resolve.
-        continue;
-      }
-      for (FoundMethodSubject method : clazz.allMethods()) {
-        if (method.hasCode()) {
-          for (InstructionSubject instruction : method.instructions(InstructionSubject::isInvoke)) {
-            assertInvokeResolution(instruction, appInfo, method, failures);
-          }
-        }
-      }
-    }
-    for (DexMethod dexMethod : new HashSet<>(failures.keySet())) {
-      if (ALLOWED_MISSING_HOLDER.contains(dexMethod.getHolderType().toString())) {
-        failures.remove(dexMethod);
-      } else if (ALLOWED_MISSING_METHOD.contains(dexMethod.toString())) {
-        failures.remove(dexMethod);
-      } else if (backports.contains(dexMethod)) {
-        failures.remove(dexMethod);
-      }
-    }
-    assertTrue(failures.isEmpty());
-  }
-
-  private void assertInvokeResolution(
-      InstructionSubject instruction,
-      AppInfoWithClassHierarchy appInfo,
-      FoundMethodSubject context,
-      Map<DexMethod, Object> failures) {
-    DexMethod method = instruction.getMethod();
-    assert method != null;
-    MethodResolutionResult methodResolutionResult =
-        appInfo.unsafeResolveMethodDueToDexFormatLegacy(method);
-    if (methodResolutionResult.isFailedResolution()) {
-      failures.put(method, new Pair(context, methodResolutionResult));
-    }
+        .inspect(this::assertCorrect);
   }
 
   @Test
   public void testDesugaredLibraryContentWithCoreLambdaStubsAsProgram() throws Exception {
     Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
-    ArrayList<Path> coreLambdaStubs = new ArrayList<>();
-    coreLambdaStubs.add(ToolHelper.getCoreLambdaStubs());
     testForL8(parameters.getApiLevel())
         .apply(libraryDesugaringSpecification::configureL8TestBuilder)
-        .addProgramFiles(coreLambdaStubs)
+        .addProgramFiles(ToolHelper.getCoreLambdaStubs())
         .compile()
         .inspect(this::assertCorrect);
   }
@@ -240,18 +120,20 @@
       assertThat(inspector.clazz("j$.util.function.Function"), isPresent());
     }
     if (parameters.getApiLevel().isLessThan(AndroidApiLevel.K)) {
-      inspector.forAllClasses(clazz -> clazz.forAllMethods(this::assertNoSupressedInvocations));
+      inspector.forAllClasses(
+          clazz ->
+              clazz.forAllMethods(m -> assertNoSupressedInvocations(m, inspector.getFactory())));
     }
   }
 
-  private void assertNoSupressedInvocations(FoundMethodSubject method) {
+  private void assertNoSupressedInvocations(
+      FoundMethodSubject method, DexItemFactory dexItemFactory) {
     if (method.isAbstract()) {
       return;
     }
     for (InstructionSubject instruction : method.instructions()) {
       if (instruction.isInvoke() && instruction.getMethod() != null) {
-        assertNotEquals(
-            instruction.getMethod(), new DexItemFactory().throwableMethods.addSuppressed);
+        assertNotEquals(instruction.getMethod(), dexItemFactory.throwableMethods.addSuppressed);
       }
     }
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvokeAllResolveTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvokeAllResolveTest.java
new file mode 100644
index 0000000..ef137bc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryInvokeAllResolveTest.java
@@ -0,0 +1,180 @@
+// Copyright (c) 2023, 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.desugar.desugaredlibrary;
+
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8_L8DEBUG;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.ThreadUtils;
+import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class DesugaredLibraryInvokeAllResolveTest extends DesugaredLibraryTestBase {
+
+  // The class sun.misc.Unsafe is runnable on Android despite not being in android.jar.
+  private static final Set<String> ALLOWED_MISSING_HOLDER = ImmutableSet.of("sun.misc.Unsafe");
+  private static final Set<String> ALLOWED_MISSING_METHOD =
+      ImmutableSet.of(
+          // The takeWhile/dropWhile methods are present in the wrappers but not yet present on
+          // android.jar
+          // leading to NoSuchMethod errors, yet, we keep them for subsequent android versions.
+          "java.util.stream.IntStream"
+              + " java.util.stream.IntStream.dropWhile(java.util.function.IntPredicate)",
+          "java.util.stream.Stream java.util.stream.Stream.takeWhile(java.util.function.Predicate)",
+          "java.util.stream.LongStream"
+              + " java.util.stream.LongStream.dropWhile(java.util.function.LongPredicate)",
+          "java.util.stream.DoubleStream"
+              + " java.util.stream.DoubleStream.takeWhile(java.util.function.DoublePredicate)",
+          "java.util.stream.IntStream"
+              + " java.util.stream.IntStream.takeWhile(java.util.function.IntPredicate)",
+          "java.util.stream.Stream java.util.stream.Stream.dropWhile(java.util.function.Predicate)",
+          "java.util.stream.LongStream"
+              + " java.util.stream.LongStream.takeWhile(java.util.function.LongPredicate)",
+          "java.util.stream.DoubleStream"
+              + " java.util.stream.DoubleStream.dropWhile(java.util.function.DoublePredicate)",
+          // FileStore.getBlockSize() was added in 33 which confuses the required library (30).
+          "long java.nio.file.FileStore.getBlockSize()",
+          // The call is present but unreachable above 26.
+          "java.nio.channels.FileChannel"
+              + " java.nio.channels.DesugarChannels.openEmulatedFileChannel(java.nio.file.Path,"
+              + " java.util.Set, java.nio.file.attribute.FileAttribute[])");
+
+  private final TestParameters parameters;
+  private final CompilationSpecification compilationSpecification;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+
+  @Parameters(name = "{0}, spec: {1}, {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
+        ImmutableList.of(JDK8, JDK11, JDK11_PATH),
+        ImmutableList.of(D8_L8DEBUG));
+  }
+
+  public DesugaredLibraryInvokeAllResolveTest(
+      TestParameters parameters,
+      LibraryDesugaringSpecification libraryDesugaringSpecification,
+      CompilationSpecification compilationSpecification) {
+    this.parameters = parameters;
+    this.compilationSpecification = compilationSpecification;
+    this.libraryDesugaringSpecification = libraryDesugaringSpecification;
+  }
+
+  @Test
+  public void testDesugaredLibraryContent() throws Exception {
+    Assume.assumeTrue(libraryDesugaringSpecification.hasAnyDesugaring(parameters));
+    testForL8(parameters.getApiLevel())
+        .apply(libraryDesugaringSpecification::configureL8TestBuilder)
+        .compile()
+        .assertNoMessages()
+        .inspect(this::assertAllInvokeResolve);
+  }
+
+  private void assertAllInvokeResolve(CodeInspector inspector) throws IOException {
+    AndroidApp build =
+        AndroidApp.builder()
+            .addLibraryFiles(libraryDesugaringSpecification.getLibraryFiles())
+            .build();
+    InternalOptions options = inspector.getApplication().options;
+    DirectMappedDexApplication libHolder =
+        new ApplicationReader(build, options, Timing.empty()).read().toDirect();
+    DirectMappedDexApplication finalApp =
+        inspector
+            .getApplication()
+            .toDirect()
+            .builder()
+            .replaceLibraryClasses(libHolder.libraryClasses())
+            .build();
+    AppInfoWithClassHierarchy appInfo =
+        AppView.createForD8(
+                AppInfo.createInitialAppInfo(
+                    finalApp, GlobalSyntheticsStrategy.forNonSynthesizing()))
+            .appInfoForDesugaring();
+    List<DexMethod> backports =
+        BackportedMethodRewriter.generateListOfBackportedMethods(
+            build, options, ThreadUtils.getExecutorService(1));
+    Map<DexMethod, Object> failures = new IdentityHashMap<>();
+    for (FoundClassSubject clazz : inspector.allClasses()) {
+      if (clazz.toString().startsWith("j$.sun.nio.cs.UTF_8")
+          && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)) {
+        // At high API level, the class UTF_8 is there just for resolution, the field access is
+        // retargeted and the code is unused so it's ok if it does not resolve.
+        continue;
+      }
+      for (FoundMethodSubject method : clazz.allMethods()) {
+        if (method.hasCode()) {
+          for (InstructionSubject instruction : method.instructions(InstructionSubject::isInvoke)) {
+            assertInvokeResolution(instruction, appInfo, method, failures);
+          }
+        }
+      }
+    }
+    for (DexMethod dexMethod : new HashSet<>(failures.keySet())) {
+      if (ALLOWED_MISSING_HOLDER.contains(dexMethod.getHolderType().toString())) {
+        failures.remove(dexMethod);
+      } else if (ALLOWED_MISSING_METHOD.contains(dexMethod.toString())) {
+        failures.remove(dexMethod);
+      } else if (backports.contains(dexMethod)) {
+        failures.remove(dexMethod);
+      }
+    }
+    assertTrue(failures.isEmpty());
+  }
+
+  private void assertInvokeResolution(
+      InstructionSubject instruction,
+      AppInfoWithClassHierarchy appInfo,
+      FoundMethodSubject context,
+      Map<DexMethod, Object> failures) {
+    DexMethod method = instruction.getMethod();
+    assert method != null;
+    MethodResolutionResult methodResolutionResult =
+        appInfo.unsafeResolveMethodDueToDexFormatLegacy(method);
+    if (methodResolutionResult.isFailedResolution()) {
+      failures.put(method, new Pair<>(context, methodResolutionResult));
+    }
+  }
+
+  static class GuineaPig {
+
+    public static void main(String[] args) {}
+  }
+}