mod repeated_pos; mod smoke; mod subcommands; mod help; use std::{ffi::OsString, fmt}; use expect_test::{expect, Expect}; fn check(f: F, args: &str, expect: Expect) where F: FnOnce(Vec) -> xflags::Result, A: fmt::Debug, { let args = args.split_ascii_whitespace().map(OsString::from).collect::>(); let res = f(args); match res { Ok(args) => { expect.assert_debug_eq(&args); } Err(err) => { expect.assert_eq(&err.to_string()); } } } #[test] fn smoke() { check( smoke::RustAnalyzer::from_vec, "-n 92 .", expect![[r#" RustAnalyzer { workspace: ".", jobs: None, log_file: None, verbose: 0, number: 92, data: [], emoji: false, } "#]], ); check( smoke::RustAnalyzer::from_vec, "-n 92 -v --verbose -v --data 0xDEAD --log-file /tmp/log.txt --data 0xBEEF .", expect![[r#" RustAnalyzer { workspace: ".", jobs: None, log_file: Some( "/tmp/log.txt", ), verbose: 3, number: 92, data: [ "0xDEAD", "0xBEEF", ], emoji: false, } "#]], ); check( smoke::RustAnalyzer::from_vec, "-n 92 --werbose", expect![[r#"unexpected flag: `--werbose`"#]], ); check(smoke::RustAnalyzer::from_vec, "", expect!["flag is required: `--number`"]); check(smoke::RustAnalyzer::from_vec, ".", expect![[r#"flag is required: `--number`"#]]); check(smoke::RustAnalyzer::from_vec, "-n", expect![[r#"expected a value for `-n`"#]]); check(smoke::RustAnalyzer::from_vec, "-n 92", expect!["flag is required: `workspace`"]); check( smoke::RustAnalyzer::from_vec, "-n lol", expect![[r#"can't parse `-n`, invalid digit found in string"#]], ); check( smoke::RustAnalyzer::from_vec, "-n 1 -n 2 .", expect![[r#"flag specified more than once: `--number`"#]], ); check( smoke::RustAnalyzer::from_vec, "-n 1 . 92 lol", expect![[r#"unexpected argument: "lol""#]], ); check( smoke::RustAnalyzer::from_vec, "-n 1 . --emoji --emoji", expect![[r#"flag specified more than once: `--emoji`"#]], ); } #[test] fn repeated_argument() { check( repeated_pos::RepeatedPos::from_vec, "a 11 c d e f", expect![[r#" RepeatedPos { a: "a", b: Some( 11, ), c: Some( "c", ), rest: [ "d", "e", "f", ], } "#]], ); } #[test] fn subcommands() { check( subcommands::RustAnalyzer::from_vec, "server", expect![[r#" RustAnalyzer { verbose: 0, subcommand: Server( Server { dir: None, subcommand: Launch( Launch { log: false, }, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "server --dir . --log", expect![[r#" RustAnalyzer { verbose: 0, subcommand: Server( Server { dir: Some( ".", ), subcommand: Launch( Launch { log: true, }, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "server watch", expect![[r#" RustAnalyzer { verbose: 0, subcommand: Server( Server { dir: None, subcommand: Watch( Watch, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "-v analysis-stats . --parallel", expect![[r#" RustAnalyzer { verbose: 1, subcommand: AnalysisStats( AnalysisStats { path: ".", parallel: true, }, ), } "#]], ); check(subcommands::RustAnalyzer::from_vec, "", expect![[r#"subcommand is required"#]]); } #[test] fn subcommand_flag_inheritance() { check( subcommands::RustAnalyzer::from_vec, "server watch --verbose --dir .", expect![[r#" RustAnalyzer { verbose: 1, subcommand: Server( Server { dir: Some( ".", ), subcommand: Watch( Watch, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "analysis-stats --verbose --dir .", expect!["unexpected flag: `--dir`"], ); check( subcommands::RustAnalyzer::from_vec, "--dir . server", expect!["unexpected flag: `--dir`"], ); } #[test] fn edge_cases() { check( subcommands::RustAnalyzer::from_vec, "server --dir --log", expect![[r#" RustAnalyzer { verbose: 0, subcommand: Server( Server { dir: Some( "--log", ), subcommand: Launch( Launch { log: false, }, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "server --dir -- --log", expect![[r#" RustAnalyzer { verbose: 0, subcommand: Server( Server { dir: Some( "--", ), subcommand: Launch( Launch { log: true, }, ), }, ), } "#]], ); check( subcommands::RustAnalyzer::from_vec, "-- -v server", expect![[r#"unexpected argument: "-v""#]], ); check(repeated_pos::RepeatedPos::from_vec, "pos 1 prog -j", expect!["unexpected flag: `-j`"]); check( repeated_pos::RepeatedPos::from_vec, "pos 1 -- prog -j", expect![[r#" RepeatedPos { a: "pos", b: Some( 1, ), c: Some( "prog", ), rest: [ "-j", ], } "#]], ); }