Enable D8Cf2Cf_L8Shrink

Enable the shrinking pipeline of Google 3
on all tests running Cf2Cf

Bug: b:231287675
Change-Id: I4fd17f467c1bdf7ccc26d226169db3f7bf90e125
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CompilationSpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CompilationSpecification.java
index 0efcc59..3aecfba 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CompilationSpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/CompilationSpecification.java
@@ -19,14 +19,12 @@
   R8_L8SHRINK(true, true, false, RELEASE),
   // The D8CFTOCF specifications can run either in CF or be dexed afterwards.
   D8CF2CF_L8DEBUG(false, false, true, DEBUG),
-  // D8CF2CF_L8SHRINK is to be implemented (Only the dex back-end outputs the keep rule).
   D8CF2CF_L8SHRINK(false, true, true, RELEASE);
 
   public static Set<CompilationSpecification> DEFAULT_SPECIFICATIONS =
       ImmutableSet.of(D8_L8DEBUG, D8_L8SHRINK, R8_L8SHRINK);
-  // Add D8CF2CF_L8SHRINK when tracereference is supported.
   public static Set<CompilationSpecification> SPECIFICATIONS_WITH_CF2CF =
-      ImmutableSet.of(D8_L8DEBUG, D8_L8SHRINK, R8_L8SHRINK, D8CF2CF_L8DEBUG);
+      ImmutableSet.of(D8_L8DEBUG, D8_L8SHRINK, R8_L8SHRINK, D8CF2CF_L8DEBUG, D8CF2CF_L8SHRINK);
 
   private final boolean programShrink;
   private final boolean l8Shrink;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
index 3588344..7e11cc5 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestBuilder.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.test;
 
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.D8CF2CF_L8SHRINK;
+
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.D8TestCompileResult;
 import com.android.tools.r8.FeatureSplit;
@@ -21,10 +23,16 @@
 import com.android.tools.r8.TestRuntime;
 import com.android.tools.r8.TestShrinkerBuilder;
 import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase.KeepRuleConsumer;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser;
+import com.android.tools.r8.tracereferences.TraceReferences;
+import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.base.Charsets;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -37,7 +45,8 @@
   private final LibraryDesugaringSpecification libraryDesugaringSpecification;
   private final CompilationSpecification compilationSpecification;
   private final TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> builder;
-  private final L8TestBuilder l8Builder;
+  private Consumer<InternalOptions> l8OptionModifier = ConsumerUtils.emptyConsumer();
+  private boolean l8FinalPrefixVerification = true;
 
   private CustomLibrarySpecification customLibrarySpecification = null;
   private TestingKeepRuleConsumer keepRuleConsumer = null;
@@ -52,21 +61,21 @@
     this.libraryDesugaringSpecification = libraryDesugaringSpecification;
     this.compilationSpecification = runSpecification;
     this.builder = generateBuilder();
-    this.l8Builder = generateL8Builder();
     setUp();
   }
 
   private void setUp() {
     builder
         .addLibraryFiles(libraryDesugaringSpecification.getLibraryFiles())
-        .setMinApi(parameters.getApiLevel());
+        .setMinApi(parameters.getApiLevel())
+        .setMode(compilationSpecification.getProgramCompilationMode());
     LibraryDesugaringTestConfiguration.Builder libraryConfBuilder =
         LibraryDesugaringTestConfiguration.builder()
             .setMinApi(parameters.getApiLevel())
             .addDesugaredLibraryConfiguration(
                 StringResource.fromFile(libraryDesugaringSpecification.getSpecification()))
             .dontAddRunClasspath();
-    if (compilationSpecification.isL8Shrink()) {
+    if (compilationSpecification.isL8Shrink() && !compilationSpecification.isCfToCf()) {
       keepRuleConsumer = new TestingKeepRuleConsumer();
       libraryConfBuilder.setKeepRuleConsumer(keepRuleConsumer);
     }
@@ -76,6 +85,10 @@
   private TestCompilerBuilder<?, ?, ?, ? extends SingleTestRunResult<?>, ?> generateBuilder() {
     if (compilationSpecification.isCfToCf()) {
       assert !compilationSpecification.isProgramShrink();
+      if (compilationSpecification.isL8Shrink()) {
+        // L8 with Cf backend and shrinking is not a supported pipeline.
+        Assume.assumeTrue(parameters.getBackend().isDex());
+      }
       return test.testForD8(Backend.CF);
     }
     // Cf back-end is only allowed in Cf to cf compilations.
@@ -86,10 +99,6 @@
     return test.testForD8(Backend.DEX);
   }
 
-  private L8TestBuilder generateL8Builder() {
-    return test.testForL8(parameters.getApiLevel(), parameters.getBackend());
-  }
-
   public DesugaredLibraryTestBuilder<T> setCustomLibrarySpecification(
       CustomLibrarySpecification customLibrarySpecification) {
     this.customLibrarySpecification = customLibrarySpecification;
@@ -99,7 +108,7 @@
 
   public DesugaredLibraryTestBuilder<T> addL8OptionsModification(
       Consumer<InternalOptions> optionModifier) {
-    l8Builder.addOptionsModifier(optionModifier);
+    l8OptionModifier = l8OptionModifier.andThen(optionModifier);
     return this;
   }
 
@@ -147,7 +156,7 @@
   }
 
   public DesugaredLibraryTestBuilder<T> ignoreL8FinalPrefixVerification() {
-    l8Builder.ignoreFinalPrefixVerification();
+    l8FinalPrefixVerification = false;
     return this;
   }
 
@@ -244,7 +253,8 @@
   }
 
   public DesugaredLibraryTestBuilder<T> disableL8AnnotationRemoval() {
-    l8Builder.setDisableL8AnnotationRemoval(true);
+    l8OptionModifier =
+        l8OptionModifier.andThen(options -> options.disableL8AnnotationRemoval = true);
     return this;
   }
 
@@ -262,8 +272,7 @@
 
   private DesugaredLibraryTestCompileResult<T> internalCompile(
       TestCompileResult<?, ? extends SingleTestRunResult<?>> compile) throws Exception {
-    String keepRule = keepRuleConsumer == null ? null : keepRuleConsumer.get();
-    L8TestCompileResult l8Compile = compileDesugaredLibrary(keepRule);
+    L8TestCompileResult l8Compile = compileDesugaredLibrary(compile, keepRuleConsumer);
     D8TestCompileResult customLibCompile = compileCustomLib();
     return new DesugaredLibraryTestCompileResult<>(
         test,
@@ -285,15 +294,69 @@
         .compile();
   }
 
+  private L8TestCompileResult compileDesugaredLibrary(
+      TestCompileResult<?, ? extends SingleTestRunResult<?>> compile,
+      KeepRuleConsumer keepRuleConsumer)
+      throws Exception {
+    if (!compilationSpecification.isL8Shrink()) {
+      return compileDesugaredLibrary(null);
+    }
+    if (!compilationSpecification.isCfToCf()) {
+      // When going to dex we can get the generated keep rule through the keep rule consumer.
+      assert keepRuleConsumer != null;
+      return compileDesugaredLibrary(keepRuleConsumer.get());
+    }
+    // In D8CF2CF_L8SHRINK, we use trace reference to extract the keep rules.
+    assert compilationSpecification == D8CF2CF_L8SHRINK;
+    L8TestCompileResult nonShrunk =
+        test.testForL8(parameters.getApiLevel(), Backend.CF)
+            .apply(libraryDesugaringSpecification::configureL8TestBuilder)
+            .apply(this::configure)
+            .compile();
+    String keepRules =
+        collectKeepRulesWithTraceReferences(compile.writeToZip(), nonShrunk.writeToZip());
+    return compileDesugaredLibrary(keepRules);
+  }
+
   private L8TestCompileResult compileDesugaredLibrary(String keepRule) throws Exception {
-    return l8Builder
+    assert !compilationSpecification.isL8Shrink() || keepRule != null;
+    return test.testForL8(parameters.getApiLevel(), parameters.getBackend())
         .apply(
             b ->
                 libraryDesugaringSpecification.configureL8TestBuilder(
                     b, compilationSpecification.isL8Shrink(), keepRule))
+        .apply(this::configure)
         .compile();
   }
 
+  private void configure(L8TestBuilder l8Builder) {
+    l8Builder
+        .applyIf(!l8FinalPrefixVerification, L8TestBuilder::ignoreFinalPrefixVerification)
+        .addOptionsModifier(l8OptionModifier);
+  }
+
+  public String collectKeepRulesWithTraceReferences(
+      Path desugaredProgramClassFile, Path desugaredLibraryClassFile) throws Exception {
+    Path generatedKeepRules = test.temp.newFile().toPath();
+    ArrayList<String> args = new ArrayList<>();
+    args.add("--keep-rules");
+    for (Path libraryFile : libraryDesugaringSpecification.getLibraryFiles()) {
+      args.add("--lib");
+      args.add(libraryFile.toString());
+    }
+    args.add("--target");
+    args.add(desugaredLibraryClassFile.toString());
+    args.add("--source");
+    args.add(desugaredProgramClassFile.toString());
+    args.add("--output");
+    args.add(generatedKeepRules.toString());
+    args.add("--map-diagnostics");
+    args.add("error");
+    args.add("info");
+    TraceReferences.run(args.toArray(new String[0]));
+    return FileUtils.readTextFile(generatedKeepRules, Charsets.UTF_8);
+  }
+
   public SingleTestRunResult<?> run(TestRuntime runtime, Class<?> mainClass, String... args)
       throws Exception {
     return compile().run(runtime, mainClass.getTypeName(), args);
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestCompileResult.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestCompileResult.java
index 3416761..bd11465 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/test/DesugaredLibraryTestCompileResult.java
@@ -132,6 +132,7 @@
     return test.testForD8()
         .addProgramFiles(this.compileResult.writeToZip())
         .setMinApi(parameters.getApiLevel())
+        .setMode(compilationSpecification.getProgramCompilationMode())
         .disableDesugaring()
         .compile();
   }