1#![cfg(not(windows))] 2 3use clap::{arg, error::ErrorKind, value_parser, Arg, ArgAction, Command}; 4use std::ffi::OsString; 5use std::os::unix::ffi::OsStringExt; 6 7#[test] 8fn invalid_utf8_strict_positional() { 9 let m = Command::new("bad_utf8") 10 .arg(Arg::new("arg")) 11 .try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); 12 assert!(m.is_err()); 13 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 14} 15 16#[test] 17fn invalid_utf8_strict_option_short_space() { 18 let m = Command::new("bad_utf8") 19 .arg( 20 Arg::new("arg") 21 .short('a') 22 .long("arg") 23 .action(ArgAction::Set), 24 ) 25 .try_get_matches_from(vec![ 26 OsString::from(""), 27 OsString::from("-a"), 28 OsString::from_vec(vec![0xe9]), 29 ]); 30 assert!(m.is_err()); 31 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 32} 33 34#[test] 35fn invalid_utf8_strict_option_short_equals() { 36 let m = Command::new("bad_utf8") 37 .arg( 38 Arg::new("arg") 39 .short('a') 40 .long("arg") 41 .action(ArgAction::Set), 42 ) 43 .try_get_matches_from(vec![ 44 OsString::from(""), 45 OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]), 46 ]); 47 assert!(m.is_err()); 48 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 49} 50 51#[test] 52fn invalid_utf8_strict_option_short_no_space() { 53 let m = Command::new("bad_utf8") 54 .arg( 55 Arg::new("arg") 56 .short('a') 57 .long("arg") 58 .action(ArgAction::Set), 59 ) 60 .try_get_matches_from(vec![ 61 OsString::from(""), 62 OsString::from_vec(vec![0x2d, 0x61, 0xe9]), 63 ]); 64 assert!(m.is_err()); 65 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 66} 67 68#[test] 69fn invalid_utf8_strict_option_long_space() { 70 let m = Command::new("bad_utf8") 71 .arg( 72 Arg::new("arg") 73 .short('a') 74 .long("arg") 75 .action(ArgAction::Set), 76 ) 77 .try_get_matches_from(vec![ 78 OsString::from(""), 79 OsString::from("--arg"), 80 OsString::from_vec(vec![0xe9]), 81 ]); 82 assert!(m.is_err()); 83 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 84} 85 86#[test] 87fn invalid_utf8_strict_option_long_equals() { 88 let m = Command::new("bad_utf8") 89 .arg( 90 Arg::new("arg") 91 .short('a') 92 .long("arg") 93 .action(ArgAction::Set), 94 ) 95 .try_get_matches_from(vec![ 96 OsString::from(""), 97 OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]), 98 ]); 99 assert!(m.is_err()); 100 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 101} 102 103#[test] 104fn invalid_utf8_strict_invalid_short() { 105 let m = Command::new("bad_utf8").try_get_matches_from(vec![ 106 OsString::from(""), 107 OsString::from("-a"), 108 OsString::from_vec(vec![0xe9]), 109 ]); 110 assert!(m.is_err()); 111 assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument); 112} 113 114#[test] 115fn invalid_utf8_strict_invalid_long() { 116 let m = Command::new("bad_utf8").try_get_matches_from(vec![ 117 OsString::from(""), 118 OsString::from("--arg"), 119 OsString::from_vec(vec![0xe9]), 120 ]); 121 assert!(m.is_err()); 122 assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument); 123} 124 125#[test] 126fn invalid_utf8_positional() { 127 let r = Command::new("bad_utf8") 128 .arg(Arg::new("arg").value_parser(value_parser!(OsString))) 129 .try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); 130 assert!(r.is_ok(), "{}", r.unwrap_err()); 131 let m = r.unwrap(); 132 assert!(m.contains_id("arg")); 133 assert_eq!( 134 m.get_one::<OsString>("arg").unwrap(), 135 &*OsString::from_vec(vec![0xe9]) 136 ); 137} 138 139#[test] 140fn invalid_utf8_option_short_space() { 141 let r = Command::new("bad_utf8") 142 .arg( 143 Arg::new("arg") 144 .short('a') 145 .long("arg") 146 .action(ArgAction::Set) 147 .value_parser(value_parser!(OsString)), 148 ) 149 .try_get_matches_from(vec![ 150 OsString::from(""), 151 OsString::from("-a"), 152 OsString::from_vec(vec![0xe9]), 153 ]); 154 assert!(r.is_ok(), "{}", r.unwrap_err()); 155 let m = r.unwrap(); 156 assert!(m.contains_id("arg")); 157 assert_eq!( 158 m.get_one::<OsString>("arg").unwrap(), 159 &*OsString::from_vec(vec![0xe9]) 160 ); 161} 162 163#[test] 164fn invalid_utf8_option_short_equals() { 165 let r = Command::new("bad_utf8") 166 .arg( 167 Arg::new("arg") 168 .short('a') 169 .long("arg") 170 .action(ArgAction::Set) 171 .value_parser(value_parser!(OsString)), 172 ) 173 .try_get_matches_from(vec![ 174 OsString::from(""), 175 OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]), 176 ]); 177 assert!(r.is_ok(), "{}", r.unwrap_err()); 178 let m = r.unwrap(); 179 assert!(m.contains_id("arg")); 180 assert_eq!( 181 m.get_one::<OsString>("arg").unwrap(), 182 &*OsString::from_vec(vec![0xe9]) 183 ); 184} 185 186#[test] 187fn invalid_utf8_option_short_no_space() { 188 let r = Command::new("bad_utf8") 189 .arg( 190 Arg::new("arg") 191 .short('a') 192 .long("arg") 193 .action(ArgAction::Set) 194 .value_parser(value_parser!(OsString)), 195 ) 196 .try_get_matches_from(vec![ 197 OsString::from(""), 198 OsString::from_vec(vec![0x2d, 0x61, 0xe9]), 199 ]); 200 assert!(r.is_ok(), "{}", r.unwrap_err()); 201 let m = r.unwrap(); 202 assert!(m.contains_id("arg")); 203 assert_eq!( 204 m.get_one::<OsString>("arg").unwrap(), 205 &*OsString::from_vec(vec![0xe9]) 206 ); 207} 208 209#[test] 210fn invalid_utf8_option_long_space() { 211 let r = Command::new("bad_utf8") 212 .arg( 213 Arg::new("arg") 214 .short('a') 215 .long("arg") 216 .action(ArgAction::Set) 217 .value_parser(value_parser!(OsString)), 218 ) 219 .try_get_matches_from(vec![ 220 OsString::from(""), 221 OsString::from("--arg"), 222 OsString::from_vec(vec![0xe9]), 223 ]); 224 assert!(r.is_ok(), "{}", r.unwrap_err()); 225 let m = r.unwrap(); 226 assert!(m.contains_id("arg")); 227 assert_eq!( 228 m.get_one::<OsString>("arg").unwrap(), 229 &*OsString::from_vec(vec![0xe9]) 230 ); 231} 232 233#[test] 234fn invalid_utf8_option_long_equals() { 235 let r = Command::new("bad_utf8") 236 .arg( 237 Arg::new("arg") 238 .short('a') 239 .long("arg") 240 .action(ArgAction::Set) 241 .value_parser(value_parser!(OsString)), 242 ) 243 .try_get_matches_from(vec![ 244 OsString::from(""), 245 OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]), 246 ]); 247 assert!(r.is_ok(), "{}", r.unwrap_err()); 248 let m = r.unwrap(); 249 assert!(m.contains_id("arg")); 250 assert_eq!( 251 m.get_one::<OsString>("arg").unwrap(), 252 &*OsString::from_vec(vec![0xe9]) 253 ); 254} 255 256#[test] 257fn refuse_invalid_utf8_subcommand_with_allow_external_subcommands() { 258 let m = Command::new("bad_utf8") 259 .allow_external_subcommands(true) 260 .external_subcommand_value_parser(value_parser!(String)) 261 .try_get_matches_from(vec![ 262 OsString::from(""), 263 OsString::from_vec(vec![0xe9]), 264 OsString::from("normal"), 265 ]); 266 assert!(m.is_err()); 267 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 268} 269 270#[test] 271fn refuse_invalid_utf8_subcommand_when_args_are_allowed_with_allow_external_subcommands() { 272 let m = Command::new("bad_utf8") 273 .allow_external_subcommands(true) 274 .try_get_matches_from(vec![ 275 OsString::from(""), 276 OsString::from_vec(vec![0xe9]), 277 OsString::from("normal"), 278 ]); 279 assert!(m.is_err()); 280 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 281} 282 283#[test] 284fn refuse_invalid_utf8_subcommand_args_with_allow_external_subcommands() { 285 let m = Command::new("bad_utf8") 286 .allow_external_subcommands(true) 287 .external_subcommand_value_parser(value_parser!(String)) 288 .try_get_matches_from(vec![ 289 OsString::from(""), 290 OsString::from("subcommand"), 291 OsString::from("normal"), 292 OsString::from_vec(vec![0xe9]), 293 OsString::from("--another_normal"), 294 ]); 295 assert!(m.is_err()); 296 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 297} 298 299#[test] 300fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() { 301 let m = Command::new("bad_utf8") 302 .allow_external_subcommands(true) 303 .try_get_matches_from(vec![ 304 OsString::from(""), 305 OsString::from("subcommand"), 306 OsString::from("normal"), 307 OsString::from_vec(vec![0xe9]), 308 OsString::from("--another_normal"), 309 ]); 310 assert!(m.is_ok(), "{}", m.unwrap_err()); 311 let m = m.unwrap(); 312 let (subcommand, args) = m.subcommand().unwrap(); 313 let args = args 314 .get_many::<OsString>("") 315 .unwrap() 316 .cloned() 317 .collect::<Vec<_>>(); 318 assert_eq!(subcommand, OsString::from("subcommand")); 319 assert_eq!( 320 args, 321 vec![ 322 OsString::from("normal"), 323 OsString::from_vec(vec![0xe9]), 324 OsString::from("--another_normal"), 325 ] 326 ); 327} 328 329#[test] 330fn allow_validated_utf8_value_of() { 331 let a = Command::new("test").arg(arg!(--name <NAME>)); 332 let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); 333 let _ = m.get_one::<String>("name").map(|v| v.as_str()); 334} 335 336#[test] 337fn allow_validated_utf8_external_subcommand_values_of() { 338 let a = Command::new("test") 339 .allow_external_subcommands(true) 340 .external_subcommand_value_parser(value_parser!(String)); 341 let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); 342 let (_ext, args) = m.subcommand().unwrap(); 343 args.get_many::<String>("").unwrap_or_default().count(); 344} 345 346#[test] 347#[should_panic = "Mismatch between definition and access of ``. Could not downcast to std::ffi::os_str::OsString, need to downcast to alloc::string::String"] 348fn panic_validated_utf8_external_subcommand_values_of_os() { 349 let a = Command::new("test") 350 .allow_external_subcommands(true) 351 .external_subcommand_value_parser(value_parser!(String)); 352 let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); 353 let (_ext, args) = m.subcommand().unwrap(); 354 args.get_many::<OsString>("").unwrap_or_default().count(); 355} 356 357#[test] 358fn allow_invalid_utf8_external_subcommand_values_of_os() { 359 let a = Command::new("test").allow_external_subcommands(true); 360 let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); 361 let (_ext, args) = m.subcommand().unwrap(); 362 args.get_many::<OsString>("").unwrap_or_default().count(); 363} 364 365#[test] 366#[should_panic = "Mismatch between definition and access of ``. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"] 367fn panic_invalid_utf8_external_subcommand_values_of() { 368 let a = Command::new("test").allow_external_subcommands(true); 369 let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); 370 let (_ext, args) = m.subcommand().unwrap(); 371 args.get_many::<String>("").unwrap_or_default().count(); 372} 373