Prepare for clap 4.

Bug: 260823636
Test: atest vm.test encryptedstore.test apkdmverity.test open_then_run.test ZipFuseTest
Change-Id: Iba2c4c317e7e42fc99362caf41ab083b4fc4a8db
diff --git a/authfs/tests/common/Android.bp b/authfs/tests/common/Android.bp
index ec426c7..01ebcfd 100644
--- a/authfs/tests/common/Android.bp
+++ b/authfs/tests/common/Android.bp
@@ -31,3 +31,19 @@
     test_suites: ["general-tests"],
     test_harness: false,
 }
+
+rust_test {
+    name: "open_then_run.test",
+    crate_name: "open_then_run",
+    srcs: ["src/open_then_run.rs"],
+    edition: "2021",
+    rustlibs: [
+        "libandroid_logger",
+        "libanyhow",
+        "libclap",
+        "libcommand_fds",
+        "liblibc",
+        "liblog_rust",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/authfs/tests/common/src/open_then_run.rs b/authfs/tests/common/src/open_then_run.rs
index 110d838..6d828e4 100644
--- a/authfs/tests/common/src/open_then_run.rs
+++ b/authfs/tests/common/src/open_then_run.rs
@@ -19,7 +19,7 @@
 //! specified numbers in the child process.
 
 use anyhow::{bail, Context, Result};
-use clap::{App, Arg, Values};
+use clap::{parser::ValuesRef, Arg, ArgAction};
 use command_fds::{CommandFdExt, FdMapping};
 use log::{debug, error};
 use std::fs::OpenOptions;
@@ -51,7 +51,7 @@
 }
 
 fn parse_and_create_file_mapping<F>(
-    values: Option<Values<'_>>,
+    values: Option<ValuesRef<'_, String>>,
     opener: F,
 ) -> Result<Vec<OwnedFdMapping>>
 where
@@ -75,35 +75,35 @@
     }
 }
 
-fn parse_args() -> Result<Args> {
-    #[rustfmt::skip]
-    let matches = App::new("open_then_run")
-        .arg(Arg::with_name("open-ro")
+#[rustfmt::skip]
+fn args_command() -> clap::Command {
+    clap::Command::new("open_then_run")
+        .arg(Arg::new("open-ro")
              .long("open-ro")
              .value_name("FD:PATH")
              .help("Open <PATH> read-only to pass as fd <FD>")
-             .multiple(true)
-             .number_of_values(1))
-        .arg(Arg::with_name("open-rw")
+             .action(ArgAction::Append))
+        .arg(Arg::new("open-rw")
              .long("open-rw")
              .value_name("FD:PATH")
              .help("Open/create <PATH> read-write to pass as fd <FD>")
-             .multiple(true)
-             .number_of_values(1))
-        .arg(Arg::with_name("open-dir")
+             .action(ArgAction::Append))
+        .arg(Arg::new("open-dir")
              .long("open-dir")
              .value_name("FD:DIR")
              .help("Open <DIR> to pass as fd <FD>")
-             .multiple(true)
-             .number_of_values(1))
-        .arg(Arg::with_name("args")
+             .action(ArgAction::Append))
+        .arg(Arg::new("args")
              .help("Command line to execute with pre-opened FD inherited")
              .last(true)
              .required(true)
-             .multiple(true))
-        .get_matches();
+             .num_args(0..))
+}
 
-    let ro_file_fds = parse_and_create_file_mapping(matches.values_of("open-ro"), |path| {
+fn parse_args() -> Result<Args> {
+    let matches = args_command().get_matches();
+
+    let ro_file_fds = parse_and_create_file_mapping(matches.get_many("open-ro"), |path| {
         Ok(OwnedFd::from(
             OpenOptions::new()
                 .read(true)
@@ -112,7 +112,7 @@
         ))
     })?;
 
-    let rw_file_fds = parse_and_create_file_mapping(matches.values_of("open-rw"), |path| {
+    let rw_file_fds = parse_and_create_file_mapping(matches.get_many("open-rw"), |path| {
         Ok(OwnedFd::from(
             OpenOptions::new()
                 .read(true)
@@ -123,7 +123,7 @@
         ))
     })?;
 
-    let dir_fds = parse_and_create_file_mapping(matches.values_of("open-dir"), |path| {
+    let dir_fds = parse_and_create_file_mapping(matches.get_many("open-dir"), |path| {
         Ok(OwnedFd::from(
             OpenOptions::new()
                 .custom_flags(libc::O_DIRECTORY)
@@ -133,7 +133,8 @@
         ))
     })?;
 
-    let cmdline_args: Vec<_> = matches.values_of("args").unwrap().map(|s| s.to_string()).collect();
+    let cmdline_args: Vec<_> =
+        matches.get_many::<String>("args").unwrap().map(|s| s.to_string()).collect();
 
     Ok(Args { ro_file_fds, rw_file_fds, dir_fds, cmdline_args })
 }
@@ -168,3 +169,14 @@
         std::process::exit(1);
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn verify_command() {
+        // Check that the command parsing has been configured in a valid way.
+        args_command().debug_assert();
+    }
+}