Use desugared methods command and test it

Change-Id: I203e36f185511006c3d46e37013d9667861f16fa
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsList.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsList.java
index 09f727b..49ab63a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsList.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsList.java
@@ -4,10 +4,6 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.lint;
 
-import static java.lang.Integer.parseInt;
-
-import com.android.tools.r8.ArchiveClassFileProvider;
-import com.android.tools.r8.ArchiveProgramResourceProvider;
 import com.android.tools.r8.ClassFileResourceProvider;
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.Keep;
@@ -15,14 +11,12 @@
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.StringResource;
 import com.android.tools.r8.Version;
+import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.Reporter;
-import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.ThreadUtils;
-import com.google.common.collect.ImmutableList;
 import java.io.IOException;
-import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
@@ -61,17 +55,16 @@
     try {
       ExceptionUtils.withD8CompilationHandler(
           command.getReporter(),
-          () -> {
-            new DesugaredMethodsList(
-                    command.getMinApi(),
-                    command.isAndroidPlatformBuild(),
-                    command.getReporter(),
-                    command.getDesugarLibrarySpecification(),
-                    command.getDesugarLibraryImplementation(),
-                    command.getOutputConsumer(),
-                    command.getLibrary())
-                .run();
-          });
+          () ->
+              new DesugaredMethodsList(
+                      command.getMinApi(),
+                      command.isAndroidPlatformBuild(),
+                      command.getReporter(),
+                      command.getDesugarLibrarySpecification(),
+                      command.getDesugarLibraryImplementation(),
+                      command.getOutputConsumer(),
+                      command.getLibrary())
+                  .run());
     } finally {
       executorService.shutdown();
     }
@@ -105,37 +98,18 @@
     outputConsumer.finished(options.reporter);
   }
 
-  private static StringResource getSpecificationArg(String arg) {
-    return arg == null ? null : StringResource.fromFile(Paths.get(arg));
+  public static void run(String[] args) throws CompilationFailedException, IOException {
+    run(DesugaredMethodsListCommand.parse(args));
   }
 
-  private static Collection<ProgramResourceProvider> getImplementationArg(String arg) {
-    if (arg == null) {
-      return ImmutableList.of();
-    }
-    return ImmutableList.of(ArchiveProgramResourceProvider.fromArchive(Paths.get(arg)));
-  }
-
-  public static void main(String[] args) throws Exception {
-    if (args.length == 4 || args.length == 5) {
-      DesugaredMethodsListCommand.Builder builder =
-          DesugaredMethodsListCommand.builder(new Reporter())
-              .setMinApi(parseInt(args[0]))
-              .setDesugarLibrarySpecification(getSpecificationArg(args[1]))
-              .setOutputPath(Paths.get(args[3]));
-      for (ProgramResourceProvider programResourceProvider : getImplementationArg(args[2])) {
-        builder.addDesugarLibraryImplementation(programResourceProvider);
-      }
-      builder.addLibrary(new ArchiveClassFileProvider(Paths.get(args[4])));
-      DesugaredMethodsList.run(builder.build());
-      return;
-    }
-    throw new RuntimeException(
-        StringUtils.joinLines(
-            "Invalid invocation.",
-            "Usage: DesugaredMethodList <min-api> <desugar configuration> "
-                + "<desugar implementation> <output file> <android jar path for Android "
-                + MAX_TESTED_ANDROID_API_LEVEL
-                + " or higher>"));
+  public static void main(String[] args) {
+    ExceptionUtils.withMainProgramHandler(
+        () -> {
+          try {
+            run(args);
+          } catch (IOException e) {
+            throw new CompilationError(e.getMessage(), e);
+          }
+        });
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsListCommand.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsListCommand.java
index d69cf6b..879d49a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsListCommand.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/DesugaredMethodsListCommand.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableList;
 import java.io.IOException;
@@ -72,6 +73,15 @@
     this.androidPlatformBuild = false;
   }
 
+  public static DesugaredMethodsListCommand parse(String[] args) throws IOException {
+    return parse(args, new Reporter());
+  }
+
+  public static DesugaredMethodsListCommand parse(String[] args, Reporter reporter)
+      throws IOException {
+    return new DesugaredMethodsListCommandParser().parse(args, reporter);
+  }
+
   public int getMinApi() {
     return minApi;
   }
@@ -205,12 +215,12 @@
       }
 
       if (desugarLibrarySpecification != null && library.isEmpty()) {
-        reporter.error("With desugared library configuration a library is required.");
+        reporter.error("With desugared library specification a library is required.");
       }
 
       if (!desugarLibraryImplementation.isEmpty() && desugarLibrarySpecification == null) {
         reporter.error(
-            "desugarLibrarySpecification is required when desugared library implementation is"
+            "The desugar library specification is required when desugared library implementation is"
                 + " present.");
       }
 
@@ -257,7 +267,7 @@
     public DesugaredMethodsListCommand parse(String[] args, DiagnosticsHandler handler)
         throws IOException {
       DesugaredMethodsListCommand.Builder builder = DesugaredMethodsListCommand.builder(handler);
-      for (int i = 0; i < args.length; i += 2) {
+      for (int i = 0; i < args.length; i++) {
         String arg = args[i].trim();
         if (arg.length() == 0) {
           continue;
@@ -271,7 +281,12 @@
           builder.setAndroidPlatformBuild();
           continue;
         }
-        String argValue = args[i + 1].trim();
+        i++;
+        if (i >= args.length) {
+          handler.error(new StringDiagnostic("Missing value for arg " + arg));
+          break;
+        }
+        String argValue = args[i].trim();
         if (arg.equals("--min-api")) {
           builder.setMinApi(Integer.parseInt(argValue));
         } else if (arg.equals("--desugared-lib")) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodListCommandTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodListCommandTest.java
new file mode 100644
index 0000000..092ac0b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodListCommandTest.java
@@ -0,0 +1,131 @@
+// Copyright (c) 2023, 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.desugar.desugaredlibrary;
+
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_LEGACY;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_MINIMAL;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.lint.DesugaredMethodsListCommand;
+import com.android.tools.r8.utils.Reporter;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+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 DesugaredMethodListCommandTest extends DesugaredLibraryTestBase {
+
+  private final TestParameters parameters;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+
+  @Parameters(name = "{0}, {1}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters().withDexRuntimes().build(),
+        ImmutableList.of(JDK8, JDK11_MINIMAL, JDK11, JDK11_PATH, JDK11_LEGACY));
+  }
+
+  public DesugaredMethodListCommandTest(
+      TestParameters parameters, LibraryDesugaringSpecification libraryDesugaringSpecification) {
+    this.parameters = parameters;
+    this.libraryDesugaringSpecification = libraryDesugaringSpecification;
+  }
+
+  @Test
+  public void testErrorPlatformDesugaredLibrary() throws IOException {
+    TestDiagnosticMessagesImpl diagnosticMessages = new TestDiagnosticMessagesImpl();
+    DesugaredMethodsListCommand.parse(
+        new String[] {
+          "--android-platform-build",
+          "--desugared-lib",
+          libraryDesugaringSpecification.getSpecification().toString(),
+          "--desugared-lib-jar",
+          libraryDesugaringSpecification.getDesugarJdkLibs().iterator().next().toString(),
+          "--lib",
+          ToolHelper.getAndroidJar(34).toString()
+        },
+        new Reporter(diagnosticMessages));
+    diagnosticMessages.assertErrorMessageThatMatches(
+        containsString("With platform build desugared library is not allowed."));
+    diagnosticMessages.assertOnlyErrors();
+  }
+
+  @Test
+  public void testErrorDesugaredLibraryNoLib() throws IOException {
+    TestDiagnosticMessagesImpl diagnosticMessages = new TestDiagnosticMessagesImpl();
+    DesugaredMethodsListCommand.parse(
+        new String[] {
+          "--desugared-lib", libraryDesugaringSpecification.getSpecification().toString()
+        },
+        new Reporter(diagnosticMessages));
+    diagnosticMessages.assertOnlyErrors();
+    diagnosticMessages.assertErrorMessageThatMatches(
+        containsString("With desugared library specification a library is required."));
+  }
+
+  @Test
+  public void testErrorDesugaredLibraryImplementationNoSpec() throws IOException {
+    TestDiagnosticMessagesImpl diagnosticMessages = new TestDiagnosticMessagesImpl();
+    DesugaredMethodsListCommand.parse(
+        new String[] {
+          "--desugared-lib-jar",
+          libraryDesugaringSpecification.getDesugarJdkLibs().iterator().next().toString()
+        },
+        new Reporter(diagnosticMessages));
+    diagnosticMessages.assertOnlyErrors();
+    diagnosticMessages.assertErrorMessageThatMatches(
+        containsString(
+            "The desugar library specification is required when desugared library "
+                + "implementation is present."));
+  }
+
+  @Test
+  public void testMissingArg() throws IOException {
+    TestDiagnosticMessagesImpl diagnosticMessages = new TestDiagnosticMessagesImpl();
+    DesugaredMethodsListCommand.parse(
+        new String[] {"--desugared-lib"}, new Reporter(diagnosticMessages));
+    diagnosticMessages.assertOnlyErrors();
+    diagnosticMessages.assertErrorMessageThatMatches(
+        containsString("Missing value for arg --desugared-lib"));
+  }
+
+  @Test
+  public void testFullCommand() throws Exception {
+    List<String> commandList = new ArrayList<>();
+    commandList.add("--min-api");
+    commandList.add(String.valueOf(21));
+    commandList.add("--desugared-lib");
+    commandList.add(libraryDesugaringSpecification.getSpecification().toString());
+    for (Path desugarJdkLib : libraryDesugaringSpecification.getDesugarJdkLibs()) {
+      commandList.add("--desugared-lib-jar");
+      commandList.add(desugarJdkLib.toString());
+    }
+    commandList.add("--lib");
+    commandList.add(ToolHelper.getAndroidJar(34).toString());
+    String[] commandArray = commandList.stream().toArray(String[]::new);
+    DesugaredMethodsListCommand command = DesugaredMethodsListCommand.parse(commandArray);
+    assertFalse(command.getDesugarLibraryImplementation().isEmpty());
+    assertNotNull(command.getDesugarLibrarySpecification().getString());
+    assertFalse(command.getLibrary().isEmpty());
+    assertFalse(command.isAndroidPlatformBuild());
+    assertFalse(command.isVersion());
+    assertFalse(command.isHelp());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodsListTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodsListTest.java
index 25494ca..5f29df3 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodsListTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredMethodsListTest.java
@@ -106,10 +106,15 @@
     AndroidApiLevel minApi = parameters.getRuntime().asDex().getMinApiLevel();
     DesugaredMethodsList.main(
         new String[] {
+          "--min-api",
           String.valueOf(minApi.getLevel()),
+          "--desugared-lib",
           libraryDesugaringSpecification.getSpecification().toString(),
+          "--desugared-lib-jar",
           jdkLibJar.toString(),
+          "--output",
           output.toString(),
+          "--lib",
           ToolHelper.getAndroidJar(AndroidApiLevel.U).toString()
         });
     checkFileContent(minApi, output, true, true);
@@ -154,10 +159,11 @@
     AndroidApiLevel minApi = parameters.getRuntime().asDex().getMinApiLevel();
     DesugaredMethodsList.main(
         new String[] {
+          "--min-api",
           String.valueOf(minApi.getLevel()),
-          null,
-          null,
+          "--output",
           output.toString(),
+          "--lib",
           ToolHelper.getAndroidJar(AndroidApiLevel.U).toString()
         });
     checkFileContent(minApi, output, true, false);