Add D8 main-dex-list API tests and update collection types.

Change-Id: I17103e98ab58d473b5dec03ba290a7247877d33c
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index cae894d..0424e2a 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -27,6 +27,7 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Consumer;
@@ -112,10 +113,8 @@
       return self();
     }
 
-    /**
-     * Add proguard configuration file resources for automatic main dex list calculation.
-     */
-    public Builder addMainDexRulesFiles(List<Path> paths) {
+    /** Add proguard configuration file resources for automatic main dex list calculation. */
+    public Builder addMainDexRulesFiles(Collection<Path> paths) {
       guard(() -> {
         for (Path path : paths) {
           mainDexRules.add(new ProguardConfigurationSourceFile(path));
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
index 2261866..e0a0b5b 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
@@ -61,12 +61,15 @@
     // (everything is put into providers) so manually parse them here.
     List<Path> libraries = new ArrayList<>(1);
     List<Path> classpath = new ArrayList<>(args.length);
+    List<Path> mainDexList = new ArrayList<>(1);
     List<Path> inputs = new ArrayList<>(args.length);
     for (int i = 0; i < args.length; i++) {
       if (args[i].equals("--lib")) {
         libraries.add(Paths.get(args[++i]));
       } else if (args[i].equals("--classpath")) {
         classpath.add(Paths.get(args[++i]));
+      } else if (args[i].equals("--main-dex-list")) {
+        mainDexList.add(Paths.get(args[++i]));
       } else if (isArchive(args[i]) || isClassFile(args[i])) {
         inputs.add(Paths.get(args[i]));
       }
@@ -83,11 +86,16 @@
     if (libraries.isEmpty()) {
       throw new RuntimeException("Must supply library inputs");
     }
+    if (mainDexList.isEmpty()) {
+      throw new RuntimeException("Must supply main-dex-list inputs");
+    }
 
     useProgramFileBuilder(CompilationMode.DEBUG, minApiLevel, libraries, classpath, inputs);
     useProgramFileBuilder(CompilationMode.RELEASE, minApiLevel, libraries, classpath, inputs);
     useProgramDataBuilder(minApiLevel, libraries, classpath, inputs);
     useLibraryAndClasspathProvider(minApiLevel, libraries, classpath, inputs);
+    useMainDexListFiles(minApiLevel, libraries, classpath, inputs, mainDexList);
+    useMainDexClasses(minApiLevel, libraries, classpath, inputs, mainDexList);
     incrementalCompileAndMerge(minApiLevel, libraries, classpath, inputs);
   }
 
@@ -162,6 +170,60 @@
     }
   }
 
+  private static void useMainDexListFiles(
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> classpath,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList) {
+    try {
+      D8.run(
+          D8Command.builder(handler)
+              .setMinApiLevel(minApiLevel)
+              .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+              .addLibraryFiles(libraries)
+              .addClasspathFiles(classpath)
+              .addProgramFiles(inputs)
+              .addMainDexListFiles(mainDexList)
+              .build());
+    } catch (CompilationFailedException e) {
+      throw new RuntimeException("Unexpected compilation exceptions", e);
+    }
+  }
+
+  private static void useMainDexClasses(
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> classpath,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList) {
+    try {
+      List<String> mainDexClasses = new ArrayList<>(1);
+      for (Path path : mainDexList) {
+        for (String line : Files.readAllLines(path)) {
+          String entry = line.trim();
+          if (entry.isEmpty() || entry.startsWith("#") || !entry.endsWith(".class")) {
+            continue;
+          }
+          mainDexClasses.add(entry.replace(".class", "").replace("/", "."));
+        }
+      }
+      D8.run(
+          D8Command.builder(handler)
+              .setMinApiLevel(minApiLevel)
+              .setProgramConsumer(DexIndexedConsumer.emptyConsumer())
+              .addLibraryFiles(libraries)
+              .addClasspathFiles(classpath)
+              .addProgramFiles(inputs)
+              .addMainDexClasses(mainDexClasses)
+              .build());
+    } catch (CompilationFailedException e) {
+      throw new RuntimeException("Unexpected compilation exceptions", e);
+    } catch (IOException e) {
+      throw new RuntimeException("Unexpected IO exception", e);
+    }
+  }
+
   private static void incrementalCompileAndMerge(
       int minApiLevel,
       Collection<Path> libraries,
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
index dff6ca9..be7e207 100644
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
+++ b/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
@@ -164,7 +164,10 @@
   }
 
   private static void useMainDexListFiles(
-      int minApiLevel, List<Path> libraries, List<Path> inputs, List<Path> mainDexList) {
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList) {
     try {
       R8.run(
           R8Command.builder(handler)
@@ -180,7 +183,10 @@
   }
 
   private static void useMainDexClasses(
-      int minApiLevel, List<Path> libraries, List<Path> inputs, List<Path> mainDexList) {
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList) {
     try {
       List<String> mainDexClasses = new ArrayList<>(1);
       for (Path path : mainDexList) {
@@ -208,7 +214,10 @@
   }
 
   private static void useMainDexRulesFiles(
-      int minApiLevel, List<Path> libraries, List<Path> inputs, List<Path> mainDexRules) {
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexRules) {
     try {
       R8.run(
           R8Command.builder(handler)
@@ -224,7 +233,10 @@
   }
 
   private static void useMainDexRules(
-      int minApiLevel, List<Path> libraries, List<Path> inputs, List<Path> mainDexRulesFiles) {
+      int minApiLevel,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexRulesFiles) {
     try {
       R8Command.Builder builder =
           R8Command.builder(handler)
@@ -246,9 +258,9 @@
 
   private static void useProguardConfigFiles(
       int minApiLevel,
-      List<Path> libraries,
-      List<Path> inputs,
-      List<Path> mainDexList,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList,
       List<Path> pgConf) {
     try {
       R8.run(
@@ -267,9 +279,9 @@
 
   private static void useProguardConfigLines(
       int minApiLevel,
-      List<Path> libraries,
-      List<Path> inputs,
-      List<Path> mainDexList,
+      Collection<Path> libraries,
+      Collection<Path> inputs,
+      Collection<Path> mainDexList,
       List<Path> pgConf) {
     try {
       R8Command.Builder builder =
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
index c5f1a19..86f0319 100644
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
@@ -7,6 +7,7 @@
 
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.FileUtils;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.Files;
 import java.io.File;
@@ -83,9 +84,9 @@
     List<Path> input =
         ImmutableList.of(
             inputDir.resolve("ImplementMethodsWithDefault.class"), inputDir.resolve("Main.class"));
-    File mainDexClasses = temp.newFile();
-    Files.asCharSink(mainDexClasses, StandardCharsets.UTF_8)
-        .write("desugaringwithmissingclasstest1/Main.class");
+
+    Path mainDexList = temp.getRoot().toPath().resolve("maindexlist.txt");
+    FileUtils.writeTextFile(mainDexList, "desugaringwithmissingclasstest1/Main.class");
 
     List<String> command =
         ImmutableList.<String>builder()
@@ -100,6 +101,8 @@
                     temp.newFolder().getAbsolutePath(),
                     "--min-api",
                     Integer.toString(minApiLevel),
+                    "--main-dex-list",
+                    mainDexList.toString(),
                     "--lib",
                     ToolHelper.getAndroidJar(minApiLevel),
                     "--classpath",
diff --git a/tests/d8_api_usage_sample.jar b/tests/d8_api_usage_sample.jar
index 4346c82..5913594 100644
--- a/tests/d8_api_usage_sample.jar
+++ b/tests/d8_api_usage_sample.jar
Binary files differ
diff --git a/tests/r8_api_usage_sample.jar b/tests/r8_api_usage_sample.jar
index 04c64d4..55c5e83 100644
--- a/tests/r8_api_usage_sample.jar
+++ b/tests/r8_api_usage_sample.jar
Binary files differ