1#![cfg(not(windows))] 2 3use clap::error::ErrorKind; 4use clap::Parser; 5use std::ffi::OsString; 6use std::os::unix::ffi::OsStringExt; 7 8#[derive(Parser, Debug, PartialEq, Eq)] 9struct Positional { 10 arg: String, 11} 12 13#[derive(Parser, Debug, PartialEq, Eq)] 14struct Named { 15 #[arg(short, long)] 16 arg: String, 17} 18 19#[test] 20fn invalid_utf8_strict_positional() { 21 let m = Positional::try_parse_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); 22 assert!(m.is_err()); 23 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 24} 25 26#[test] 27fn invalid_utf8_strict_option_short_space() { 28 let m = Named::try_parse_from(vec![ 29 OsString::from(""), 30 OsString::from("-a"), 31 OsString::from_vec(vec![0xe9]), 32 ]); 33 assert!(m.is_err()); 34 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 35} 36 37#[test] 38fn invalid_utf8_strict_option_short_equals() { 39 let m = Named::try_parse_from(vec![ 40 OsString::from(""), 41 OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]), 42 ]); 43 assert!(m.is_err()); 44 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 45} 46 47#[test] 48fn invalid_utf8_strict_option_short_no_space() { 49 let m = Named::try_parse_from(vec![ 50 OsString::from(""), 51 OsString::from_vec(vec![0x2d, 0x61, 0xe9]), 52 ]); 53 assert!(m.is_err()); 54 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 55} 56 57#[test] 58fn invalid_utf8_strict_option_long_space() { 59 let m = Named::try_parse_from(vec![ 60 OsString::from(""), 61 OsString::from("--arg"), 62 OsString::from_vec(vec![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_equals() { 70 let m = Named::try_parse_from(vec![ 71 OsString::from(""), 72 OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]), 73 ]); 74 assert!(m.is_err()); 75 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 76} 77 78#[derive(Parser, Debug, PartialEq, Eq)] 79struct PositionalOs { 80 arg: OsString, 81} 82 83#[derive(Parser, Debug, PartialEq, Eq)] 84struct NamedOs { 85 #[arg(short, long)] 86 arg: OsString, 87} 88 89#[test] 90fn invalid_utf8_positional() { 91 let r = PositionalOs::try_parse_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); 92 assert_eq!( 93 r.unwrap(), 94 PositionalOs { 95 arg: OsString::from_vec(vec![0xe9]) 96 } 97 ); 98} 99 100#[test] 101fn invalid_utf8_option_short_space() { 102 let r = NamedOs::try_parse_from(vec![ 103 OsString::from(""), 104 OsString::from("-a"), 105 OsString::from_vec(vec![0xe9]), 106 ]); 107 assert_eq!( 108 r.unwrap(), 109 NamedOs { 110 arg: OsString::from_vec(vec![0xe9]) 111 } 112 ); 113} 114 115#[test] 116fn invalid_utf8_option_short_equals() { 117 let r = NamedOs::try_parse_from(vec![ 118 OsString::from(""), 119 OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]), 120 ]); 121 assert_eq!( 122 r.unwrap(), 123 NamedOs { 124 arg: OsString::from_vec(vec![0xe9]) 125 } 126 ); 127} 128 129#[test] 130fn invalid_utf8_option_short_no_space() { 131 let r = NamedOs::try_parse_from(vec![ 132 OsString::from(""), 133 OsString::from_vec(vec![0x2d, 0x61, 0xe9]), 134 ]); 135 assert_eq!( 136 r.unwrap(), 137 NamedOs { 138 arg: OsString::from_vec(vec![0xe9]) 139 } 140 ); 141} 142 143#[test] 144fn invalid_utf8_option_long_space() { 145 let r = NamedOs::try_parse_from(vec![ 146 OsString::from(""), 147 OsString::from("--arg"), 148 OsString::from_vec(vec![0xe9]), 149 ]); 150 assert_eq!( 151 r.unwrap(), 152 NamedOs { 153 arg: OsString::from_vec(vec![0xe9]) 154 } 155 ); 156} 157 158#[test] 159fn invalid_utf8_option_long_equals() { 160 let r = NamedOs::try_parse_from(vec![ 161 OsString::from(""), 162 OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]), 163 ]); 164 assert_eq!( 165 r.unwrap(), 166 NamedOs { 167 arg: OsString::from_vec(vec![0xe9]) 168 } 169 ); 170} 171 172#[derive(Debug, PartialEq, Parser)] 173enum External { 174 #[command(external_subcommand)] 175 Other(Vec<String>), 176} 177 178#[test] 179fn refuse_invalid_utf8_subcommand_with_allow_external_subcommands() { 180 let m = External::try_parse_from(vec![ 181 OsString::from(""), 182 OsString::from_vec(vec![0xe9]), 183 OsString::from("normal"), 184 ]); 185 assert!(m.is_err()); 186 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 187} 188 189#[test] 190fn refuse_invalid_utf8_subcommand_args_with_allow_external_subcommands() { 191 let m = External::try_parse_from(vec![ 192 OsString::from(""), 193 OsString::from("subcommand"), 194 OsString::from("normal"), 195 OsString::from_vec(vec![0xe9]), 196 OsString::from("--another_normal"), 197 ]); 198 assert!(m.is_err()); 199 assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8); 200} 201 202#[derive(Debug, PartialEq, Parser)] 203enum ExternalOs { 204 #[command(external_subcommand)] 205 Other(Vec<OsString>), 206} 207 208#[test] 209fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() { 210 let m = ExternalOs::try_parse_from(vec![ 211 OsString::from(""), 212 OsString::from("subcommand"), 213 OsString::from("normal"), 214 OsString::from_vec(vec![0xe9]), 215 OsString::from("--another_normal"), 216 ]); 217 assert_eq!( 218 m.unwrap(), 219 ExternalOs::Other(vec![ 220 OsString::from("subcommand"), 221 OsString::from("normal"), 222 OsString::from_vec(vec![0xe9]), 223 OsString::from("--another_normal"), 224 ]) 225 ); 226} 227