1use clap::{arg, Arg, ArgAction, Command}; 2 3#[test] 4fn opt_missing() { 5 let r = Command::new("df") 6 .arg( 7 Arg::new("color") 8 .long("color") 9 .default_value("auto") 10 .num_args(0..=1) 11 .require_equals(true) 12 .default_missing_value("always"), 13 ) 14 .try_get_matches_from(vec![""]); 15 assert!(r.is_ok(), "{}", r.unwrap_err()); 16 let m = r.unwrap(); 17 assert!(m.contains_id("color")); 18 assert_eq!( 19 m.get_one::<String>("color").map(|v| v.as_str()).unwrap(), 20 "auto" 21 ); 22 assert_eq!( 23 m.value_source("color").unwrap(), 24 clap::parser::ValueSource::DefaultValue 25 ); 26 assert_eq!(m.index_of("color"), Some(1)); 27} 28 29#[test] 30fn opt_present_with_missing_value() { 31 let r = Command::new("df") 32 .arg( 33 Arg::new("color") 34 .long("color") 35 .default_value("auto") 36 .num_args(0..=1) 37 .require_equals(true) 38 .default_missing_value("always"), 39 ) 40 .try_get_matches_from(vec!["", "--color"]); 41 assert!(r.is_ok(), "{}", r.unwrap_err()); 42 let m = r.unwrap(); 43 assert!(m.contains_id("color")); 44 assert_eq!( 45 m.get_one::<String>("color").map(|v| v.as_str()).unwrap(), 46 "always" 47 ); 48 assert_eq!( 49 m.value_source("color").unwrap(), 50 clap::parser::ValueSource::CommandLine 51 ); 52 assert_eq!(m.index_of("color"), Some(2)); 53} 54 55#[test] 56fn opt_present_with_value() { 57 let r = Command::new("df") 58 .arg( 59 Arg::new("color") 60 .long("color") 61 .default_value("auto") 62 .num_args(0..=1) 63 .require_equals(true) 64 .default_missing_value("always"), 65 ) 66 .try_get_matches_from(vec!["", "--color=never"]); 67 assert!(r.is_ok(), "{}", r.unwrap_err()); 68 let m = r.unwrap(); 69 assert!(m.contains_id("color")); 70 assert_eq!( 71 m.get_one::<String>("color").map(|v| v.as_str()).unwrap(), 72 "never" 73 ); 74 assert_eq!( 75 m.value_source("color").unwrap(), 76 clap::parser::ValueSource::CommandLine 77 ); 78 assert_eq!(m.index_of("color"), Some(2)); 79} 80 81#[test] 82fn opt_present_with_empty_value() { 83 let r = Command::new("df") 84 .arg( 85 Arg::new("color") 86 .long("color") 87 .default_value("auto") 88 .require_equals(true) 89 .default_missing_value("always"), 90 ) 91 .try_get_matches_from(vec!["", "--color="]); 92 assert!(r.is_ok(), "{}", r.unwrap_err()); 93 let m = r.unwrap(); 94 assert!(m.contains_id("color")); 95 assert_eq!( 96 m.get_one::<String>("color").map(|v| v.as_str()).unwrap(), 97 "" 98 ); 99 assert_eq!( 100 m.value_source("color").unwrap(), 101 clap::parser::ValueSource::CommandLine 102 ); 103 assert_eq!(m.index_of("color"), Some(2)); 104} 105 106//## `default_value`/`default_missing_value` non-interaction checks 107 108#[test] 109fn opt_default() { 110 // assert no change to usual argument handling when adding default_missing_value() 111 let r = Command::new("cmd") 112 .arg( 113 arg!(o: -o [opt] "some opt") 114 .default_value("default") 115 .default_missing_value("default_missing"), 116 ) 117 .try_get_matches_from(vec![""]); 118 assert!(r.is_ok(), "{}", r.unwrap_err()); 119 let m = r.unwrap(); 120 assert!(m.contains_id("o")); 121 assert_eq!( 122 m.get_one::<String>("o").map(|v| v.as_str()).unwrap(), 123 "default" 124 ); 125} 126 127#[test] 128fn opt_default_user_override() { 129 // assert no change to usual argument handling when adding default_missing_value() 130 let r = Command::new("cmd") 131 .arg( 132 arg!(o: -o [opt] "some opt") 133 .default_value("default") 134 .default_missing_value("default_missing"), 135 ) 136 .try_get_matches_from(vec!["", "-o=value"]); 137 assert!(r.is_ok(), "{}", r.unwrap_err()); 138 let m = r.unwrap(); 139 assert!(m.contains_id("o")); 140 assert_eq!( 141 m.get_one::<String>("o").map(|v| v.as_str()).unwrap(), 142 "value" 143 ); 144} 145 146#[test] 147fn default_missing_value_per_occurrence() { 148 // assert no change to usual argument handling when adding default_missing_value() 149 let r = Command::new("cmd") 150 .arg( 151 arg!(o: -o [opt] ... "some opt") 152 .default_value("default") 153 .default_missing_value("default_missing"), 154 ) 155 .try_get_matches_from(vec!["", "-o", "-o=value", "-o"]); 156 assert!(r.is_ok(), "{}", r.unwrap_err()); 157 let m = r.unwrap(); 158 assert_eq!( 159 m.get_many::<String>("o") 160 .unwrap() 161 .map(|v| v.as_str()) 162 .collect::<Vec<_>>(), 163 vec!["default_missing", "value", "default_missing"] 164 ); 165} 166 167#[test] 168#[allow(clippy::bool_assert_comparison)] 169fn default_missing_value_flag_value() { 170 let cmd = Command::new("test").arg( 171 Arg::new("flag") 172 .long("flag") 173 .action(ArgAction::Set) 174 .num_args(0..=1) 175 .default_value("false") 176 .default_missing_value("true"), 177 ); 178 179 let m = cmd.clone().try_get_matches_from(["test"]).unwrap(); 180 assert!(m.contains_id("flag")); 181 assert_eq!( 182 m.get_one::<String>("flag").map(|v| v.as_str()), 183 Some("false") 184 ); 185 assert_eq!( 186 m.value_source("flag").unwrap(), 187 clap::parser::ValueSource::DefaultValue 188 ); 189 190 let m = cmd 191 .clone() 192 .try_get_matches_from(["test", "--flag"]) 193 .unwrap(); 194 assert!(m.contains_id("flag")); 195 assert_eq!( 196 m.get_one::<String>("flag").map(|v| v.as_str()), 197 Some("true") 198 ); 199 assert_eq!( 200 m.value_source("flag").unwrap(), 201 clap::parser::ValueSource::CommandLine 202 ); 203 204 let m = cmd 205 .clone() 206 .try_get_matches_from(["test", "--flag=true"]) 207 .unwrap(); 208 assert!(m.contains_id("flag")); 209 assert_eq!( 210 m.get_one::<String>("flag").map(|v| v.as_str()), 211 Some("true") 212 ); 213 assert_eq!( 214 m.value_source("flag").unwrap(), 215 clap::parser::ValueSource::CommandLine 216 ); 217 218 let m = cmd.try_get_matches_from(["test", "--flag=false"]).unwrap(); 219 assert!(m.contains_id("flag")); 220 assert_eq!( 221 m.get_one::<String>("flag").map(|v| v.as_str()), 222 Some("false") 223 ); 224 assert_eq!( 225 m.value_source("flag").unwrap(), 226 clap::parser::ValueSource::CommandLine 227 ); 228} 229 230#[test] 231fn delimited_missing_value() { 232 let cmd = Command::new("test").arg( 233 Arg::new("flag") 234 .long("flag") 235 .default_value("one,two") 236 .default_missing_value("three,four") 237 .num_args(0..) 238 .value_delimiter(',') 239 .require_equals(true), 240 ); 241 242 let m = cmd.clone().try_get_matches_from(["test"]).unwrap(); 243 assert_eq!( 244 m.get_many::<String>("flag") 245 .unwrap() 246 .map(|s| s.as_str()) 247 .collect::<Vec<_>>(), 248 vec!["one", "two"] 249 ); 250 251 let m = cmd.try_get_matches_from(["test", "--flag"]).unwrap(); 252 assert_eq!( 253 m.get_many::<String>("flag") 254 .unwrap() 255 .map(|s| s.as_str()) 256 .collect::<Vec<_>>(), 257 vec!["three", "four"] 258 ); 259} 260 261#[cfg(debug_assertions)] 262#[test] 263#[cfg(feature = "error-context")] 264#[should_panic = "Argument `arg`'s default_missing_value=\"value\" failed validation: error: invalid value 'value' for '[arg]'"] 265fn default_missing_values_are_possible_values() { 266 use clap::{Arg, Command}; 267 268 let _ = Command::new("test") 269 .arg( 270 Arg::new("arg") 271 .value_parser(["one", "two"]) 272 .default_missing_value("value"), 273 ) 274 .try_get_matches(); 275} 276 277#[cfg(debug_assertions)] 278#[test] 279#[cfg(feature = "error-context")] 280#[should_panic = "Argument `arg`'s default_missing_value=\"value\" failed validation: error: invalid value 'value' for '[arg]"] 281fn default_missing_values_are_valid() { 282 use clap::{Arg, Command}; 283 284 let _ = Command::new("test") 285 .arg( 286 Arg::new("arg") 287 .value_parser(clap::value_parser!(u32)) 288 .default_missing_value("value"), 289 ) 290 .try_get_matches(); 291} 292 293#[test] 294fn valid_index() { 295 let m = Command::new("df") 296 .arg( 297 Arg::new("color") 298 .long("color") 299 .default_value("auto") 300 .num_args(0..=1) 301 .require_equals(true) 302 .default_missing_value("always"), 303 ) 304 .arg(Arg::new("sync").long("sync").action(ArgAction::SetTrue)) 305 .try_get_matches_from(vec!["df", "--color", "--sync"]) 306 .unwrap(); 307 assert!(m.contains_id("color")); 308 assert_eq!( 309 m.get_one::<String>("color").map(|v| v.as_str()).unwrap(), 310 "always" 311 ); 312 assert_eq!( 313 m.value_source("color").unwrap(), 314 clap::parser::ValueSource::CommandLine 315 ); 316 317 // Make sure the index reflects `--color`s position and not something else 318 assert_eq!(m.index_of("color"), Some(2)); 319} 320