1 #![cfg(not(windows))]
2
3 use clap::error::ErrorKind;
4 use clap::Parser;
5 use std::ffi::OsString;
6 use std::os::unix::ffi::OsStringExt;
7
8 #[derive(Parser, Debug, PartialEq, Eq)]
9 struct Positional {
10 arg: String,
11 }
12
13 #[derive(Parser, Debug, PartialEq, Eq)]
14 struct Named {
15 #[arg(short, long)]
16 arg: String,
17 }
18
19 #[test]
invalid_utf8_strict_positional()20 fn 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]
invalid_utf8_strict_option_short_space()27 fn 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]
invalid_utf8_strict_option_short_equals()38 fn 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]
invalid_utf8_strict_option_short_no_space()48 fn 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]
invalid_utf8_strict_option_long_space()58 fn 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]
invalid_utf8_strict_option_long_equals()69 fn 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)]
79 struct PositionalOs {
80 arg: OsString,
81 }
82
83 #[derive(Parser, Debug, PartialEq, Eq)]
84 struct NamedOs {
85 #[arg(short, long)]
86 arg: OsString,
87 }
88
89 #[test]
invalid_utf8_positional()90 fn 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]
invalid_utf8_option_short_space()101 fn 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]
invalid_utf8_option_short_equals()116 fn 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]
invalid_utf8_option_short_no_space()130 fn 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]
invalid_utf8_option_long_space()144 fn 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]
invalid_utf8_option_long_equals()159 fn 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)]
173 enum External {
174 #[command(external_subcommand)]
175 Other(Vec<String>),
176 }
177
178 #[test]
refuse_invalid_utf8_subcommand_with_allow_external_subcommands()179 fn 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]
refuse_invalid_utf8_subcommand_args_with_allow_external_subcommands()190 fn 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)]
203 enum ExternalOs {
204 #[command(external_subcommand)]
205 Other(Vec<OsString>),
206 }
207
208 #[test]
allow_invalid_utf8_subcommand_args_with_allow_external_subcommands()209 fn 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