Move old binary tests to the new API test set up.

The main-dex APIs are split out into their own tests, the rest is close to a
blind copy. The test inputs are changed to avoid using legacy example artifacts.

Bug: b/181858113
Change-Id: I4db1ce2f42e8cc5637284124da8ecbf98bf82c88
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java
deleted file mode 100644
index 775a308..0000000
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/CachingArchiveClassFileProvider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2017, 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.apiusagesample;
-
-import com.android.tools.r8.ArchiveClassFileProvider;
-import com.android.tools.r8.ClassFileResourceProvider;
-import com.android.tools.r8.DirectoryClassFileProvider;
-import com.android.tools.r8.ProgramResource;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class CachingArchiveClassFileProvider extends ArchiveClassFileProvider {
-
-  private ConcurrentHashMap<String, ProgramResource> resources = new ConcurrentHashMap<>();
-
-  private CachingArchiveClassFileProvider(Path archive) throws IOException {
-    super(archive);
-  }
-
-  @Override
-  public ProgramResource getProgramResource(String descriptor) {
-    return resources.computeIfAbsent(descriptor, super::getProgramResource);
-  }
-
-  public static ClassFileResourceProvider getProvider(Path entry)
-      throws IOException {
-    if (Files.isRegularFile(entry)) {
-      return new CachingArchiveClassFileProvider(entry);
-    } else if (Files.isDirectory(entry)) {
-      return DirectoryClassFileProvider.fromDirectory(entry);
-    } else {
-      throw new FileNotFoundException(entry.toString());
-    }
-  }
-}
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
deleted file mode 100644
index 80a2845..0000000
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8ApiUsageSample.java
+++ /dev/null
@@ -1,628 +0,0 @@
-// Copyright (c) 2017, 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.apiusagesample;
-
-import com.android.tools.r8.ArchiveProgramResourceProvider;
-import com.android.tools.r8.AssertionsConfiguration;
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.D8;
-import com.android.tools.r8.D8Command;
-import com.android.tools.r8.DesugarGraphConsumer;
-import com.android.tools.r8.DexFilePerClassFileConsumer;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.ProgramResource;
-import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.ProgramResourceProvider;
-import com.android.tools.r8.ResourceException;
-import com.android.tools.r8.origin.ArchiveEntryOrigin;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.utils.StringDiagnostic;
-import com.android.tools.r8.utils.StringUtils;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-public class D8ApiUsageSample {
-
-  private static final Origin origin =
-      new Origin(Origin.root()) {
-        @Override
-        public String part() {
-          return "D8ApiUsageSample";
-        }
-      };
-
-  private static final DiagnosticsHandler handler = new D8DiagnosticsHandler();
-
-  /**
-   * Example invocation:
-   *
-   * <pre>
-   *   java -jar d8-api-uses.jar \
-   *     --output path/to/output/dir \
-   *     --min-api minApiLevel \
-   *     --lib path/to/library.jar \
-   *     --classpath path/to/classpath.jar \
-   *     path/to/input{1,2,3}.{jar,class}
-   * </pre>
-   */
-  public static void main(String[] args) {
-    // Parse arguments with the commandline parser to make use of its API.
-    D8Command.Builder cmd = D8Command.parse(args, origin);
-    CompilationMode mode = cmd.getMode();
-    Path temp = cmd.getOutputPath();
-    int minApiLevel = cmd.getMinApiLevel();
-    // The Builder API does not provide access to the concrete paths
-    // (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> mainDexRules = 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 (args[i].equals("--main-dex-rules")) {
-        mainDexRules.add(Paths.get(args[++i]));
-      } else if (isArchive(args[i]) || isClassFile(args[i])) {
-        inputs.add(Paths.get(args[i]));
-      }
-    }
-    if (!Files.exists(temp) || !Files.isDirectory(temp)) {
-      throw new RuntimeException("Must supply a temp/output directory");
-    }
-    if (inputs.isEmpty()) {
-      throw new RuntimeException("Must supply program inputs");
-    }
-    if (classpath.isEmpty()) {
-      throw new RuntimeException("Must supply classpath inputs");
-    }
-    if (libraries.isEmpty()) {
-      throw new RuntimeException("Must supply library inputs");
-    }
-    if (mainDexList.isEmpty()) {
-      throw new RuntimeException("Must supply main-dex-list inputs");
-    }
-    if (mainDexRules.isEmpty()) {
-      throw new RuntimeException("Must supply main-dex-rules inputs");
-    }
-
-    useProgramFileList(CompilationMode.DEBUG, minApiLevel, libraries, classpath, inputs);
-    useProgramFileList(CompilationMode.RELEASE, minApiLevel, libraries, classpath, inputs);
-    useProgramData(minApiLevel, libraries, classpath, inputs);
-    useProgramResourceProvider(minApiLevel, libraries, classpath, inputs);
-    useLibraryAndClasspathProvider(minApiLevel, libraries, classpath, inputs);
-    useMainDexListFiles(minApiLevel, libraries, classpath, inputs, mainDexList);
-    useMainDexClasses(minApiLevel, libraries, classpath, inputs, mainDexList);
-    useMainDexRulesFiles(minApiLevel, libraries, classpath, inputs, mainDexRules);
-    useMainDexRules(minApiLevel, libraries, classpath, inputs, mainDexRules);
-    useAssertionConfig(minApiLevel, libraries, classpath, inputs);
-    useVArgVariants(minApiLevel, libraries, classpath, inputs, mainDexList);
-    incrementalCompileAndMerge(minApiLevel, libraries, classpath, inputs);
-  }
-
-  // Check API support for compiling Java class-files from the file system.
-  private static void useProgramFileList(
-      CompilationMode mode,
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMode(mode)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath)
-              .addProgramFiles(inputs)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  // Check API support for compiling Java class-files from byte content.
-  private static void useProgramData(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    try {
-      D8Command.Builder builder =
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath);
-      for (ClassFileContent classfile : readClassFiles(inputs)) {
-        builder.addClassProgramData(classfile.data, classfile.origin);
-      }
-      for (Path input : inputs) {
-        if (isDexFile(input)) {
-          builder.addDexProgramData(Files.readAllBytes(input), new PathOrigin(input));
-        }
-      }
-      D8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  // Check API support for compiling Java class-files from a program provider abstraction.
-  private static void useProgramResourceProvider(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    try {
-      D8Command.Builder builder =
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath);
-      for (Path input : inputs) {
-        if (isArchive(input)) {
-          builder.addProgramResourceProvider(
-              ArchiveProgramResourceProvider.fromArchive(
-                  input, ArchiveProgramResourceProvider::includeClassFileEntries));
-        } else if (isClassFile(input)) {
-          builder.addProgramResourceProvider(
-              new ProgramResourceProvider() {
-                @Override
-                public Collection<ProgramResource> getProgramResources() throws ResourceException {
-                  return Collections.singleton(ProgramResource.fromFile(Kind.CF, input));
-                }
-              });
-        } else if (isDexFile(input)) {
-          builder.addProgramResourceProvider(
-              new ProgramResourceProvider() {
-                @Override
-                public Collection<ProgramResource> getProgramResources() throws ResourceException {
-                  return Collections.singleton(ProgramResource.fromFile(Kind.DEX, input));
-                }
-              });
-        }
-      }
-      D8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void useLibraryAndClasspathProvider(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    try {
-      D8Command.Builder builder =
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addProgramFiles(inputs);
-      for (Path library : libraries) {
-        builder.addLibraryResourceProvider(CachingArchiveClassFileProvider.getProvider(library));
-      }
-      for (Path path : classpath) {
-        builder.addClasspathResourceProvider(CachingArchiveClassFileProvider.getProvider(path));
-      }
-      D8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  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(new EnsureOutputConsumer())
-              .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(new EnsureOutputConsumer())
-              .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 useMainDexRulesFiles(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs,
-      Collection<Path> mainDexRules) {
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath)
-              .addProgramFiles(inputs)
-              .addMainDexRulesFiles(mainDexRules)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void useMainDexRules(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs,
-      Collection<Path> mainDexRulesFiles) {
-    try {
-      D8Command.Builder builder =
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath)
-              .addProgramFiles(inputs);
-      for (Path mainDexRulesFile : mainDexRulesFiles) {
-        builder.addMainDexRules(
-            Files.readAllLines(mainDexRulesFile), new PathOrigin(mainDexRulesFile));
-      }
-      D8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  private static void useAssertionConfig(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath)
-              .addProgramFiles(inputs)
-              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeEnable().build())
-              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeDisable().build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setCompileTimeEnable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setPassthrough()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setCompileTimeDisable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setCompileTimeEnable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setPassthrough()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setCompileTimeDisable()
-                          .build())
-              .addAssertionsConfiguration(
-                  AssertionsConfiguration.Builder::compileTimeEnableAllAssertions)
-              .addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions)
-              .addAssertionsConfiguration(
-                  AssertionsConfiguration.Builder::compileTimeDisableAllAssertions)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  // Check API support for all the varg variants.
-  private static void useVArgVariants(
-      int minApiLevel,
-      List<Path> libraries,
-      List<Path> classpath,
-      List<Path> inputs,
-      List<Path> mainDexList) {
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries.get(0))
-              .addLibraryFiles(libraries.stream().skip(1).toArray(Path[]::new))
-              .addClasspathFiles(classpath.get(0))
-              .addClasspathFiles(classpath.stream().skip(1).toArray(Path[]::new))
-              .addProgramFiles(inputs.get(0))
-              .addProgramFiles(inputs.stream().skip(1).toArray(Path[]::new))
-              .addMainDexListFiles(mainDexList.get(0))
-              .addMainDexListFiles(mainDexList.stream().skip(1).toArray(Path[]::new))
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void incrementalCompileAndMerge(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    // Compile and merge via index intermediates.
-    mergeIntermediates(
-        minApiLevel, compileToIndexedIntermediates(minApiLevel, libraries, classpath, inputs));
-    // Compile and merge via per-classfile intermediates.
-    mergeIntermediates(
-        minApiLevel, compileToPerClassFileIntermediates(minApiLevel, libraries, classpath, inputs));
-  }
-
-  private static Collection<byte[]> compileToIndexedIntermediates(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    IndexIntermediatesConsumer consumer = new IndexIntermediatesConsumer();
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setIntermediate(true)
-              .setProgramConsumer(consumer)
-              .addClasspathFiles(classpath)
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .setDisableDesugaring(false)
-              .setDesugarGraphConsumer(new MyDesugarGraphConsumer())
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-    return consumer.bytes;
-  }
-
-  private static Collection<byte[]> compileToPerClassFileIntermediates(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> classpath,
-      Collection<Path> inputs) {
-    PerClassIntermediatesConsumer consumer = new PerClassIntermediatesConsumer();
-    try {
-      D8.run(
-          D8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(consumer)
-              .addLibraryFiles(libraries)
-              .addClasspathFiles(classpath)
-              .addProgramFiles(inputs)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-    return consumer.bytes;
-  }
-
-  private static void mergeIntermediates(int minApiLevel, Collection<byte[]> intermediates) {
-    D8Command.Builder builder =
-        D8Command.builder(handler)
-            .setMinApiLevel(minApiLevel)
-            .setProgramConsumer(new EnsureOutputConsumer())
-            .setDisableDesugaring(true);
-    for (byte[] intermediate : intermediates) {
-      builder.addDexProgramData(intermediate, Origin.unknown());
-    }
-    try {
-      D8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected merging error", e);
-    }
-  }
-
-  // Helpers for tests.
-  // Some of this reimplements stuff in R8 utils, but that is not public API and we should not
-  // rely on it.
-
-  private static List<ClassFileContent> readClassFiles(Collection<Path> files) throws IOException {
-    List<ClassFileContent> classfiles = new ArrayList<>();
-    for (Path file : files) {
-      if (isArchive(file)) {
-        Origin zipOrigin = new PathOrigin(file);
-        ZipInputStream zip = new ZipInputStream(Files.newInputStream(file), StandardCharsets.UTF_8);
-        ZipEntry entry;
-        while (null != (entry = zip.getNextEntry())) {
-          String name = entry.getName();
-          if (isClassFile(name)) {
-            Origin origin = new ArchiveEntryOrigin(name, zipOrigin);
-            classfiles.add(new ClassFileContent(origin, readBytes(zip)));
-          }
-        }
-      } else if (isClassFile(file)) {
-        classfiles.add(new ClassFileContent(new PathOrigin(file), Files.readAllBytes(file)));
-      }
-    }
-    return classfiles;
-  }
-
-  private static byte[] readBytes(InputStream stream) throws IOException {
-    try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
-      byte[] buffer = new byte[0xffff];
-      for (int length; (length = stream.read(buffer)) != -1; ) {
-        bytes.write(buffer, 0, length);
-      }
-      return bytes.toByteArray();
-    }
-  }
-
-  private static boolean isClassFile(Path file) {
-    return isClassFile(file.toString());
-  }
-
-  private static boolean isClassFile(String file) {
-    file = StringUtils.toLowerCase(file);
-    return file.endsWith(".class");
-  }
-
-  private static boolean isDexFile(Path file) {
-    return isDexFile(file.toString());
-  }
-
-  private static boolean isDexFile(String file) {
-    file = StringUtils.toLowerCase(file);
-    return file.endsWith(".dex");
-  }
-
-  private static boolean isArchive(Path file) {
-    return isArchive(file.toString());
-  }
-
-  private static boolean isArchive(String file) {
-    file = StringUtils.toLowerCase(file);
-    return file.endsWith(".zip") || file.endsWith(".jar");
-  }
-
-  private static class ClassFileContent {
-    final Origin origin;
-    final byte[] data;
-
-    public ClassFileContent(Origin origin, byte[] data) {
-      this.origin = origin;
-      this.data = data;
-    }
-  }
-
-  private static class IndexIntermediatesConsumer implements DexIndexedConsumer {
-
-    List<byte[]> bytes = new ArrayList<>();
-
-    @Override
-    public synchronized void accept(
-        int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
-      bytes.add(data);
-    }
-
-    @Override
-    public void finished(DiagnosticsHandler handler) {}
-  }
-
-  private static class PerClassIntermediatesConsumer implements DexFilePerClassFileConsumer {
-
-    List<byte[]> bytes = new ArrayList<>();
-
-    @Override
-    public synchronized void accept(
-        String primaryClassDescriptor,
-        byte[] data,
-        Set<String> descriptors,
-        DiagnosticsHandler handler) {
-      bytes.add(data);
-    }
-
-    @Override
-    public void finished(DiagnosticsHandler handler) {}
-  }
-
-  private static class EnsureOutputConsumer implements DexIndexedConsumer {
-    boolean hasOutput = false;
-
-    @Override
-    public synchronized void accept(
-        int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
-      hasOutput = true;
-    }
-
-    @Override
-    public void finished(DiagnosticsHandler handler) {
-      if (!hasOutput) {
-        handler.error(new StringDiagnostic("Expected to produce output but had none"));
-      }
-    }
-  }
-
-  private static class MyDesugarGraphConsumer implements DesugarGraphConsumer {
-
-    @Override
-    public void accept(Origin dependent, Origin dependency) {
-    }
-
-    public void finished() {
-
-    }
-  }
-}
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java
deleted file mode 100644
index d523a53..0000000
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/D8DiagnosticsHandler.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2017, 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.apiusagesample;
-
-import com.android.tools.r8.Diagnostic;
-import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
-import com.android.tools.r8.origin.ArchiveEntryOrigin;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.position.Position;
-import com.android.tools.r8.position.TextPosition;
-import com.android.tools.r8.position.TextRange;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-class D8DiagnosticsHandler implements DiagnosticsHandler {
-
-  public D8DiagnosticsHandler() {
-  }
-
-  public static Origin getOrigin(Path root, Path entry) {
-    if (Files.isRegularFile(root)) {
-      return new ArchiveEntryOrigin(entry.toString(), new PathOrigin(root));
-    } else {
-      return new PathOrigin(root.resolve(entry.toString()));
-    }
-  }
-
-  @Override
-  public void error(Diagnostic error) {
-    convertToMessage(error);
-  }
-
-  @Override
-  public void warning(Diagnostic warning) {
-    if (warning instanceof InterfaceDesugarMissingTypeDiagnostic) {
-      desugarInterfaceMethodInfo((InterfaceDesugarMissingTypeDiagnostic) warning);
-    } else {
-      convertToMessage(warning);
-    }
-  }
-
-  @Override
-  public void info(Diagnostic info) {
-    convertToMessage(info);
-  }
-
-  void desugarInterfaceMethodInfo(InterfaceDesugarMissingTypeDiagnostic info) {
-    System.out.println("desugar is missing: " + info.getMissingType().toString());
-    System.out.println("  used from: " + info.getContextType().toString());
-    convertToMessage(info);
-  }
-
-  protected void convertToMessage(Diagnostic diagnostic) {
-    String textMessage = diagnostic.getDiagnosticMessage();
-
-    Origin origin = diagnostic.getOrigin();
-    Position positionInOrigin = diagnostic.getPosition();
-    String position;
-    if (origin instanceof PathOrigin) {
-      Path originFile = ((PathOrigin) origin).getPath();
-      if (positionInOrigin instanceof TextRange) {
-        TextRange textRange = (TextRange) positionInOrigin;
-        position = originFile + ": "
-            + textRange.getStart().getLine() + "," + textRange.getStart().getColumn()
-            + " - " + textRange.getEnd().getLine() + "," + textRange.getEnd().getColumn();
-      } else if (positionInOrigin instanceof TextPosition) {
-        TextPosition textPosition = (TextPosition) positionInOrigin;
-        position = originFile + ": "
-            + textPosition.getLine() + "," + textPosition.getColumn();
-      } else {
-        position = originFile.toString();
-      }
-    } else if (origin.parent() instanceof PathOrigin) {
-      Path originFile = ((PathOrigin) origin.parent()).getPath();
-      position = originFile.toString();
-    } else {
-      position = "UNKNOWN";
-      if (origin != Origin.unknown()) {
-        textMessage = origin.toString() + ": " + textMessage;
-      }
-    }
-
-    System.out.println(position + ": " + textMessage);
-  }
-}
diff --git a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java b/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
deleted file mode 100644
index 521ccba..0000000
--- a/src/test/apiUsageSample/com/android/tools/apiusagesample/R8ApiUsageSample.java
+++ /dev/null
@@ -1,612 +0,0 @@
-// Copyright (c) 2018, 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.apiusagesample;
-
-import com.android.tools.r8.ArchiveClassFileProvider;
-import com.android.tools.r8.ArchiveProgramResourceProvider;
-import com.android.tools.r8.AssertionsConfiguration;
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
-import com.android.tools.r8.ProgramResource;
-import com.android.tools.r8.ProgramResource.Kind;
-import com.android.tools.r8.ProgramResourceProvider;
-import com.android.tools.r8.R8;
-import com.android.tools.r8.R8Command;
-import com.android.tools.r8.ResourceException;
-import com.android.tools.r8.StringConsumer;
-import com.android.tools.r8.Version;
-import com.android.tools.r8.origin.ArchiveEntryOrigin;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.origin.PathOrigin;
-import com.android.tools.r8.utils.StringDiagnostic;
-import com.android.tools.r8.utils.StringUtils;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-public class R8ApiUsageSample {
-
-  private static final Origin origin =
-      new Origin(Origin.root()) {
-        @Override
-        public String part() {
-          return "R8ApiUsageSample";
-        }
-      };
-
-  private static final DiagnosticsHandler handler = new D8DiagnosticsHandler();
-
-  /**
-   * Example invocation:
-   *
-   * <pre>
-   *   java -jar r8-api-uses.jar \
-   *     --output path/to/output/dir \
-   *     --min-api minApiLevel \
-   *     --lib path/to/library.jar \
-   *     path/to/input{1,2,3}.{jar,class}
-   * </pre>
-   */
-  public static void main(String[] args) {
-    // Check version API
-    checkVersionApi();
-    // Parse arguments with the commandline parser to make use of its API.
-    R8Command.Builder cmd = R8Command.parse(args, origin);
-    CompilationMode mode = cmd.getMode();
-    Path temp = cmd.getOutputPath();
-    int minApiLevel = cmd.getMinApiLevel();
-    // The Builder API does not provide access to the concrete paths
-    // (everything is put into providers) so manually parse them here.
-    List<Path> libraries = new ArrayList<>(1);
-    List<Path> mainDexList = new ArrayList<>(1);
-    List<Path> mainDexRules = new ArrayList<>(1);
-    List<Path> pgConf = 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("--main-dex-list")) {
-        mainDexList.add(Paths.get(args[++i]));
-      } else if (args[i].equals("--main-dex-rules")) {
-        mainDexRules.add(Paths.get(args[++i]));
-      } else if (args[i].equals("--pg-conf")) {
-        pgConf.add(Paths.get(args[++i]));
-      } else if (isArchive(args[i]) || isClassFile(args[i])) {
-        inputs.add(Paths.get(args[i]));
-      }
-    }
-    if (!Files.exists(temp) || !Files.isDirectory(temp)) {
-      throw new RuntimeException("Must supply a temp/output directory");
-    }
-    if (inputs.isEmpty()) {
-      throw new RuntimeException("Must supply program inputs");
-    }
-    if (libraries.isEmpty()) {
-      throw new RuntimeException("Must supply library inputs");
-    }
-    if (mainDexList.isEmpty()) {
-      throw new RuntimeException("Must supply main-dex-list inputs");
-    }
-    if (mainDexRules.isEmpty()) {
-      throw new RuntimeException("Must supply main-dex-rules inputs");
-    }
-    if (pgConf.isEmpty()) {
-      throw new RuntimeException("Must supply pg-conf inputs");
-    }
-
-    useProgramFileList(CompilationMode.DEBUG, minApiLevel, libraries, inputs);
-    useProgramFileList(CompilationMode.RELEASE, minApiLevel, libraries, inputs);
-    useProgramData(minApiLevel, libraries, inputs);
-    useProgramResourceProvider(minApiLevel, libraries, inputs);
-    useLibraryResourceProvider(minApiLevel, libraries, inputs);
-    useMainDexListFiles(minApiLevel, libraries, inputs, mainDexList);
-    useMainDexClasses(minApiLevel, libraries, inputs, mainDexList);
-    useMainDexRulesFiles(minApiLevel, libraries, inputs, mainDexRules);
-    useMainDexRules(minApiLevel, libraries, inputs, mainDexRules);
-    useProguardConfigFiles(minApiLevel, libraries, inputs, mainDexList, pgConf);
-    useProguardConfigLines(minApiLevel, libraries, inputs, mainDexList, pgConf);
-    useAssertionConfig(minApiLevel, libraries, inputs);
-    useVArgVariants(minApiLevel, libraries, inputs, mainDexList, mainDexRules, pgConf);
-    useProguardConfigConsumers(minApiLevel, libraries, inputs, pgConf);
-  }
-
-  private static class InMemoryStringConsumer implements StringConsumer {
-    public String value = null;
-
-    @Override
-    public void accept(String string, DiagnosticsHandler handler) {
-      value = string;
-    }
-  }
-
-  private static void useProguardConfigConsumers(
-      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs, List<Path> pgConf) {
-    InMemoryStringConsumer usageConsumer = new InMemoryStringConsumer();
-    InMemoryStringConsumer seedsConsumer = new InMemoryStringConsumer();
-    InMemoryStringConsumer configConsumer = new InMemoryStringConsumer();
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .addProguardConfigurationFiles(pgConf)
-              .setProguardUsageConsumer(usageConsumer)
-              .setProguardSeedsConsumer(seedsConsumer)
-              .setProguardConfigurationConsumer(configConsumer)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exception", e);
-    }
-    if (usageConsumer.value == null) {
-      throw new RuntimeException("Expected usage info but had none");
-    }
-    if (seedsConsumer.value == null) {
-      throw new RuntimeException("Expected seeds info but had none");
-    }
-    if (configConsumer.value == null) {
-      throw new RuntimeException("Expected config info but had none");
-    }
-  }
-
-  // Check API support for compiling Java class-files from the file system.
-  private static void useProgramFileList(
-      CompilationMode mode, int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMode(mode)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  // Check API support for compiling Java class-files from byte content.
-  private static void useProgramData(
-      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries);
-      for (ClassFileContent classfile : readClassFiles(inputs)) {
-        builder.addClassProgramData(classfile.data, classfile.origin);
-      }
-      R8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  // Check API support for compiling Java class-files from a program provider abstraction.
-  private static void useProgramResourceProvider(
-      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries);
-      for (Path input : inputs) {
-        if (isArchive(input)) {
-          builder.addProgramResourceProvider(
-              ArchiveProgramResourceProvider.fromArchive(
-                  input, ArchiveProgramResourceProvider::includeClassFileEntries));
-        } else {
-          builder.addProgramResourceProvider(
-              new ProgramResourceProvider() {
-                @Override
-                public Collection<ProgramResource> getProgramResources() throws ResourceException {
-                  return Collections.singleton(ProgramResource.fromFile(Kind.CF, input));
-                }
-              });
-        }
-      }
-      R8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void useLibraryResourceProvider(
-      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addProgramFiles(inputs);
-      for (Path library : libraries) {
-        builder.addLibraryResourceProvider(new ArchiveClassFileProvider(library));
-      }
-      R8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  private static void useMainDexListFiles(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> inputs,
-      Collection<Path> mainDexList) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .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> 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("/", "."));
-        }
-      }
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .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 useMainDexRulesFiles(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> inputs,
-      Collection<Path> mainDexRules) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .addMainDexRulesFiles(mainDexRules)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void useMainDexRules(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> inputs,
-      Collection<Path> mainDexRulesFiles) {
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setDisableTreeShaking(true)
-              .setDisableMinification(true)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs);
-      for (Path mainDexRulesFile : mainDexRulesFiles) {
-        builder.addMainDexRules(
-            Files.readAllLines(mainDexRulesFile), new PathOrigin(mainDexRulesFile));
-      }
-      R8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  private static void useProguardConfigFiles(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> inputs,
-      Collection<Path> mainDexList,
-      List<Path> pgConf) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .addMainDexListFiles(mainDexList)
-              .addProguardConfigurationFiles(pgConf)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  private static void useProguardConfigLines(
-      int minApiLevel,
-      Collection<Path> libraries,
-      Collection<Path> inputs,
-      Collection<Path> mainDexList,
-      List<Path> pgConf) {
-    try {
-      R8Command.Builder builder =
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .addMainDexListFiles(mainDexList);
-      for (Path file : pgConf) {
-        builder.addProguardConfiguration(Files.readAllLines(file), new PathOrigin(file));
-      }
-      R8.run(builder.build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    } catch (IOException e) {
-      throw new RuntimeException("Unexpected IO exception", e);
-    }
-  }
-
-  private static void useAssertionConfig(
-      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setDisableTreeShaking(true)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries)
-              .addProgramFiles(inputs)
-              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeEnable().build())
-              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeDisable().build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setCompileTimeEnable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setPassthrough()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopePackage("com.android.tools.apiusagesample")
-                          .setCompileTimeDisable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setCompileTimeEnable()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setPassthrough()
-                          .build())
-              .addAssertionsConfiguration(
-                  b ->
-                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
-                          .setCompileTimeDisable()
-                          .build())
-              .addAssertionsConfiguration(
-                  AssertionsConfiguration.Builder::compileTimeEnableAllAssertions)
-              .addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions)
-              .addAssertionsConfiguration(
-                  AssertionsConfiguration.Builder::compileTimeDisableAllAssertions)
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  // Check API support for all the varg variants.
-  private static void useVArgVariants(
-      int minApiLevel,
-      List<Path> libraries,
-      List<Path> inputs,
-      List<Path> mainDexList,
-      List<Path> mainDexRules,
-      List<Path> pgConf) {
-    try {
-      R8.run(
-          R8Command.builder(handler)
-              .setMinApiLevel(minApiLevel)
-              .setProgramConsumer(new EnsureOutputConsumer())
-              .addLibraryFiles(libraries.get(0))
-              .addLibraryFiles(libraries.stream().skip(1).toArray(Path[]::new))
-              .addProgramFiles(inputs.get(0))
-              .addProgramFiles(inputs.stream().skip(1).toArray(Path[]::new))
-              .addMainDexListFiles(mainDexList.get(0))
-              .addMainDexListFiles(mainDexList.stream().skip(1).toArray(Path[]::new))
-              .addMainDexRulesFiles(mainDexRules.get(0))
-              .addMainDexRulesFiles(mainDexRules.stream().skip(1).toArray(Path[]::new))
-              .addProguardConfigurationFiles(pgConf.get(0))
-              .addProguardConfigurationFiles(pgConf.stream().skip(1).toArray(Path[]::new))
-              .build());
-    } catch (CompilationFailedException e) {
-      throw new RuntimeException("Unexpected compilation exceptions", e);
-    }
-  }
-
-  // Helpers for tests.
-  // Some of this reimplements stuff in R8 utils, but that is not public API and we should not
-  // rely on it.
-
-  private static List<ClassFileContent> readClassFiles(Collection<Path> files) throws IOException {
-    List<ClassFileContent> classfiles = new ArrayList<>();
-    for (Path file : files) {
-      if (isArchive(file)) {
-        Origin zipOrigin = new PathOrigin(file);
-        ZipInputStream zip = new ZipInputStream(Files.newInputStream(file), StandardCharsets.UTF_8);
-        ZipEntry entry;
-        while (null != (entry = zip.getNextEntry())) {
-          String name = entry.getName();
-          if (isClassFile(name)) {
-            Origin origin = new ArchiveEntryOrigin(name, zipOrigin);
-            classfiles.add(new ClassFileContent(origin, readBytes(zip)));
-          }
-        }
-      } else if (isClassFile(file)) {
-        classfiles.add(new ClassFileContent(new PathOrigin(file), Files.readAllBytes(file)));
-      }
-    }
-    return classfiles;
-  }
-
-  private static byte[] readBytes(InputStream stream) throws IOException {
-    try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
-      byte[] buffer = new byte[0xffff];
-      for (int length; (length = stream.read(buffer)) != -1; ) {
-        bytes.write(buffer, 0, length);
-      }
-      return bytes.toByteArray();
-    }
-  }
-
-  private static boolean isClassFile(Path file) {
-    return isClassFile(file.toString());
-  }
-
-  private static boolean isClassFile(String file) {
-    file = StringUtils.toLowerCase(file);
-    return file.endsWith(".class");
-  }
-
-  private static boolean isArchive(Path file) {
-    return isArchive(file.toString());
-  }
-
-  private static boolean isArchive(String file) {
-    file = StringUtils.toLowerCase(file);
-    return file.endsWith(".zip") || file.endsWith(".jar");
-  }
-
-  private static class ClassFileContent {
-    final Origin origin;
-    final byte[] data;
-
-    public ClassFileContent(Origin origin, byte[] data) {
-      this.origin = origin;
-      this.data = data;
-    }
-  }
-
-  private static class EnsureOutputConsumer implements DexIndexedConsumer {
-    boolean hasOutput = false;
-
-    @Override
-    public synchronized void accept(
-        int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
-      hasOutput = true;
-    }
-
-    @Override
-    public void finished(DiagnosticsHandler handler) {
-      if (!hasOutput) {
-        handler.error(new StringDiagnostic("Expected to produce output but had none"));
-      }
-    }
-  }
-
-  private static void checkVersionApi() {
-    String labelValue;
-    int labelAccess;
-    try {
-      Field field = Version.class.getDeclaredField("LABEL");
-      labelAccess = field.getModifiers();
-      labelValue = (String) field.get(Version.class);
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-    if (!Modifier.isPublic(labelAccess)
-        || !Modifier.isStatic(labelAccess)
-        || !Modifier.isFinal(labelAccess)) {
-      throw new RuntimeException("Expected public static final LABEL");
-    }
-    if (labelValue.isEmpty()) {
-      throw new RuntimeException("Expected LABEL constant");
-    }
-    if (Version.LABEL.isEmpty()) {
-      throw new RuntimeException("Expected LABEL constant");
-    }
-    if (Version.getVersionString() == null) {
-      throw new RuntimeException("Expected getVersionString API");
-    }
-    if (Version.getMajorVersion() < -1) {
-      throw new RuntimeException("Expected getMajorVersion API");
-    }
-    if (Version.getMinorVersion() < -1) {
-      throw new RuntimeException("Expected getMinorVersion API");
-    }
-    if (Version.getPatchVersion() < -1) {
-      throw new RuntimeException("Expected getPatchVersion API");
-    }
-    if (Version.getPreReleaseString() == null && false) {
-      throw new RuntimeException("Expected getPreReleaseString API");
-    }
-    if (Version.isDevelopmentVersion() && false) {
-      throw new RuntimeException("Expected isDevelopmentVersion API");
-    }
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
deleted file mode 100644
index d660bed..0000000
--- a/src/test/java/com/android/tools/r8/D8ApiBinaryCompatibilityTests.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2017, 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 static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-import static org.junit.Assert.assertEquals;
-
-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 java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.junit.Assert;
-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 D8ApiBinaryCompatibilityTests extends TestBase {
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withNoneRuntime().build();
-  }
-
-  public D8ApiBinaryCompatibilityTests(TestParameters parameters) {
-    parameters.assertNoneRuntime();
-  }
-
-  @Test
-  public void testCompatibility() throws IOException {
-    Path jar = ToolHelper.API_SAMPLE_JAR;
-    String main = "com.android.tools.apiusagesample.D8ApiUsageSample";
-    int minApiLevel = AndroidApiLevel.K.getLevel();
-
-    Path lib1 =
-        Paths.get(
-            ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR,
-            "desugaringwithmissingclasslib1" + JAR_EXTENSION);
-    Path lib2 =
-        Paths.get(
-            ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR,
-            "desugaringwithmissingclasslib2" + JAR_EXTENSION);
-    Path inputDir =
-        Paths.get(
-            ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR, "classes", "desugaringwithmissingclasstest1");
-    List<Path> input =
-        ImmutableList.of(
-            inputDir.resolve("ImplementMethodsWithDefault.class"), inputDir.resolve("Main.class"));
-
-    Path mainDexList = temp.getRoot().toPath().resolve("maindexlist.txt");
-    FileUtils.writeTextFile(mainDexList, "desugaringwithmissingclasstest1/Main.class");
-
-    Path mainDexRules = temp.getRoot().toPath().resolve("maindex.rules");
-    FileUtils.writeTextFile(mainDexRules, "# empty file");
-
-    // It is important to place the api usage sample jar after the current classpath because we want
-    // to find D8/R8 classes before the ones in the jar, otherwise renamed classes and fields cannot
-    // be found.
-    String classPath = System.getProperty("java.class.path") + File.pathSeparator + jar;
-    List<String> command =
-        ImmutableList.<String>builder()
-            .addAll(
-                ImmutableList.of(
-                    ToolHelper.getJavaExecutable(),
-                    "-cp",
-                    classPath,
-                    main,
-                    // Compiler arguments.
-                    "--output",
-                    temp.newFolder().getAbsolutePath(),
-                    "--min-api",
-                    Integer.toString(minApiLevel),
-                    "--main-dex-list",
-                    mainDexList.toString(),
-                    "--main-dex-rules",
-                    mainDexRules.toString(),
-                    "--lib",
-                    ToolHelper.getAndroidJar(AndroidApiLevel.getAndroidApiLevel(minApiLevel))
-                        .toString(),
-                    "--classpath",
-                    lib1.toString(),
-                    "--classpath",
-                    lib2.toString()))
-            .addAll(input.stream().map(Path::toString).collect(Collectors.toList()))
-            .build();
-
-    ProcessBuilder builder = new ProcessBuilder(command);
-    ProcessResult result = ToolHelper.runProcess(builder);
-    assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
-    Assert.assertEquals("", filterOutMainDexListWarnings(result.stdout));
-    Assert.assertEquals("", result.stderr);
-  }
-
-  public static String filterOutMainDexListWarnings(String output) {
-    StringBuilder builder = new StringBuilder();
-    for (String line : output.split("\n")) {
-      if (!line.contains("Unsupported usage of main-dex list")) {
-        builder.append(line).append("\n");
-      }
-    }
-    return builder.toString();
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java b/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
deleted file mode 100644
index 67753da..0000000
--- a/src/test/java/com/android/tools/r8/R8ApiBinaryCompatibilityTests.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2018, 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 static org.junit.Assert.assertEquals;
-
-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 java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.stream.Collectors;
-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 R8ApiBinaryCompatibilityTests extends TestBase {
-
-  static final Path JAR = ToolHelper.API_SAMPLE_JAR;
-  static final String MAIN = "com.android.tools.apiusagesample.R8ApiUsageSample";
-  static final AndroidApiLevel MIN_API = AndroidApiLevel.K;
-
-  @Parameters(name = "{0}")
-  public static TestParametersCollection data() {
-    return getTestParameters().withNoneRuntime().build();
-  }
-
-  public R8ApiBinaryCompatibilityTests(TestParameters parameters) {
-    parameters.assertNoneRuntime();
-  }
-
-  @Test
-  public void testCompatibility() throws IOException {
-    List<Path> inputs =
-        ImmutableList.of(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "arithmetic.jar"));
-
-    String keepMain = "-keep public class arithmetic.Arithmetic {\n"
-        + "  public static void main(java.lang.String[]);\n"
-        + "}";
-
-    Path pgConf = temp.getRoot().toPath().resolve("pg.conf");
-    FileUtils.writeTextFile(pgConf, keepMain);
-
-    Path mainDexRules = temp.getRoot().toPath().resolve("maindex.rules");
-    FileUtils.writeTextFile(mainDexRules, keepMain);
-
-    Path mainDexList = temp.getRoot().toPath().resolve("maindexlist.txt");
-    FileUtils.writeTextFile(mainDexList, "arithmetic/Arithmetic.class");
-
-    List<String> command =
-        ImmutableList.<String>builder()
-            .addAll(
-                ImmutableList.of(
-                    ToolHelper.getJavaExecutable(),
-                    "-cp",
-                    JAR.toString() + File.pathSeparator + System.getProperty("java.class.path"),
-                    MAIN,
-                    // Compiler arguments.
-                    "--output",
-                    temp.newFolder().toString(),
-                    "--min-api",
-                    Integer.toString(MIN_API.getLevel()),
-                    "--pg-conf",
-                    pgConf.toString(),
-                    "--main-dex-rules",
-                    mainDexRules.toString(),
-                    "--main-dex-list",
-                    mainDexList.toString(),
-                    "--lib",
-                    ToolHelper.getAndroidJar(MIN_API).toString()))
-            .addAll(inputs.stream().map(Path::toString).collect(Collectors.toList()))
-            .build();
-
-    ProcessBuilder builder = new ProcessBuilder(command);
-    ProcessResult result = ToolHelper.runProcess(builder);
-    assertEquals(result.stderr + "\n" + result.stdout, 0, result.exitCode);
-    assertEquals("", D8ApiBinaryCompatibilityTests.filterOutMainDexListWarnings(result.stdout));
-    assertEquals("", result.stderr);
-  }
-}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
index c50b238..5d349fc 100644
--- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
+++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
@@ -20,11 +20,16 @@
 import com.android.tools.r8.compilerapi.globalsyntheticsgenerator.GlobalSyntheticsGeneratorTest;
 import com.android.tools.r8.compilerapi.inputdependencies.InputDependenciesTest;
 import com.android.tools.r8.compilerapi.inputmap.InputMapTest;
+import com.android.tools.r8.compilerapi.maindex.MainDexClassesTest;
+import com.android.tools.r8.compilerapi.maindex.MainDexListTest;
+import com.android.tools.r8.compilerapi.maindex.MainDexRulesTest;
 import com.android.tools.r8.compilerapi.mapid.CustomMapIdTest;
 import com.android.tools.r8.compilerapi.mockdata.MockClass;
 import com.android.tools.r8.compilerapi.mockdata.MockClassWithAssertion;
 import com.android.tools.r8.compilerapi.mockdata.PostStartupMockClass;
 import com.android.tools.r8.compilerapi.partitionmap.PartitionMapCommandTest;
+import com.android.tools.r8.compilerapi.sampleapi.D8ApiUsageSampleTest;
+import com.android.tools.r8.compilerapi.sampleapi.R8ApiUsageSampleTest;
 import com.android.tools.r8.compilerapi.sourcefile.CustomSourceFileTest;
 import com.android.tools.r8.compilerapi.startupprofile.StartupProfileApiTest;
 import com.android.tools.r8.compilerapi.syntheticscontexts.SyntheticContextsConsumerTest;
@@ -47,6 +52,8 @@
   private static final List<Class<? extends CompilerApiTest>> CLASSES_FOR_BINARY_COMPATIBILITY =
       ImmutableList.of(
           ApiTestingSetUpTest.ApiTest.class,
+          D8ApiUsageSampleTest.ApiTest.class,
+          R8ApiUsageSampleTest.ApiTest.class,
           CustomMapIdTest.ApiTest.class,
           CustomSourceFileTest.ApiTest.class,
           AssertionConfigurationTest.ApiTest.class,
@@ -66,7 +73,10 @@
           PartitionMapCommandTest.ApiTest.class,
           CancelCompilationCheckerTest.ApiTest.class,
           GlobalSyntheticsGeneratorTest.ApiTest.class,
-          InputMapTest.ApiTest.class);
+          InputMapTest.ApiTest.class,
+          MainDexListTest.ApiTest.class,
+          MainDexClassesTest.ApiTest.class,
+          MainDexRulesTest.ApiTest.class);
 
   private static final List<Class<? extends CompilerApiTest>> CLASSES_PENDING_BINARY_COMPATIBILITY =
       ImmutableList.of();
diff --git a/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexClassesTest.java b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexClassesTest.java
new file mode 100644
index 0000000..c24ab90
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexClassesTest.java
@@ -0,0 +1,127 @@
+// Copyright (c) 2024, 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.compilerapi.maindex;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DiagnosticsMatcher;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
+import java.nio.file.Path;
+import java.util.Arrays;
+import org.junit.Test;
+
+public class MainDexClassesTest extends CompilerApiTestRunner {
+
+  public MainDexClassesTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  static class InputClass {}
+
+  interface Runner {
+    void run(ApiTest test, String[] mainDexClasses, DiagnosticsHandler handler) throws Exception;
+  }
+
+  private TestDiagnosticMessagesImpl runTest(Runner runner) throws Exception {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    String[] mainDexClasses = new String[] {InputClass.class.getName()};
+    TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
+    runner.run(test, mainDexClasses, handler);
+    return handler;
+  }
+
+  private Path getDexInput() throws Exception {
+    return testForD8().addProgramClasses(InputClass.class).compile().writeToZip();
+  }
+
+  private static Path getCfInput() {
+    return ToolHelper.getClassFileForTestClass(InputClass.class);
+  }
+
+  @Test
+  public void testD8DexInputs() throws Exception {
+    runTest((test, mainDexClasses, handler) -> test.runD8(getDexInput(), mainDexClasses, handler))
+        .assertNoMessages();
+  }
+
+  @Test
+  public void testD8CfInputs() throws Exception {
+    runTest((test, mainDexClasses, handler) -> test.runD8(getCfInput(), mainDexClasses, handler))
+        .assertOnlyWarnings()
+        .assertAllWarningsMatch(
+            DiagnosticsMatcher.diagnosticType(UnsupportedMainDexListUsageDiagnostic.class));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    runTest((test, mainDexClasses, handler) -> test.runR8(getCfInput(), mainDexClasses, handler))
+        .assertOnlyWarnings()
+        .assertAllWarningsMatch(
+            DiagnosticsMatcher.diagnosticType(UnsupportedMainDexListUsageDiagnostic.class));
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    public void runD8(Path programInput, String[] mainDexClassesInput, DiagnosticsHandler handler)
+        throws CompilationFailedException {
+      D8Command.Builder builder =
+          handler == null ? D8Command.builder() : D8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      if (mainDexClassesInput != null) {
+        builder.addMainDexClasses(mainDexClassesInput);
+        builder.addMainDexClasses(Arrays.asList(mainDexClassesInput));
+      }
+      D8.run(builder.build());
+    }
+
+    public void runR8(Path programInput, String[] mainDexClassesInput, DiagnosticsHandler handler)
+        throws CompilationFailedException {
+      R8Command.Builder builder =
+          handler == null ? R8Command.builder() : R8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      builder.addMainDexClasses(mainDexClassesInput);
+      builder.addMainDexClasses(Arrays.asList(mainDexClassesInput));
+      R8.run(builder.build());
+    }
+
+    @Test
+    public void testD8() throws CompilationFailedException {
+      runD8(null, new String[0], null);
+    }
+
+    @Test
+    public void testR8() throws CompilationFailedException {
+      runR8(null, new String[0], null);
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexListTest.java b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexListTest.java
new file mode 100644
index 0000000..7b2264d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexListTest.java
@@ -0,0 +1,132 @@
+// Copyright (c) 2024, 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.compilerapi.maindex;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.DiagnosticsMatcher;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.errors.UnsupportedMainDexListUsageDiagnostic;
+import com.android.tools.r8.utils.FileUtils;
+import java.nio.file.Path;
+import java.util.Collections;
+import org.junit.Test;
+
+public class MainDexListTest extends CompilerApiTestRunner {
+
+  public MainDexListTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  static class InputClass {}
+
+  interface Runner {
+    void run(ApiTest test, Path mainDexList, DiagnosticsHandler handler) throws Exception;
+  }
+
+  private TestDiagnosticMessagesImpl runTest(Runner runner) throws Exception {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    Path mainDexListInput =
+        FileUtils.writeTextFile(
+            temp.newFile().toPath(), InputClass.class.getName().replace('.', '/') + ".class");
+    TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
+    runner.run(test, mainDexListInput, handler);
+    return handler;
+  }
+
+  private Path getDexInput() throws Exception {
+    return testForD8().addProgramClasses(InputClass.class).compile().writeToZip();
+  }
+
+  private static Path getCfInput() {
+    return ToolHelper.getClassFileForTestClass(InputClass.class);
+  }
+
+  @Test
+  public void testD8DexInputs() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runD8(getDexInput(), mainDexList, handler))
+        .assertNoMessages();
+  }
+
+  @Test
+  public void testD8CfInputs() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runD8(getCfInput(), mainDexList, handler))
+        .assertOnlyWarnings()
+        .assertAllWarningsMatch(
+            DiagnosticsMatcher.diagnosticType(UnsupportedMainDexListUsageDiagnostic.class));
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runR8(getCfInput(), mainDexList, handler))
+        .assertOnlyWarnings()
+        .assertAllWarningsMatch(
+            DiagnosticsMatcher.diagnosticType(UnsupportedMainDexListUsageDiagnostic.class));
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    public void runD8(Path programInput, Path mainDexListInput, DiagnosticsHandler handler)
+        throws CompilationFailedException {
+      D8Command.Builder builder =
+          handler == null ? D8Command.builder() : D8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      if (mainDexListInput != null) {
+        builder.addMainDexListFiles(mainDexListInput);
+        builder.addMainDexListFiles(Collections.singletonList(mainDexListInput));
+      }
+      D8.run(builder.build());
+    }
+
+    public void runR8(Path programInput, Path mainDexListInput, DiagnosticsHandler handler)
+        throws CompilationFailedException {
+      R8Command.Builder builder =
+          handler == null ? R8Command.builder() : R8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      if (mainDexListInput != null) {
+        builder.addMainDexListFiles(mainDexListInput);
+        builder.addMainDexListFiles(Collections.singletonList(mainDexListInput));
+      }
+      R8.run(builder.build());
+    }
+
+    @Test
+    public void testD8() throws CompilationFailedException {
+      runD8(null, null, null);
+    }
+
+    @Test
+    public void testR8() throws CompilationFailedException {
+      runR8(null, null, null);
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexRulesTest.java b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexRulesTest.java
new file mode 100644
index 0000000..5701058
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/maindex/MainDexRulesTest.java
@@ -0,0 +1,137 @@
+// Copyright (c) 2024, 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.compilerapi.maindex;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.utils.FileUtils;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+
+public class MainDexRulesTest extends CompilerApiTestRunner {
+
+  public MainDexRulesTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  static class InputClass {}
+
+  interface Runner {
+    void run(ApiTest test, Path mainDexList, DiagnosticsHandler handler) throws Exception;
+  }
+
+  private TestDiagnosticMessagesImpl runTest(Runner runner) throws Exception {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    Path mainDexRulesFile = FileUtils.writeTextFile(temp.newFile().toPath(), "# empty file");
+    TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
+    runner.run(test, mainDexRulesFile, handler);
+    return handler;
+  }
+
+  private Path getDexInput() throws Exception {
+    return testForD8().addProgramClasses(InputClass.class).compile().writeToZip();
+  }
+
+  private static Path getCfInput() {
+    return ToolHelper.getClassFileForTestClass(InputClass.class);
+  }
+
+  @Test
+  public void testD8DexInputs() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runD8(getDexInput(), mainDexList, handler))
+        .assertNoMessages();
+  }
+
+  @Test
+  public void testD8CfInputs() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runD8(getCfInput(), mainDexList, handler))
+        .assertNoMessages();
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    runTest((test, mainDexList, handler) -> test.runR8(getCfInput(), mainDexList, handler))
+        .assertNoMessages();
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    public void runD8(Path programInput, Path mainDexRulesFile, DiagnosticsHandler handler)
+        throws Exception {
+      D8Command.Builder builder =
+          handler == null ? D8Command.builder() : D8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      if (mainDexRulesFile != null) {
+        List<String> rules = Files.readAllLines(mainDexRulesFile);
+        builder.addMainDexRules(rules, new PathOrigin(mainDexRulesFile));
+        builder.addMainDexRulesFiles(mainDexRulesFile);
+        builder.addMainDexRulesFiles(Collections.singletonList(mainDexRulesFile));
+      }
+      D8.run(builder.build());
+    }
+
+    public void runR8(Path programInput, Path mainDexRulesFile, DiagnosticsHandler handler)
+        throws CompilationFailedException {
+      R8Command.Builder builder =
+          handler == null ? R8Command.builder() : R8Command.builder(handler);
+      builder
+          .addLibraryFiles(getJava8RuntimeJar())
+          .setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+      if (programInput != null) {
+        builder.addProgramFiles(programInput);
+      }
+      if (mainDexRulesFile != null) {
+        List<String> rules;
+        try {
+          rules = Files.readAllLines(mainDexRulesFile);
+        } catch (IOException e) {
+          throw new RuntimeException(e);
+        }
+        builder.addMainDexRules(rules, new PathOrigin(mainDexRulesFile));
+        builder.addMainDexRulesFiles(mainDexRulesFile);
+        builder.addMainDexRulesFiles(Collections.singletonList(mainDexRulesFile));
+      }
+      R8.run(builder.build());
+    }
+
+    @Test
+    public void testD8() throws Exception {
+      runD8(null, null, null);
+    }
+
+    @Test
+    public void testR8() throws Exception {
+      runR8(null, null, null);
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/sampleapi/D8ApiUsageSampleTest.java b/src/test/java/com/android/tools/r8/compilerapi/sampleapi/D8ApiUsageSampleTest.java
new file mode 100644
index 0000000..7a71205
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/sampleapi/D8ApiUsageSampleTest.java
@@ -0,0 +1,541 @@
+// Copyright (c) 2024, 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.compilerapi.sampleapi;
+
+import com.android.tools.r8.ArchiveClassFileProvider;
+import com.android.tools.r8.ArchiveProgramResourceProvider;
+import com.android.tools.r8.AssertionsConfiguration;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.D8;
+import com.android.tools.r8.D8Command;
+import com.android.tools.r8.DesugarGraphConsumer;
+import com.android.tools.r8.DexFilePerClassFileConsumer;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.ProgramResourceProvider;
+import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.origin.ArchiveEntryOrigin;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.utils.StringDiagnostic;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * This API test is a copy over from the old API sample test set up.
+ *
+ * <p>NOTE: Don't use this test as the basis for new API tests. Instead, use one of the simpler and
+ * more feature directed tests found in the sibling packages.
+ */
+public class D8ApiUsageSampleTest extends CompilerApiTestRunner {
+
+  public D8ApiUsageSampleTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  @Test
+  public void test() throws IOException {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    test.run(temp);
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    private static final Origin origin =
+        new Origin(Origin.root()) {
+          @Override
+          public String part() {
+            return "D8ApiUsageSample";
+          }
+        };
+
+    private static final DiagnosticsHandler handler = new DiagnosticsHandler() {};
+
+    @Test
+    public void test() throws IOException {
+      run(temp);
+    }
+
+    public void run(TemporaryFolder temp) throws IOException {
+      runFromArgs(
+          new String[] {
+            "--output",
+            temp.newFolder().getAbsolutePath(),
+            "--min-api",
+            "19",
+            "--lib",
+            getAndroidJar().toString(),
+            "--classpath",
+            getAndroidJar().toString(),
+            getPathForClass(getMockClass()).toString()
+          });
+    }
+
+    public void runFromArgs(String[] args) {
+      // Parse arguments with the commandline parser to make use of its API.
+      D8Command.Builder cmd = D8Command.parse(args, origin);
+      CompilationMode mode = cmd.getMode();
+      Path temp = cmd.getOutputPath();
+      int minApiLevel = cmd.getMinApiLevel();
+      // The Builder API does not provide access to the concrete paths
+      // (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> 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 (isArchive(args[i]) || isClassFile(args[i])) {
+          inputs.add(Paths.get(args[i]));
+        }
+      }
+      if (!Files.exists(temp) || !Files.isDirectory(temp)) {
+        throw new RuntimeException("Must supply a temp/output directory");
+      }
+      if (inputs.isEmpty()) {
+        throw new RuntimeException("Must supply program inputs");
+      }
+      if (libraries.isEmpty()) {
+        throw new RuntimeException("Must supply library inputs");
+      }
+      useProgramFileList(CompilationMode.DEBUG, minApiLevel, libraries, classpath, inputs);
+      useProgramFileList(CompilationMode.RELEASE, minApiLevel, libraries, classpath, inputs);
+      useProgramData(minApiLevel, libraries, classpath, inputs);
+      useProgramResourceProvider(minApiLevel, libraries, classpath, inputs);
+      useLibraryAndClasspathProvider(minApiLevel, libraries, classpath, inputs);
+      useAssertionConfig(minApiLevel, libraries, classpath, inputs);
+      useVArgVariants(minApiLevel, libraries, classpath, inputs);
+      incrementalCompileAndMerge(minApiLevel, libraries, classpath, inputs);
+    }
+
+    // Check API support for compiling Java class-files from the file system.
+    private static void useProgramFileList(
+        CompilationMode mode,
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      try {
+        D8.run(
+            D8Command.builder(handler)
+                .setMode(mode)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addClasspathFiles(classpath)
+                .addProgramFiles(inputs)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    // Check API support for compiling Java class-files from byte content.
+    private static void useProgramData(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      try {
+        D8Command.Builder builder =
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addClasspathFiles(classpath);
+        for (ClassFileContent classfile : readClassFiles(inputs)) {
+          builder.addClassProgramData(classfile.data, classfile.origin);
+        }
+        for (Path input : inputs) {
+          if (isDexFile(input)) {
+            builder.addDexProgramData(Files.readAllBytes(input), new PathOrigin(input));
+          }
+        }
+        D8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      } catch (IOException e) {
+        throw new RuntimeException("Unexpected IO exception", e);
+      }
+    }
+
+    // Check API support for compiling Java class-files from a program provider abstraction.
+    private static void useProgramResourceProvider(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      try {
+        D8Command.Builder builder =
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addClasspathFiles(classpath);
+        for (Path input : inputs) {
+          if (isArchive(input)) {
+            builder.addProgramResourceProvider(
+                ArchiveProgramResourceProvider.fromArchive(
+                    input, ArchiveProgramResourceProvider::includeClassFileEntries));
+          } else if (isClassFile(input)) {
+            builder.addProgramResourceProvider(
+                new ProgramResourceProvider() {
+                  @Override
+                  public Collection<ProgramResource> getProgramResources()
+                      throws ResourceException {
+                    return Collections.singleton(ProgramResource.fromFile(Kind.CF, input));
+                  }
+                });
+          } else if (isDexFile(input)) {
+            builder.addProgramResourceProvider(
+                new ProgramResourceProvider() {
+                  @Override
+                  public Collection<ProgramResource> getProgramResources()
+                      throws ResourceException {
+                    return Collections.singleton(ProgramResource.fromFile(Kind.DEX, input));
+                  }
+                });
+          }
+        }
+        D8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    private static void useLibraryAndClasspathProvider(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      try {
+        D8Command.Builder builder =
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addProgramFiles(inputs);
+        for (Path library : libraries) {
+          builder.addLibraryResourceProvider(new ArchiveClassFileProvider(library));
+        }
+        for (Path path : classpath) {
+          builder.addClasspathResourceProvider(new ArchiveClassFileProvider(path));
+        }
+        D8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      } catch (IOException e) {
+        throw new RuntimeException("Unexpected IO exception", e);
+      }
+    }
+
+    private static void useAssertionConfig(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      String pkg = "com.android.tools.r8.compilerapi.sampleapi";
+      try {
+        D8.run(
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addClasspathFiles(classpath)
+                .addProgramFiles(inputs)
+                .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeEnable().build())
+                .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeDisable().build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopePackage(pkg).setCompileTimeEnable().build())
+                .addAssertionsConfiguration(b -> b.setScopePackage(pkg).setPassthrough().build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopePackage(pkg).setCompileTimeDisable().build())
+                .addAssertionsConfiguration(
+                    b ->
+                        b.setScopeClass(pkg + ".D8ApiUsageSampleTest")
+                            .setCompileTimeEnable()
+                            .build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopeClass(pkg + ".D8ApiUsageSampleTest").setPassthrough().build())
+                .addAssertionsConfiguration(
+                    b ->
+                        b.setScopeClass(pkg + ".D8ApiUsageSampleTest")
+                            .setCompileTimeDisable()
+                            .build())
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::compileTimeEnableAllAssertions)
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::passthroughAllAssertions)
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::compileTimeDisableAllAssertions)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    // Check API support for all the varg variants.
+    private static void useVArgVariants(
+        int minApiLevel, List<Path> libraries, List<Path> classpath, List<Path> inputs) {
+      try {
+        D8Command.Builder builder =
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries.get(0))
+                .addLibraryFiles(libraries.stream().skip(1).toArray(Path[]::new))
+                .addProgramFiles(inputs.get(0))
+                .addProgramFiles(inputs.stream().skip(1).toArray(Path[]::new));
+        if (!classpath.isEmpty()) {
+          builder
+              .addClasspathFiles(classpath.get(0))
+              .addClasspathFiles(classpath.stream().skip(1).toArray(Path[]::new));
+        }
+        D8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    private static void incrementalCompileAndMerge(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      // Compile and merge via index intermediates.
+      mergeIntermediates(
+          minApiLevel, compileToIndexedIntermediates(minApiLevel, libraries, classpath, inputs));
+      // Compile and merge via per-classfile intermediates.
+      mergeIntermediates(
+          minApiLevel,
+          compileToPerClassFileIntermediates(minApiLevel, libraries, classpath, inputs));
+    }
+
+    private static Collection<byte[]> compileToIndexedIntermediates(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      IndexIntermediatesConsumer consumer = new IndexIntermediatesConsumer();
+      try {
+        D8.run(
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setIntermediate(true)
+                .setProgramConsumer(consumer)
+                .addClasspathFiles(classpath)
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs)
+                .setDisableDesugaring(false)
+                .setDesugarGraphConsumer(new MyDesugarGraphConsumer())
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+      return consumer.bytes;
+    }
+
+    private static Collection<byte[]> compileToPerClassFileIntermediates(
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> classpath,
+        Collection<Path> inputs) {
+      PerClassIntermediatesConsumer consumer = new PerClassIntermediatesConsumer();
+      try {
+        D8.run(
+            D8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(consumer)
+                .addLibraryFiles(libraries)
+                .addClasspathFiles(classpath)
+                .addProgramFiles(inputs)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+      return consumer.bytes;
+    }
+
+    private static void mergeIntermediates(int minApiLevel, Collection<byte[]> intermediates) {
+      D8Command.Builder builder =
+          D8Command.builder(handler)
+              .setMinApiLevel(minApiLevel)
+              .setProgramConsumer(new EnsureOutputConsumer())
+              .setDisableDesugaring(true);
+      for (byte[] intermediate : intermediates) {
+        builder.addDexProgramData(intermediate, Origin.unknown());
+      }
+      try {
+        D8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected merging error", e);
+      }
+    }
+
+    // Helpers for tests.
+    // Some of this reimplements stuff in R8 utils, but that is not public API and we should not
+    // rely on it.
+
+    private static List<ClassFileContent> readClassFiles(Collection<Path> files)
+        throws IOException {
+      List<ClassFileContent> classfiles = new ArrayList<>();
+      for (Path file : files) {
+        if (isArchive(file)) {
+          Origin zipOrigin = new PathOrigin(file);
+          ZipInputStream zip =
+              new ZipInputStream(Files.newInputStream(file), StandardCharsets.UTF_8);
+          ZipEntry entry;
+          while (null != (entry = zip.getNextEntry())) {
+            String name = entry.getName();
+            if (isClassFile(name)) {
+              Origin origin = new ArchiveEntryOrigin(name, zipOrigin);
+              classfiles.add(new ClassFileContent(origin, readBytes(zip)));
+            }
+          }
+        } else if (isClassFile(file)) {
+          classfiles.add(new ClassFileContent(new PathOrigin(file), Files.readAllBytes(file)));
+        }
+      }
+      return classfiles;
+    }
+
+    private static byte[] readBytes(InputStream stream) throws IOException {
+      try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
+        byte[] buffer = new byte[0xffff];
+        for (int length; (length = stream.read(buffer)) != -1; ) {
+          bytes.write(buffer, 0, length);
+        }
+        return bytes.toByteArray();
+      }
+    }
+
+    private static String toLowerCase(String str) {
+      return str.toLowerCase(Locale.ROOT);
+    }
+
+    private static boolean isClassFile(Path file) {
+      return isClassFile(file.toString());
+    }
+
+    private static boolean isClassFile(String file) {
+      file = toLowerCase(file);
+      return file.endsWith(".class");
+    }
+
+    private static boolean isDexFile(Path file) {
+      return isDexFile(file.toString());
+    }
+
+    private static boolean isDexFile(String file) {
+      file = toLowerCase(file);
+      return file.endsWith(".dex");
+    }
+
+    private static boolean isArchive(Path file) {
+      return isArchive(file.toString());
+    }
+
+    private static boolean isArchive(String file) {
+      file = toLowerCase(file);
+      return file.endsWith(".zip") || file.endsWith(".jar");
+    }
+
+    private static class ClassFileContent {
+      final Origin origin;
+      final byte[] data;
+
+      public ClassFileContent(Origin origin, byte[] data) {
+        this.origin = origin;
+        this.data = data;
+      }
+    }
+
+    private static class IndexIntermediatesConsumer implements DexIndexedConsumer {
+
+      List<byte[]> bytes = new ArrayList<>();
+
+      @Override
+      public synchronized void accept(
+          int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
+        bytes.add(data);
+      }
+
+      @Override
+      public void finished(DiagnosticsHandler handler) {}
+    }
+
+    private static class PerClassIntermediatesConsumer implements DexFilePerClassFileConsumer {
+
+      List<byte[]> bytes = new ArrayList<>();
+
+      @Override
+      public synchronized void accept(
+          String primaryClassDescriptor,
+          byte[] data,
+          Set<String> descriptors,
+          DiagnosticsHandler handler) {
+        bytes.add(data);
+      }
+
+      @Override
+      public void finished(DiagnosticsHandler handler) {}
+    }
+
+    private static class EnsureOutputConsumer implements DexIndexedConsumer {
+      boolean hasOutput = false;
+
+      @Override
+      public synchronized void accept(
+          int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
+        hasOutput = true;
+      }
+
+      @Override
+      public void finished(DiagnosticsHandler handler) {
+        if (!hasOutput) {
+          handler.error(new StringDiagnostic("Expected to produce output but had none"));
+        }
+      }
+    }
+
+    private static class MyDesugarGraphConsumer implements DesugarGraphConsumer {
+
+      @Override
+      public void accept(Origin dependent, Origin dependency) {}
+
+      public void finished() {}
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/compilerapi/sampleapi/R8ApiUsageSampleTest.java b/src/test/java/com/android/tools/r8/compilerapi/sampleapi/R8ApiUsageSampleTest.java
new file mode 100644
index 0000000..b3258e5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/compilerapi/sampleapi/R8ApiUsageSampleTest.java
@@ -0,0 +1,522 @@
+// Copyright (c) 2024, 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.compilerapi.sampleapi;
+
+import com.android.tools.r8.ArchiveClassFileProvider;
+import com.android.tools.r8.ArchiveProgramResourceProvider;
+import com.android.tools.r8.AssertionsConfiguration;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.ProgramResourceProvider;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.StringConsumer;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.Version;
+import com.android.tools.r8.compilerapi.CompilerApiTest;
+import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.origin.ArchiveEntryOrigin;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.utils.StringDiagnostic;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * This API test is a copy over from the old API sample test set up.
+ *
+ * <p>NOTE: Don't use this test as the basis for new API tests. Instead, use one of the simpler and
+ * more feature directed tests found in the sibling packages.
+ */
+public class R8ApiUsageSampleTest extends CompilerApiTestRunner {
+
+  public R8ApiUsageSampleTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<? extends CompilerApiTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  @Test
+  public void test() throws IOException {
+    ApiTest test = new ApiTest(ApiTest.PARAMETERS);
+    test.run(temp);
+  }
+
+  public static class ApiTest extends CompilerApiTest {
+
+    public ApiTest(Object parameters) {
+      super(parameters);
+    }
+
+    private static final Origin origin =
+        new Origin(Origin.root()) {
+          @Override
+          public String part() {
+            return "R8ApiUsageSample";
+          }
+        };
+
+    private static final DiagnosticsHandler handler = new DiagnosticsHandler() {};
+
+    @Test
+    public void test() throws IOException {
+      run(temp);
+    }
+
+    public void run(TemporaryFolder temp) throws IOException {
+      Path pgConf = temp.getRoot().toPath().resolve("rules.conf");
+      Files.write(pgConf, getKeepMainRules(getMockClass()));
+      runFromArgs(
+          new String[] {
+            "--output",
+            temp.newFolder().getAbsolutePath(),
+            "--min-api",
+            "19",
+            "--pg-conf",
+            pgConf.toString(),
+            "--lib",
+            getAndroidJar().toString(),
+            getPathForClass(getMockClass()).toString()
+          });
+    }
+
+    public void runFromArgs(String[] args) {
+      // Check version API
+      checkVersionApi();
+      // Parse arguments with the commandline parser to make use of its API.
+      R8Command.Builder cmd = R8Command.parse(args, origin);
+      CompilationMode mode = cmd.getMode();
+      Path temp = cmd.getOutputPath();
+      int minApiLevel = cmd.getMinApiLevel();
+      // The Builder API does not provide access to the concrete paths
+      // (everything is put into providers) so manually parse them here.
+      List<Path> libraries = new ArrayList<>(1);
+      List<Path> pgConf = 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("--pg-conf")) {
+          pgConf.add(Paths.get(args[++i]));
+        } else if (isArchive(args[i]) || isClassFile(args[i])) {
+          inputs.add(Paths.get(args[i]));
+        }
+      }
+      if (!Files.exists(temp) || !Files.isDirectory(temp)) {
+        throw new RuntimeException("Must supply a temp/output directory");
+      }
+      if (inputs.isEmpty()) {
+        throw new RuntimeException("Must supply program inputs");
+      }
+      if (libraries.isEmpty()) {
+        throw new RuntimeException("Must supply library inputs");
+      }
+      if (pgConf.isEmpty()) {
+        throw new RuntimeException("Must supply pg-conf inputs");
+      }
+
+      useProgramFileList(CompilationMode.DEBUG, minApiLevel, libraries, inputs);
+      useProgramFileList(CompilationMode.RELEASE, minApiLevel, libraries, inputs);
+      useProgramData(minApiLevel, libraries, inputs);
+      useProgramResourceProvider(minApiLevel, libraries, inputs);
+      useLibraryResourceProvider(minApiLevel, libraries, inputs);
+      useProguardConfigFiles(minApiLevel, libraries, inputs, pgConf);
+      useProguardConfigLines(minApiLevel, libraries, inputs, pgConf);
+      useAssertionConfig(minApiLevel, libraries, inputs);
+      useVArgVariants(minApiLevel, libraries, inputs, pgConf);
+      useProguardConfigConsumers(minApiLevel, libraries, inputs, pgConf);
+    }
+
+    private static class InMemoryStringConsumer implements StringConsumer {
+
+      public String value = null;
+
+      @Override
+      public void accept(String string, DiagnosticsHandler handler) {
+        value = string;
+      }
+    }
+
+    private static void useProguardConfigConsumers(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs, List<Path> pgConf) {
+      InMemoryStringConsumer usageConsumer = new InMemoryStringConsumer();
+      InMemoryStringConsumer seedsConsumer = new InMemoryStringConsumer();
+      InMemoryStringConsumer configConsumer = new InMemoryStringConsumer();
+      try {
+        R8.run(
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs)
+                .addProguardConfigurationFiles(pgConf)
+                .setProguardUsageConsumer(usageConsumer)
+                .setProguardSeedsConsumer(seedsConsumer)
+                .setProguardConfigurationConsumer(configConsumer)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exception", e);
+      }
+      if (usageConsumer.value == null) {
+        throw new RuntimeException("Expected usage info but had none");
+      }
+      if (seedsConsumer.value == null) {
+        throw new RuntimeException("Expected seeds info but had none");
+      }
+      if (configConsumer.value == null) {
+        throw new RuntimeException("Expected config info but had none");
+      }
+    }
+
+    // Check API support for compiling Java class-files from the file system.
+    private static void useProgramFileList(
+        CompilationMode mode,
+        int minApiLevel,
+        Collection<Path> libraries,
+        Collection<Path> inputs) {
+      try {
+        R8.run(
+            R8Command.builder(handler)
+                .setMode(mode)
+                .setMinApiLevel(minApiLevel)
+                .setDisableTreeShaking(true)
+                .setDisableMinification(true)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    // Check API support for compiling Java class-files from byte content.
+    private static void useProgramData(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
+      try {
+        R8Command.Builder builder =
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setDisableTreeShaking(true)
+                .setDisableMinification(true)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries);
+        for (ClassFileContent classfile : readClassFiles(inputs)) {
+          builder.addClassProgramData(classfile.data, classfile.origin);
+        }
+        R8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      } catch (IOException e) {
+        throw new RuntimeException("Unexpected IO exception", e);
+      }
+    }
+
+    // Check API support for compiling Java class-files from a program provider abstraction.
+    private static void useProgramResourceProvider(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
+      try {
+        R8Command.Builder builder =
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setDisableTreeShaking(true)
+                .setDisableMinification(true)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries);
+        for (Path input : inputs) {
+          if (isArchive(input)) {
+            builder.addProgramResourceProvider(
+                ArchiveProgramResourceProvider.fromArchive(
+                    input, ArchiveProgramResourceProvider::includeClassFileEntries));
+          } else {
+            builder.addProgramResourceProvider(
+                new ProgramResourceProvider() {
+                  @Override
+                  public Collection<ProgramResource> getProgramResources()
+                      throws ResourceException {
+                    return Collections.singleton(ProgramResource.fromFile(Kind.CF, input));
+                  }
+                });
+          }
+        }
+        R8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    private static void useLibraryResourceProvider(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
+      try {
+        R8Command.Builder builder =
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setDisableTreeShaking(true)
+                .setDisableMinification(true)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addProgramFiles(inputs);
+        for (Path library : libraries) {
+          builder.addLibraryResourceProvider(new ArchiveClassFileProvider(library));
+        }
+        R8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      } catch (IOException e) {
+        throw new RuntimeException("Unexpected IO exception", e);
+      }
+    }
+
+    private static void useProguardConfigFiles(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs, List<Path> pgConf) {
+      try {
+        R8.run(
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs)
+                .addProguardConfigurationFiles(pgConf)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    private static void useProguardConfigLines(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs, List<Path> pgConf) {
+      try {
+        R8Command.Builder builder =
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs);
+        for (Path file : pgConf) {
+          builder.addProguardConfiguration(Files.readAllLines(file), new PathOrigin(file));
+        }
+        R8.run(builder.build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      } catch (IOException e) {
+        throw new RuntimeException("Unexpected IO exception", e);
+      }
+    }
+
+    private static void useAssertionConfig(
+        int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
+      String pkg = "com.android.tools.r8.compilerapi.sampleapi";
+      try {
+        R8.run(
+            R8Command.builder(handler)
+                .setDisableTreeShaking(true)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries)
+                .addProgramFiles(inputs)
+                .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeEnable().build())
+                .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeDisable().build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopePackage(pkg).setCompileTimeEnable().build())
+                .addAssertionsConfiguration(b -> b.setScopePackage(pkg).setPassthrough().build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopePackage(pkg).setCompileTimeDisable().build())
+                .addAssertionsConfiguration(
+                    b ->
+                        b.setScopeClass(pkg + "R8ApiUsageSampleTest")
+                            .setCompileTimeEnable()
+                            .build())
+                .addAssertionsConfiguration(
+                    b -> b.setScopeClass(pkg + "R8ApiUsageSampleTest").setPassthrough().build())
+                .addAssertionsConfiguration(
+                    b ->
+                        b.setScopeClass(pkg + "R8ApiUsageSampleTest")
+                            .setCompileTimeDisable()
+                            .build())
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::compileTimeEnableAllAssertions)
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::passthroughAllAssertions)
+                .addAssertionsConfiguration(
+                    AssertionsConfiguration.Builder::compileTimeDisableAllAssertions)
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    // Check API support for all the varg variants.
+    private static void useVArgVariants(
+        int minApiLevel, List<Path> libraries, List<Path> inputs, List<Path> pgConf) {
+      try {
+        R8.run(
+            R8Command.builder(handler)
+                .setMinApiLevel(minApiLevel)
+                .setProgramConsumer(new EnsureOutputConsumer())
+                .addLibraryFiles(libraries.get(0))
+                .addLibraryFiles(libraries.stream().skip(1).toArray(Path[]::new))
+                .addProgramFiles(inputs.get(0))
+                .addProgramFiles(inputs.stream().skip(1).toArray(Path[]::new))
+                .addProguardConfigurationFiles(pgConf.get(0))
+                .addProguardConfigurationFiles(pgConf.stream().skip(1).toArray(Path[]::new))
+                .build());
+      } catch (CompilationFailedException e) {
+        throw new RuntimeException("Unexpected compilation exceptions", e);
+      }
+    }
+
+    // Helpers for tests.
+    // Some of this reimplements stuff in R8 utils, but that is not public API and we should not
+    // rely on it.
+
+    private static List<ClassFileContent> readClassFiles(Collection<Path> files)
+        throws IOException {
+      List<ClassFileContent> classfiles = new ArrayList<>();
+      for (Path file : files) {
+        if (isArchive(file)) {
+          Origin zipOrigin = new PathOrigin(file);
+          ZipInputStream zip =
+              new ZipInputStream(Files.newInputStream(file), StandardCharsets.UTF_8);
+          ZipEntry entry;
+          while (null != (entry = zip.getNextEntry())) {
+            String name = entry.getName();
+            if (isClassFile(name)) {
+              Origin origin = new ArchiveEntryOrigin(name, zipOrigin);
+              classfiles.add(new ClassFileContent(origin, readBytes(zip)));
+            }
+          }
+        } else if (isClassFile(file)) {
+          classfiles.add(new ClassFileContent(new PathOrigin(file), Files.readAllBytes(file)));
+        }
+      }
+      return classfiles;
+    }
+
+    private static byte[] readBytes(InputStream stream) throws IOException {
+      try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
+        byte[] buffer = new byte[0xffff];
+        for (int length; (length = stream.read(buffer)) != -1; ) {
+          bytes.write(buffer, 0, length);
+        }
+        return bytes.toByteArray();
+      }
+    }
+
+    private static String toLowerCase(String str) {
+      return str.toLowerCase(Locale.ROOT);
+    }
+
+    private static boolean isClassFile(Path file) {
+      return isClassFile(file.toString());
+    }
+
+    private static boolean isClassFile(String file) {
+      file = toLowerCase(file);
+      return file.endsWith(".class");
+    }
+
+    private static boolean isArchive(Path file) {
+      return isArchive(file.toString());
+    }
+
+    private static boolean isArchive(String file) {
+      file = toLowerCase(file);
+      return file.endsWith(".zip") || file.endsWith(".jar");
+    }
+
+    private static class ClassFileContent {
+
+      final Origin origin;
+      final byte[] data;
+
+      public ClassFileContent(Origin origin, byte[] data) {
+        this.origin = origin;
+        this.data = data;
+      }
+    }
+
+    private static class EnsureOutputConsumer implements DexIndexedConsumer {
+
+      boolean hasOutput = false;
+
+      @Override
+      public synchronized void accept(
+          int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
+        hasOutput = true;
+      }
+
+      @Override
+      public void finished(DiagnosticsHandler handler) {
+        if (!hasOutput) {
+          handler.error(new StringDiagnostic("Expected to produce output but had none"));
+        }
+      }
+    }
+
+    private static void checkVersionApi() {
+      String labelValue;
+      int labelAccess;
+      try {
+        Field field = Version.class.getDeclaredField("LABEL");
+        labelAccess = field.getModifiers();
+        labelValue = (String) field.get(Version.class);
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+      if (!Modifier.isPublic(labelAccess)
+          || !Modifier.isStatic(labelAccess)
+          || !Modifier.isFinal(labelAccess)) {
+        throw new RuntimeException("Expected public static final LABEL");
+      }
+      if (labelValue.isEmpty()) {
+        throw new RuntimeException("Expected LABEL constant");
+      }
+      if (Version.LABEL.isEmpty()) {
+        throw new RuntimeException("Expected LABEL constant");
+      }
+      if (Version.getVersionString() == null) {
+        throw new RuntimeException("Expected getVersionString API");
+      }
+      if (Version.getMajorVersion() < -1) {
+        throw new RuntimeException("Expected getMajorVersion API");
+      }
+      if (Version.getMinorVersion() < -1) {
+        throw new RuntimeException("Expected getMinorVersion API");
+      }
+      if (Version.getPatchVersion() < -1) {
+        throw new RuntimeException("Expected getPatchVersion API");
+      }
+      if (Version.getPreReleaseString() == null && false) {
+        throw new RuntimeException("Expected getPreReleaseString API");
+      }
+      if (Version.isDevelopmentVersion() && false) {
+        throw new RuntimeException("Expected isDevelopmentVersion API");
+      }
+    }
+  }
+}
diff --git a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
index d3481a6..1d1ede2 100644
--- a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
@@ -211,9 +211,6 @@
   public static final String ASM_JAR = BUILD_DIR + "deps/asm-9.6.jar";
   public static final String ASM_UTIL_JAR = BUILD_DIR + "deps/asm-util-9.6.jar";
 
-  public static final Path API_SAMPLE_JAR =
-      Paths.get(getProjectRoot(), "tests", "r8_api_usage_sample.jar");
-
   public static final String LINE_SEPARATOR = StringUtils.LINE_SEPARATOR;
   public static final String CLASSPATH_SEPARATOR = File.pathSeparator;
 
diff --git a/tests/r8_api_usage_sample.jar b/tests/r8_api_usage_sample.jar
deleted file mode 100644
index 61fd5f8..0000000
--- a/tests/r8_api_usage_sample.jar
+++ /dev/null
Binary files differ
diff --git a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1 b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
index 009f4e4..d5d2cf4 100644
--- a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
+++ b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
@@ -1 +1 @@
-9de592304071fa794e07e9e8d955aa4ae62cdef1
\ No newline at end of file
+02211ea3af0536a2e074154e513c222f31e1514c
\ No newline at end of file