Add support for addRunClasspathClasses() with dex runtimes

Change-Id: Ibda6246a2acd1b3c3c56675a2c0744a2df612a52
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index 1496847..44fe743 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -64,7 +64,7 @@
       Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
       throws CompilationFailedException {
     ToolHelper.runD8(builder, optionsConsumer);
-    return new D8TestCompileResult(getState(), app.get(), getOutputMode());
+    return new D8TestCompileResult(getState(), app.get(), minApiLevel, getOutputMode());
   }
 
   public D8TestBuilder setIntermediate(boolean intermediate) {
diff --git a/src/test/java/com/android/tools/r8/D8TestCompileResult.java b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
index 8b91d57..ea8ff8b 100644
--- a/src/test/java/com/android/tools/r8/D8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
@@ -4,11 +4,13 @@
 package com.android.tools.r8;
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 
 public class D8TestCompileResult extends TestCompileResult<D8TestCompileResult, D8TestRunResult> {
-  D8TestCompileResult(TestState state, AndroidApp app, OutputMode outputMode) {
-    super(state, app, outputMode);
+  D8TestCompileResult(
+      TestState state, AndroidApp app, AndroidApiLevel minApiLevel, OutputMode outputMode) {
+    super(state, app, minApiLevel, outputMode);
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/DXTestBuilder.java b/src/test/java/com/android/tools/r8/DXTestBuilder.java
index 9e26ecd..49055a1 100644
--- a/src/test/java/com/android/tools/r8/DXTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/DXTestBuilder.java
@@ -29,8 +29,6 @@
   // Ordered list of injar entries.
   private List<Path> injars = new ArrayList<>();
 
-  private int minApiLevel = -1;
-
   private DXTestBuilder(TestState state) {
     super(state, D8Command.builder(), Backend.DEX);
   }
@@ -53,9 +51,7 @@
       Path outJar = dxOutputFolder.resolve("output.jar");
 
       List<String> args = new ArrayList<>();
-      if (minApiLevel >= 0) {
-        args.add("--min-sdk-version=" + minApiLevel);
-      }
+      args.add("--min-sdk-version=" + minApiLevel.getLevel());
       args.add("--output=" + outJar.toString());
       args.addAll(injars.stream().map(Path::toString).collect(Collectors.toList()));
       ProcessResult result =
@@ -66,7 +62,7 @@
         throw new CompilationFailedException(result.toString());
       }
       return new DXTestCompileResult(
-          getState(), AndroidApp.builder().addProgramFile(outJar).build());
+          getState(), AndroidApp.builder().addProgramFile(outJar).build(), minApiLevel);
     } catch (IOException e) {
       throw new CompilationFailedException(e);
     }
@@ -123,10 +119,4 @@
     injars.addAll(files);
     return self();
   }
-
-  @Override
-  public DXTestBuilder setMinApi(int minApiLevel) {
-    this.minApiLevel = minApiLevel;
-    return self();
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/DXTestCompileResult.java b/src/test/java/com/android/tools/r8/DXTestCompileResult.java
index e362f78..9cb6482 100644
--- a/src/test/java/com/android/tools/r8/DXTestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/DXTestCompileResult.java
@@ -5,12 +5,13 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 
 public class DXTestCompileResult extends TestCompileResult<DXTestCompileResult, DXTestRunResult> {
 
-  DXTestCompileResult(TestState state, AndroidApp app) {
-    super(state, app, OutputMode.DexIndexed);
+  DXTestCompileResult(TestState state, AndroidApp app, AndroidApiLevel minApiLevel) {
+    super(state, app, minApiLevel, OutputMode.DexIndexed);
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
index 08ce5be..b6fe80d 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
@@ -142,7 +142,7 @@
               ? FileUtils.readTextFile(proguardMapFile, Charsets.UTF_8)
               : "";
       return new ExternalR8TestCompileResult(
-          getState(), outputJar, processResult, proguardMap, getOutputMode());
+          getState(), outputJar, processResult, proguardMap, minApiLevel, getOutputMode());
     } catch (IOException e) {
       throw new CompilationFailedException(e);
     }
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestCompileResult.java b/src/test/java/com/android/tools/r8/ExternalR8TestCompileResult.java
index 75cd5526..73fe9b4 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestCompileResult.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.io.IOException;
@@ -24,8 +25,9 @@
       Path outputJar,
       ProcessResult processResult,
       String proguardMap,
+      AndroidApiLevel minApiLevel,
       OutputMode outputMode) {
-    super(state, AndroidApp.builder().addProgramFiles(outputJar).build(), outputMode);
+    super(state, AndroidApp.builder().addProgramFiles(outputJar).build(), minApiLevel, outputMode);
     assert processResult.exitCode == 0;
     this.outputJar = outputJar;
     this.processResult = processResult;
diff --git a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
index ba1d485..27d4655 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
@@ -106,7 +106,7 @@
       }
       String proguardMap =
           Files.exists(mapFile) ? FileUtils.readTextFile(mapFile, Charsets.UTF_8) : "";
-      return new ProguardTestCompileResult(getState(), outJar, proguardMap);
+      return new ProguardTestCompileResult(getState(), outJar, minApiLevel, proguardMap);
     } catch (IOException e) {
       throw new CompilationFailedException(e);
     }
diff --git a/src/test/java/com/android/tools/r8/ProguardTestCompileResult.java b/src/test/java/com/android/tools/r8/ProguardTestCompileResult.java
index dbb3c6e..b51c598 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestCompileResult.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.io.IOException;
@@ -17,8 +18,13 @@
   private final Path outputJar;
   private final String proguardMap;
 
-  ProguardTestCompileResult(TestState state, Path outputJar, String proguardMap) {
-    super(state, AndroidApp.builder().addProgramFiles(outputJar).build(), OutputMode.ClassFile);
+  ProguardTestCompileResult(
+      TestState state, Path outputJar, AndroidApiLevel minApiLevel, String proguardMap) {
+    super(
+        state,
+        AndroidApp.builder().addProgramFiles(outputJar).build(),
+        minApiLevel,
+        OutputMode.ClassFile);
     this.outputJar = outputJar;
     this.proguardMap = proguardMap;
   }
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 86776a3..1ad8f28 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -150,7 +150,7 @@
             box.syntheticProguardRules,
             proguardMapBuilder.toString(),
             graphConsumer,
-            builder.getMinApiLevel(),
+            minApiLevel,
             features);
     switch (allowedDiagnosticMessages) {
       case ALL:
diff --git a/src/test/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
index c2a1dac..0deb4f5 100644
--- a/src/test/java/com/android/tools/r8/R8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.shaking.CollectingGraphConsumer;
 import com.android.tools.r8.shaking.ProguardConfiguration;
 import com.android.tools.r8.shaking.ProguardConfigurationRule;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.ThrowingConsumer;
@@ -29,7 +30,6 @@
   private final List<ProguardConfigurationRule> syntheticProguardRules;
   private final String proguardMap;
   private final CollectingGraphConsumer graphConsumer;
-  private final int minApiLevel;
   private final List<Path> features;
 
   R8TestCompileResult(
@@ -40,14 +40,13 @@
       List<ProguardConfigurationRule> syntheticProguardRules,
       String proguardMap,
       CollectingGraphConsumer graphConsumer,
-      int minApiLevel,
+      AndroidApiLevel minApiLevel,
       List<Path> features) {
-    super(state, app, outputMode);
+    super(state, app, minApiLevel, outputMode);
     this.proguardConfiguration = proguardConfiguration;
     this.syntheticProguardRules = syntheticProguardRules;
     this.proguardMap = proguardMap;
     this.graphConsumer = graphConsumer;
-    this.minApiLevel = minApiLevel;
     this.features = features;
   }
 
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index c3c51de..d7bebd8 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -133,6 +133,10 @@
     CF,
     DEX;
 
+    public boolean isDex() {
+      return this == DEX;
+    }
+
     public static Backend fromConsumer(ProgramConsumer consumer) {
       return consumer instanceof ClassFileConsumer ? CF : DEX;
     }
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 3294828..7dfe4b5 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -5,6 +5,7 @@
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
 import static com.android.tools.r8.TestBase.Backend.DEX;
+import static com.android.tools.r8.TestBase.testForD8;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -48,15 +49,18 @@
     extends TestBaseResult<CR, RR> {
 
   public final AndroidApp app;
+  public final AndroidApiLevel minApiLevel;
   private final OutputMode outputMode;
   final List<Path> additionalRunClassPath = new ArrayList<>();
   final List<String> vmArguments = new ArrayList<>();
   private boolean withArt6Plus64BitsLib = false;
   private boolean withArtFrameworks = true;
 
-  TestCompileResult(TestState state, AndroidApp app, OutputMode outputMode) {
+  TestCompileResult(
+      TestState state, AndroidApp app, AndroidApiLevel minApiLevel, OutputMode outputMode) {
     super(state);
     this.app = app;
+    this.minApiLevel = minApiLevel;
     this.outputMode = outputMode;
   }
 
@@ -167,11 +171,19 @@
     return self();
   }
 
-  public CR addRunClasspathClasses(Class<?>... classpath) {
+  public CR addRunClasspathClasses(Class<?>... classpath) throws Exception {
     return addRunClasspathClasses(Arrays.asList(classpath));
   }
 
-  public CR addRunClasspathClasses(List<Class<?>> classpath) {
+  public CR addRunClasspathClasses(List<Class<?>> classpath) throws Exception {
+    if (getBackend() == Backend.DEX) {
+      return addRunClasspathFiles(
+          testForD8(state.getTempFolder())
+              .addProgramClasses(classpath)
+              .setMinApi(minApiLevel)
+              .compile()
+              .writeToZip());
+    }
     assert getBackend() == Backend.CF;
     try {
       Path path = state.getNewTempFolder().resolve("runtime-classes.jar");
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index 43b5478..590f10a 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -53,7 +53,7 @@
   private final List<Path> additionalRunClassPath = new ArrayList<>();
   private ProgramConsumer programConsumer;
   private StringConsumer mainDexListConsumer;
-  private AndroidApiLevel defaultMinApiLevel = ToolHelper.getMinApiLevelForDexVm();
+  protected AndroidApiLevel minApiLevel = ToolHelper.getMinApiLevelForDexVm();
   private Consumer<InternalOptions> optionsConsumer = DEFAULT_OPTIONS;
   private ByteArrayOutputStream stdout = null;
   private PrintStream oldStdout = null;
@@ -63,6 +63,10 @@
 
   private boolean isAndroidBuildVersionAdded = false;
 
+  public boolean isTestShrinkerBuilder() {
+    return false;
+  }
+
   public T addAndroidBuildVersion() {
     addProgramClasses(AndroidBuildVersion.class);
     isAndroidBuildVersionAdded = true;
@@ -103,13 +107,14 @@
     AndroidAppConsumers sink = new AndroidAppConsumers();
     builder.setProgramConsumer(sink.wrapProgramConsumer(programConsumer));
     builder.setMainDexListConsumer(mainDexListConsumer);
-    if (backend == Backend.DEX && defaultMinApiLevel != null) {
+    if (backend.isDex() || !isTestShrinkerBuilder()) {
       assert !builder.isMinApiLevelSet()
           : "Don't set the API level directly through BaseCompilerCommand.Builder in tests";
-      builder.setMinApiLevel(defaultMinApiLevel.getLevel());
+      builder.setMinApiLevel(minApiLevel.getLevel());
     }
     if (useDefaultRuntimeLibrary) {
-      if (backend == Backend.DEX && builder.isMinApiLevelSet()) {
+      if (backend == Backend.DEX) {
+        assert builder.isMinApiLevelSet();
         builder.addLibraryFiles(
             ToolHelper.getFirstSupportedAndroidJar(
                 AndroidApiLevel.getAndroidApiLevel(builder.getMinApiLevel())));
@@ -233,11 +238,7 @@
   }
 
   public T setMinApi(int minApiLevel) {
-    assert builder.getMinApiLevel() > 0 || this.defaultMinApiLevel != null
-        : "Tests must use this method to set min API level, and not"
-            + " BaseCompilerCommand.Builder.setMinApiLevel()";
-    this.defaultMinApiLevel = null;
-    builder.setMinApiLevel(minApiLevel);
+    this.minApiLevel = AndroidApiLevel.getAndroidApiLevel(minApiLevel);
     return self();
   }
 
diff --git a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
index 69a42a4..6d3590d 100644
--- a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
@@ -35,17 +35,14 @@
   }
 
   @Override
-  public T setMinApi(AndroidApiLevel minApiLevel) {
-    if (backend == Backend.DEX) {
-      return super.setMinApi(minApiLevel.getLevel());
-    }
-    return self();
+  public boolean isTestShrinkerBuilder() {
+    return true;
   }
 
   @Override
-  public T setMinApi(int minApiLevel) {
+  public T setMinApi(AndroidApiLevel minApiLevel) {
     if (backend == Backend.DEX) {
-      return super.setMinApi(minApiLevel);
+      return super.setMinApi(minApiLevel.getLevel());
     }
     return self();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java b/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java
index d191976..c73b948 100644
--- a/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java
+++ b/src/test/java/com/android/tools/r8/graph/MissingClassThrowingTest.java
@@ -6,7 +6,6 @@
 
 import static org.hamcrest.core.StringContains.containsString;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NoStaticClassMerging;
 import com.android.tools.r8.TestBase;
@@ -14,7 +13,6 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import java.io.IOException;
-import java.util.concurrent.ExecutionException;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -65,8 +63,7 @@
 
   @Ignore("b/128885552")
   @Test
-  public void testSuperTypeOfExceptions()
-      throws ExecutionException, CompilationFailedException, IOException {
+  public void testSuperTypeOfExceptions() throws Exception {
     testForR8(parameters.getBackend())
         .addProgramClasses(Program.class)
         .noMinification()
diff --git a/src/test/java/com/android/tools/r8/rewrite/serviceloaders/MissingServiceClassTest.java b/src/test/java/com/android/tools/r8/rewrite/serviceloaders/MissingServiceClassTest.java
index 94d7781..cd6d815 100644
--- a/src/test/java/com/android/tools/r8/rewrite/serviceloaders/MissingServiceClassTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/serviceloaders/MissingServiceClassTest.java
@@ -11,7 +11,6 @@
 import static org.junit.Assert.assertNotNull;
 
 import com.android.tools.r8.DataEntryResource;
-import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -77,7 +76,7 @@
                                   + ServiceImpl.class.getTypeName()
                                   + "."))));
             })
-        .apply(this::configureRunClasspath)
+        .addRunClasspathClasses(Service.class, ServiceImpl.class)
         .run(parameters.getRuntime(), TestClass.class)
         .assertSuccessWithEmptyOutput();
 
@@ -91,19 +90,6 @@
     assertEquals(ServiceImpl.class.getTypeName(), contents.get(0));
   }
 
-  private void configureRunClasspath(R8TestCompileResult compileResult) throws Exception {
-    if (parameters.isCfRuntime()) {
-      compileResult.addRunClasspathClasses(Service.class, ServiceImpl.class);
-    } else {
-      compileResult.addRunClasspathFiles(
-          testForD8(temp)
-              .addProgramClasses(Service.class, ServiceImpl.class)
-              .setMinApi(parameters.getApiLevel())
-              .compile()
-              .writeToZip());
-    }
-  }
-
   static class TestClass {
 
     public static void main(String[] args) throws ClassNotFoundException {