Refactor desugar test builder

Bug: 147485959
Change-Id: I063dda44f1afa244640e90af48b8d5a06d1f73c4
diff --git a/src/test/java/com/android/tools/r8/DesugarTestBuilder.java b/src/test/java/com/android/tools/r8/DesugarTestBuilder.java
new file mode 100644
index 0000000..33ef940
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/DesugarTestBuilder.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, 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;
+
+import com.android.tools.r8.utils.Pair;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+public class DesugarTestBuilder
+    extends TestBuilderCollection<
+        DesugarTestConfiguration, DesugarTestRunResult, DesugarTestBuilder> {
+
+  public static DesugarTestBuilder create(
+      TestState state,
+      List<Pair<DesugarTestConfiguration, TestBuilder<? extends TestRunResult<?>, ?>>>
+          testBuilders) {
+    return new DesugarTestBuilder(state, testBuilders);
+  }
+
+  private DesugarTestBuilder(
+      TestState state,
+      List<Pair<DesugarTestConfiguration, TestBuilder<? extends TestRunResult<?>, ?>>> builders) {
+    super(state, builders);
+  }
+
+  @Override
+  DesugarTestBuilder self() {
+    return this;
+  }
+
+  @Override
+  public DesugarTestRunResult run(TestRuntime runtime, String mainClass, String... args)
+      throws CompilationFailedException, ExecutionException, IOException {
+    List<Pair<DesugarTestConfiguration, TestRunResult<?>>> runs = new ArrayList<>(builders.size());
+    for (Pair<DesugarTestConfiguration, TestBuilder<? extends TestRunResult<?>, ?>> builder :
+        builders) {
+      runs.add(new Pair<>(builder.getFirst(), builder.getSecond().run(runtime, mainClass, args)));
+    }
+    return DesugarTestRunResult.create(runs);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/DesugarTestConfiguration.java b/src/test/java/com/android/tools/r8/DesugarTestConfiguration.java
new file mode 100644
index 0000000..28ce5c7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/DesugarTestConfiguration.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, 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;
+
+/** The configurations for a desugar test */
+public enum DesugarTestConfiguration {
+  // Javac generated code with no desugaring (reference run).
+  JAVAC,
+  // Javac generated code with desugaring to class file.
+  D8_CF,
+  // Javac generated code with desugaring to DEX.
+  D8_DEX,
+  // Javac generated code with desugaring to class file and then compiled to DEX without desugaring.
+  D8_CF_D8_DEX
+}
diff --git a/src/test/java/com/android/tools/r8/DesugarTestRunResult.java b/src/test/java/com/android/tools/r8/DesugarTestRunResult.java
new file mode 100644
index 0000000..4bffdfa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/DesugarTestRunResult.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, 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;
+
+import com.android.tools.r8.utils.Pair;
+import java.util.List;
+
+public class DesugarTestRunResult
+    extends TestRunResultCollection<DesugarTestConfiguration, DesugarTestRunResult> {
+
+  public static DesugarTestRunResult create(
+      List<Pair<DesugarTestConfiguration, TestRunResult<?>>> runs) {
+    assert !runs.isEmpty();
+    return new DesugarTestRunResult(runs);
+  }
+
+  private DesugarTestRunResult(List<Pair<DesugarTestConfiguration, TestRunResult<?>>> runs) {
+    super(runs);
+  }
+
+  @Override
+  DesugarTestRunResult self() {
+    return this;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 342920c..b548650 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -220,28 +220,28 @@
     return testForRuntime(parameters.getRuntime(), parameters.getApiLevel());
   }
 
-  public TestBuilder<? extends TestRunResult<?>, ?> testForDesugaring(TestParameters parameters) {
+  public TestBuilder<DesugarTestRunResult, ?> testForDesugaring(TestParameters parameters) {
     return testForDesugaring(
         parameters.getRuntime().getBackend(), parameters.getApiLevel(), o -> {});
   }
 
-  public TestBuilder<? extends TestRunResult<?>, ?> testForDesugaring(
+  public TestBuilder<DesugarTestRunResult, ?> testForDesugaring(
       TestParameters parameters, Consumer<InternalOptions> optionsModification) {
     return testForDesugaring(
         parameters.getRuntime().getBackend(), parameters.getApiLevel(), optionsModification);
   }
 
-  private TestBuilder<? extends TestRunResult<?>, ?> testForDesugaring(
+  private TestBuilder<DesugarTestRunResult, ?> testForDesugaring(
       Backend backend, AndroidApiLevel apiLevel, Consumer<InternalOptions> optionsModification) {
     assert apiLevel != null : "No API level. Add .withAllApiLevelsAlsoForCf() to test parameters?";
     TestState state = new TestState(temp);
-    List<Pair<String, TestBuilder<? extends TestRunResult<?>, ?>>> builders;
+    List<Pair<DesugarTestConfiguration, TestBuilder<? extends TestRunResult<?>, ?>>> builders;
     if (backend == Backend.CF) {
       builders =
           ImmutableList.of(
-              new Pair<>("JAVAC", JvmTestBuilder.create(state)),
+              new Pair<>(DesugarTestConfiguration.JAVAC, JvmTestBuilder.create(state)),
               new Pair<>(
-                  "D8/CF",
+                  DesugarTestConfiguration.D8_CF,
                   D8TestBuilder.create(state, Backend.CF)
                       .setMinApi(apiLevel)
                       .addOptionsModification(optionsModification)));
@@ -250,16 +250,16 @@
       builders =
           ImmutableList.of(
               new Pair<>(
-                  "D8/DEX",
+                  DesugarTestConfiguration.D8_DEX,
                   D8TestBuilder.create(state, Backend.DEX)
                       .setMinApi(apiLevel)
                       .addOptionsModification(optionsModification)),
               new Pair<>(
-                  "D8/DEX o D8/CF",
+                  DesugarTestConfiguration.D8_CF_D8_DEX,
                   IntermediateCfD8TestBuilder.create(state, apiLevel)
                       .addOptionsModification(optionsModification)));
     }
-    return TestBuilderCollection.create(state, builders);
+    return DesugarTestBuilder.create(state, builders);
   }
 
   public ProguardTestBuilder testForProguard() {
diff --git a/src/test/java/com/android/tools/r8/TestBuilderCollection.java b/src/test/java/com/android/tools/r8/TestBuilderCollection.java
index a537aea..0192832 100644
--- a/src/test/java/com/android/tools/r8/TestBuilderCollection.java
+++ b/src/test/java/com/android/tools/r8/TestBuilderCollection.java
@@ -6,49 +6,28 @@
 import com.android.tools.r8.debug.DebugTestConfig;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.utils.Pair;
-import java.io.IOException;
 import java.nio.file.Path;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
 
 /** Abstraction to allow setup and execution of multiple test builders. */
-public class TestBuilderCollection
-    extends TestBuilder<TestRunResultCollection, TestBuilderCollection> {
+public abstract class TestBuilderCollection<
+        C extends Enum<C>,
+        RR extends TestRunResultCollection<C, RR>,
+        T extends TestBuilderCollection<C, RR, T>>
+    extends TestBuilder<RR, T> {
 
-  public static TestBuilderCollection create(
-      TestState state,
-      List<Pair<String, TestBuilder<? extends TestRunResult<?>, ?>>> testBuilders) {
-    return new TestBuilderCollection(state, testBuilders);
-  }
+  final List<Pair<C, TestBuilder<? extends TestRunResult<?>, ?>>> builders;
 
-  private final List<Pair<String, TestBuilder<? extends TestRunResult<?>, ?>>> builders;
-
-  private TestBuilderCollection(
-      TestState state, List<Pair<String, TestBuilder<? extends TestRunResult<?>, ?>>> builders) {
+  TestBuilderCollection(
+      TestState state, List<Pair<C, TestBuilder<? extends TestRunResult<?>, ?>>> builders) {
     super(state);
     assert !builders.isEmpty();
     this.builders = builders;
   }
 
-  @Override
-  TestBuilderCollection self() {
-    return this;
-  }
-
-  @Override
-  public TestRunResultCollection run(TestRuntime runtime, String mainClass, String... args)
-      throws CompilationFailedException, ExecutionException, IOException {
-    List<Pair<String, TestRunResult<?>>> runs = new ArrayList<>(builders.size());
-    for (Pair<String, TestBuilder<? extends TestRunResult<?>, ?>> builder : builders) {
-      runs.add(new Pair<>(builder.getFirst(), builder.getSecond().run(runtime, mainClass, args)));
-    }
-    return TestRunResultCollection.create(runs);
-  }
-
-  private TestBuilderCollection forEach(Consumer<TestBuilder<? extends TestRunResult<?>, ?>> fn) {
+  private T forEach(Consumer<TestBuilder<? extends TestRunResult<?>, ?>> fn) {
     builders.forEach(b -> fn.accept(b.getSecond()));
     return self();
   }
@@ -59,42 +38,42 @@
   }
 
   @Override
-  public TestBuilderCollection addProgramFiles(Collection<Path> files) {
+  public T addProgramFiles(Collection<Path> files) {
     return forEach(b -> b.addProgramFiles(files));
   }
 
   @Override
-  public TestBuilderCollection addProgramClassFileData(Collection<byte[]> classes) {
+  public T addProgramClassFileData(Collection<byte[]> classes) {
     return forEach(b -> b.addProgramClassFileData(classes));
   }
 
   @Override
-  public TestBuilderCollection addProgramDexFileData(Collection<byte[]> data) {
+  public T addProgramDexFileData(Collection<byte[]> data) {
     return forEach(b -> b.addProgramDexFileData(data));
   }
 
   @Override
-  public TestBuilderCollection addLibraryFiles(Collection<Path> files) {
+  public T addLibraryFiles(Collection<Path> files) {
     return forEach(b -> b.addLibraryFiles(files));
   }
 
   @Override
-  public TestBuilderCollection addLibraryClasses(Collection<Class<?>> classes) {
+  public T addLibraryClasses(Collection<Class<?>> classes) {
     return forEach(b -> b.addLibraryClasses(classes));
   }
 
   @Override
-  public TestBuilderCollection addClasspathClasses(Collection<Class<?>> classes) {
+  public T addClasspathClasses(Collection<Class<?>> classes) {
     return forEach(b -> b.addClasspathClasses(classes));
   }
 
   @Override
-  public TestBuilderCollection addClasspathFiles(Collection<Path> files) {
+  public T addClasspathFiles(Collection<Path> files) {
     return forEach(b -> b.addClasspathFiles(files));
   }
 
   @Override
-  public TestBuilderCollection addRunClasspathFiles(Collection<Path> files) {
+  public T addRunClasspathFiles(Collection<Path> files) {
     return forEach(b -> b.addRunClasspathFiles(files));
   }
 }
diff --git a/src/test/java/com/android/tools/r8/TestRunResultCollection.java b/src/test/java/com/android/tools/r8/TestRunResultCollection.java
index af4256a..e5f3c44 100644
--- a/src/test/java/com/android/tools/r8/TestRunResultCollection.java
+++ b/src/test/java/com/android/tools/r8/TestRunResultCollection.java
@@ -11,65 +11,66 @@
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import org.hamcrest.Matcher;
 
 /** Checking container for checking the same properties of multiple run results. */
-public class TestRunResultCollection extends TestRunResult<TestRunResultCollection> {
+public abstract class TestRunResultCollection<
+        C extends Enum<C>, RR extends TestRunResultCollection<C, RR>>
+    extends TestRunResult<RR> {
 
-  public static TestRunResultCollection create(List<Pair<String, TestRunResult<?>>> runs) {
-    assert !runs.isEmpty();
-    return new TestRunResultCollection(runs);
-  }
+  private final List<Pair<C, TestRunResult<?>>> runs;
 
-  private final List<Pair<String, TestRunResult<?>>> runs;
-
-  public TestRunResultCollection(List<Pair<String, TestRunResult<?>>> runs) {
+  public TestRunResultCollection(List<Pair<C, TestRunResult<?>>> runs) {
     this.runs = runs;
   }
 
-  @Override
-  TestRunResultCollection self() {
-    return this;
-  }
-
-  private TestRunResultCollection forEach(Consumer<TestRunResult<?>> fn) {
+  private RR forEach(Consumer<TestRunResult<?>> fn) {
     runs.forEach(r -> fn.accept(r.getSecond()));
     return self();
   }
 
   @Override
-  public TestRunResultCollection assertSuccess() {
+  public RR assertSuccess() {
     return forEach(TestRunResult::assertSuccess);
   }
 
   @Override
-  public TestRunResultCollection assertFailure() {
+  public RR assertFailure() {
     return forEach(TestRunResult::assertFailure);
   }
 
   @Override
-  public TestRunResultCollection assertStdoutMatches(Matcher<String> matcher) {
+  public RR assertStdoutMatches(Matcher<String> matcher) {
     return forEach(r -> r.assertStdoutMatches(matcher));
   }
 
   @Override
-  public TestRunResultCollection assertStderrMatches(Matcher<String> matcher) {
+  public RR assertStderrMatches(Matcher<String> matcher) {
     return forEach(r -> r.assertStderrMatches(matcher));
   }
 
   @Override
-  public <E extends Throwable> TestRunResultCollection inspect(
-      ThrowingConsumer<CodeInspector, E> consumer) throws IOException, ExecutionException, E {
-    for (Pair<String, TestRunResult<?>> run : runs) {
-      run.getSecond().inspect(consumer);
+  public <E extends Throwable> RR inspect(ThrowingConsumer<CodeInspector, E> consumer)
+      throws IOException, ExecutionException, E {
+    return inspect(c -> true, consumer);
+  }
+
+  public <E extends Throwable> RR inspect(
+      Predicate<C> filter, ThrowingConsumer<CodeInspector, E> consumer)
+      throws IOException, ExecutionException, E {
+    for (Pair<C, TestRunResult<?>> run : runs) {
+      if (filter.test(run.getFirst())) {
+        run.getSecond().inspect(consumer);
+      }
     }
     return self();
   }
 
   @Override
-  public TestRunResultCollection disassemble() throws IOException, ExecutionException {
-    for (Pair<String, TestRunResult<?>> run : runs) {
-      String name = run.getFirst();
+  public RR disassemble() throws IOException, ExecutionException {
+    for (Pair<C, TestRunResult<?>> run : runs) {
+      String name = run.getFirst().name();
       System.out.println(name + " " + Strings.repeat("=", 80 - name.length() - 1));
       run.getSecond().disassemble();
     }