1//! These Windows-only tests are ported from the Unix-only tests in 2//! tests/utf16.rs. The tests that use StrictUtf8 mode are omitted here, 3//! because that's a Unix-only feature. 4 5#![cfg(windows)] 6 7use clap::{arg, value_parser, Command}; 8use std::ffi::OsString; 9use std::os::windows::ffi::OsStringExt; 10 11// Take a slice of ASCII bytes, convert them to UTF-16, and then append a 12// dangling surrogate character to make the result invalid UTF-16. 13fn bad_osstring(ascii: &[u8]) -> OsString { 14 let mut wide_chars: Vec<u16> = ascii.iter().map(|&c| c as u16).collect(); 15 // UTF-16 surrogate characters are only valid in pairs. 16 let surrogate_char: u16 = 0xDC00; 17 wide_chars.push(surrogate_char); 18 let os = OsString::from_wide(&wide_chars); 19 assert!(os.to_str().is_none(), "invalid Unicode"); 20 os 21} 22 23#[test] 24fn invalid_utf16_positional() { 25 let r = Command::new("bad_utf16") 26 .arg(arg!(<arg> "some arg").value_parser(value_parser!(OsString))) 27 .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"")]); 28 assert!(r.is_ok(), "{}", r.unwrap_err()); 29 let m = r.unwrap(); 30 assert!(m.contains_id("arg")); 31 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 32} 33 34#[test] 35fn invalid_utf16_option_short_space() { 36 let r = Command::new("bad_utf16") 37 .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString))) 38 .try_get_matches_from(vec![ 39 OsString::from(""), 40 OsString::from("-a"), 41 bad_osstring(b""), 42 ]); 43 assert!(r.is_ok(), "{}", r.unwrap_err()); 44 let m = r.unwrap(); 45 assert!(m.contains_id("arg")); 46 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 47} 48 49#[test] 50fn invalid_utf16_option_short_equals() { 51 let r = Command::new("bad_utf16") 52 .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString))) 53 .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a=")]); 54 assert!(r.is_ok(), "{}", r.unwrap_err()); 55 let m = r.unwrap(); 56 assert!(m.contains_id("arg")); 57 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 58} 59 60#[test] 61fn invalid_utf16_option_short_no_space() { 62 let r = Command::new("bad_utf16") 63 .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString))) 64 .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"-a")]); 65 assert!(r.is_ok(), "{}", r.unwrap_err()); 66 let m = r.unwrap(); 67 assert!(m.contains_id("arg")); 68 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 69} 70 71#[test] 72fn invalid_utf16_option_long_space() { 73 let r = Command::new("bad_utf16") 74 .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString))) 75 .try_get_matches_from(vec![ 76 OsString::from(""), 77 OsString::from("--arg"), 78 bad_osstring(b""), 79 ]); 80 assert!(r.is_ok(), "{}", r.unwrap_err()); 81 let m = r.unwrap(); 82 assert!(m.contains_id("arg")); 83 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 84} 85 86#[test] 87fn invalid_utf16_option_long_equals() { 88 let r = Command::new("bad_utf16") 89 .arg(arg!(-a --arg <arg> "some arg").value_parser(value_parser!(OsString))) 90 .try_get_matches_from(vec![OsString::from(""), bad_osstring(b"--arg=")]); 91 assert!(r.is_ok(), "{}", r.unwrap_err()); 92 let m = r.unwrap(); 93 assert!(m.contains_id("arg")); 94 assert_eq!(&*m.get_one::<OsString>("arg").unwrap(), &*bad_osstring(b"")); 95} 96