1use clap::{arg, Arg, ArgAction, Command}; 2 3#[cfg(feature = "error-context")] 4use super::utils; 5 6#[test] 7fn flag_using_short() { 8 let m = Command::new("flag") 9 .args([ 10 arg!(-f --flag "some flag").action(ArgAction::SetTrue), 11 arg!(-c --color "some other flag").action(ArgAction::SetTrue), 12 ]) 13 .try_get_matches_from(vec!["", "-f", "-c"]) 14 .unwrap(); 15 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap")); 16 assert!(*m.get_one::<bool>("color").expect("defaulted by clap")); 17} 18 19#[test] 20fn lots_o_flags_sep() { 21 let r = Command::new("opts") 22 .args_override_self(true) 23 .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue)) 24 .try_get_matches_from(vec![ 25 "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 26 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 27 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 28 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 29 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 30 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 31 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 32 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 33 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 34 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 35 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 36 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 37 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 38 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 39 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 40 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 41 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 42 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 43 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 44 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 45 "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", 46 "-o", "-o", "-o", 47 ]); 48 assert!(r.is_ok(), "{:?}", r.unwrap_err().kind()); 49 let m = r.unwrap(); 50 assert!(m.contains_id("o")); 51 assert!(*m.get_one::<bool>("o").expect("defaulted by clap")); 52} 53 54#[test] 55fn lots_o_flags_combined() { 56 let r = Command::new("opts") 57 .args_override_self(true) 58 .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue)) 59 .try_get_matches_from(vec![ 60 "", 61 "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", 62 "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", 63 "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", 64 "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", 65 "-ooooooooooooooooooooooooooooooooooooooooo", 66 ]); 67 assert!(r.is_ok(), "{:?}", r.unwrap_err().kind()); 68 let m = r.unwrap(); 69 assert!(m.contains_id("o")); 70 assert!(*m.get_one::<bool>("o").expect("defaulted by clap")); 71} 72 73#[test] 74fn flag_using_long() { 75 let m = Command::new("flag") 76 .args([ 77 arg!(--flag "some flag").action(ArgAction::SetTrue), 78 arg!(--color "some other flag").action(ArgAction::SetTrue), 79 ]) 80 .try_get_matches_from(vec!["", "--flag", "--color"]) 81 .unwrap(); 82 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap")); 83 assert!(*m.get_one::<bool>("color").expect("defaulted by clap")); 84} 85 86#[test] 87fn flag_using_long_with_literals() { 88 use clap::error::ErrorKind; 89 90 let m = Command::new("flag") 91 .arg( 92 Arg::new("rainbow") 93 .long("rainbow") 94 .action(ArgAction::SetTrue), 95 ) 96 .try_get_matches_from(vec!["", "--rainbow=false"]); 97 assert!(m.is_err(), "{:#?}", m.unwrap()); 98 assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues); 99} 100 101#[test] 102fn flag_using_mixed() { 103 let m = Command::new("flag") 104 .args([ 105 arg!(-f --flag "some flag").action(ArgAction::SetTrue), 106 arg!(-c --color "some other flag").action(ArgAction::SetTrue), 107 ]) 108 .try_get_matches_from(vec!["", "-f", "--color"]) 109 .unwrap(); 110 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap")); 111 assert!(*m.get_one::<bool>("color").expect("defaulted by clap")); 112 113 let m = Command::new("flag") 114 .args([ 115 arg!(-f --flag "some flag").action(ArgAction::SetTrue), 116 arg!(-c --color "some other flag").action(ArgAction::SetTrue), 117 ]) 118 .try_get_matches_from(vec!["", "--flag", "-c"]) 119 .unwrap(); 120 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap")); 121 assert!(*m.get_one::<bool>("color").expect("defaulted by clap")); 122} 123 124#[test] 125fn multiple_flags_in_single() { 126 let m = Command::new("multe_flags") 127 .args([ 128 arg!(-f --flag "some flag").action(ArgAction::SetTrue), 129 arg!(-c --color "some other flag").action(ArgAction::SetTrue), 130 arg!(-d --debug "another other flag").action(ArgAction::SetTrue), 131 ]) 132 .try_get_matches_from(vec!["", "-fcd"]) 133 .unwrap(); 134 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap")); 135 assert!(*m.get_one::<bool>("color").expect("defaulted by clap")); 136 assert!(*m.get_one::<bool>("debug").expect("defaulted by clap")); 137} 138 139#[test] 140#[cfg(feature = "error-context")] 141fn unexpected_value_error() { 142 const USE_FLAG_AS_ARGUMENT: &str = "\ 143error: unexpected value 'foo' for '--a-flag' found; no more were expected 144 145Usage: mycat --a-flag [filename] 146 147For more information, try '--help'. 148"; 149 150 let cmd = Command::new("mycat") 151 .arg(Arg::new("filename")) 152 .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue)); 153 154 utils::assert_output(cmd, "mycat --a-flag=foo", USE_FLAG_AS_ARGUMENT, true); 155} 156 157#[test] 158#[cfg(feature = "error-context")] 159fn issue_1284_argument_in_flag_style() { 160 const USE_FLAG_AS_ARGUMENT: &str = "\ 161error: unexpected argument '--another-flag' found 162 163 note: to pass '--another-flag' as a value, use '-- --another-flag' 164 165Usage: mycat [OPTIONS] [filename] 166 167For more information, try '--help'. 168"; 169 170 let cmd = Command::new("mycat") 171 .arg(Arg::new("filename")) 172 .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue)); 173 174 let m = cmd 175 .clone() 176 .try_get_matches_from(vec!["", "--", "--another-flag"]) 177 .unwrap(); 178 assert_eq!( 179 m.get_one::<String>("filename").map(|v| v.as_str()), 180 Some("--another-flag") 181 ); 182 183 let m = cmd 184 .clone() 185 .try_get_matches_from(vec!["", "--a-flag"]) 186 .unwrap(); 187 assert!(*m.get_one::<bool>("a-flag").expect("defaulted by clap")); 188 189 let m = cmd 190 .clone() 191 .try_get_matches_from(vec!["", "--", "--a-flag"]) 192 .unwrap(); 193 assert_eq!( 194 m.get_one::<String>("filename").map(|v| v.as_str()), 195 Some("--a-flag") 196 ); 197 198 utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true); 199} 200 201#[test] 202#[cfg(feature = "error-context")] 203fn issue_2308_multiple_dashes() { 204 static MULTIPLE_DASHES: &str = "\ 205error: unexpected argument '-----' found 206 207 note: to pass '-----' as a value, use '-- -----' 208 209Usage: test <arg> 210 211For more information, try '--help'. 212"; 213 let cmd = Command::new("test").arg(Arg::new("arg").action(ArgAction::Set).required(true)); 214 215 utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true); 216} 217 218#[test] 219#[cfg(debug_assertions)] 220#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"] 221fn leading_dash_stripped() { 222 let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename")); 223 cmd.debug_assert(); 224} 225