1 // Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
2 // Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
3 // Ana Hobden (@hoverbear) <operator@hoverbear.org>
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 use clap::Parser;
11
12 #[test]
basic()13 fn basic() {
14 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
15 enum ArgChoice {
16 Foo,
17 Bar,
18 }
19
20 #[derive(Parser, PartialEq, Debug)]
21 struct Opt {
22 #[arg(value_enum)]
23 arg: ArgChoice,
24 }
25
26 assert_eq!(
27 Opt {
28 arg: ArgChoice::Foo
29 },
30 Opt::try_parse_from(["", "foo"]).unwrap()
31 );
32 assert_eq!(
33 Opt {
34 arg: ArgChoice::Bar
35 },
36 Opt::try_parse_from(["", "bar"]).unwrap()
37 );
38 assert!(Opt::try_parse_from(["", "fOo"]).is_err());
39 }
40
41 #[test]
default_value()42 fn default_value() {
43 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
44 enum ArgChoice {
45 Foo,
46 Bar,
47 }
48
49 impl Default for ArgChoice {
50 fn default() -> Self {
51 Self::Bar
52 }
53 }
54
55 #[derive(Parser, PartialEq, Debug)]
56 struct Opt {
57 #[arg(value_enum, default_value_t)]
58 arg: ArgChoice,
59 }
60
61 assert_eq!(
62 Opt {
63 arg: ArgChoice::Foo
64 },
65 Opt::try_parse_from(["", "foo"]).unwrap()
66 );
67 assert_eq!(
68 Opt {
69 arg: ArgChoice::Bar
70 },
71 Opt::try_parse_from(["", "bar"]).unwrap()
72 );
73 assert_eq!(
74 Opt {
75 arg: ArgChoice::Bar
76 },
77 Opt::try_parse_from([""]).unwrap()
78 );
79 }
80
81 #[test]
vec_for_default_values_t()82 fn vec_for_default_values_t() {
83 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
84 enum ArgChoice {
85 Foo,
86 Bar,
87 }
88
89 #[derive(Parser, PartialEq, Debug)]
90 struct Opt {
91 #[arg(value_enum, default_values_t = vec![ArgChoice::Foo, ArgChoice::Bar])]
92 arg1: Vec<ArgChoice>,
93
94 #[arg(
95 long,
96 value_enum,
97 default_values_t = clap::ValueEnum::value_variants()
98 )]
99 arg2: Vec<ArgChoice>,
100 }
101
102 assert_eq!(
103 Opt {
104 arg1: vec![ArgChoice::Foo],
105 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
106 },
107 Opt::try_parse_from(["", "foo"]).unwrap()
108 );
109 assert_eq!(
110 Opt {
111 arg1: vec![ArgChoice::Bar],
112 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
113 },
114 Opt::try_parse_from(["", "bar"]).unwrap()
115 );
116 assert_eq!(
117 Opt {
118 arg1: vec![ArgChoice::Foo, ArgChoice::Bar],
119 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
120 },
121 Opt::try_parse_from([""]).unwrap()
122 );
123 assert_eq!(
124 Opt {
125 arg1: vec![ArgChoice::Foo, ArgChoice::Bar],
126 arg2: vec![ArgChoice::Foo]
127 },
128 Opt::try_parse_from(["", "--arg2", "foo"]).unwrap()
129 );
130 }
131
132 #[test]
vec_for_default_values_os_t()133 fn vec_for_default_values_os_t() {
134 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
135 enum ArgChoice {
136 Foo,
137 Bar,
138 }
139
140 #[derive(Parser, PartialEq, Debug)]
141 struct Opt {
142 #[arg(value_enum, default_values_os_t = vec![ArgChoice::Foo, ArgChoice::Bar])]
143 arg: Vec<ArgChoice>,
144
145 #[arg(
146 long,
147 value_enum,
148 default_values_os_t = clap::ValueEnum::value_variants()
149 )]
150 arg2: Vec<ArgChoice>,
151 }
152
153 assert_eq!(
154 Opt {
155 arg: vec![ArgChoice::Foo],
156 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
157 },
158 Opt::try_parse_from(["", "foo"]).unwrap()
159 );
160 assert_eq!(
161 Opt {
162 arg: vec![ArgChoice::Bar],
163 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
164 },
165 Opt::try_parse_from(["", "bar"]).unwrap()
166 );
167 assert_eq!(
168 Opt {
169 arg: vec![ArgChoice::Foo, ArgChoice::Bar],
170 arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
171 },
172 Opt::try_parse_from([""]).unwrap()
173 );
174 assert_eq!(
175 Opt {
176 arg: vec![ArgChoice::Foo, ArgChoice::Bar],
177 arg2: vec![ArgChoice::Foo]
178 },
179 Opt::try_parse_from(["", "--arg2", "foo"]).unwrap()
180 );
181 }
182
183 #[test]
multi_word_is_renamed_kebab()184 fn multi_word_is_renamed_kebab() {
185 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
186 #[allow(non_camel_case_types)]
187 enum ArgChoice {
188 FooBar,
189 BAR_BAZ,
190 }
191
192 #[derive(Parser, PartialEq, Debug)]
193 struct Opt {
194 #[arg(value_enum)]
195 arg: ArgChoice,
196 }
197
198 assert_eq!(
199 Opt {
200 arg: ArgChoice::FooBar
201 },
202 Opt::try_parse_from(["", "foo-bar"]).unwrap()
203 );
204 assert_eq!(
205 Opt {
206 arg: ArgChoice::BAR_BAZ
207 },
208 Opt::try_parse_from(["", "bar-baz"]).unwrap()
209 );
210 assert!(Opt::try_parse_from(["", "FooBar"]).is_err());
211 }
212
213 #[test]
variant_with_defined_casing()214 fn variant_with_defined_casing() {
215 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
216 enum ArgChoice {
217 #[value(rename_all = "screaming_snake")]
218 FooBar,
219 }
220
221 #[derive(Parser, PartialEq, Debug)]
222 struct Opt {
223 #[arg(value_enum)]
224 arg: ArgChoice,
225 }
226
227 assert_eq!(
228 Opt {
229 arg: ArgChoice::FooBar
230 },
231 Opt::try_parse_from(["", "FOO_BAR"]).unwrap()
232 );
233 assert!(Opt::try_parse_from(["", "FooBar"]).is_err());
234 }
235
236 #[test]
casing_is_propagated_from_parent()237 fn casing_is_propagated_from_parent() {
238 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
239 #[value(rename_all = "screaming_snake")]
240 enum ArgChoice {
241 FooBar,
242 }
243
244 #[derive(Parser, PartialEq, Debug)]
245 struct Opt {
246 #[arg(value_enum)]
247 arg: ArgChoice,
248 }
249
250 assert_eq!(
251 Opt {
252 arg: ArgChoice::FooBar
253 },
254 Opt::try_parse_from(["", "FOO_BAR"]).unwrap()
255 );
256 assert!(Opt::try_parse_from(["", "FooBar"]).is_err());
257 }
258
259 #[test]
casing_propagation_is_overridden()260 fn casing_propagation_is_overridden() {
261 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
262 #[value(rename_all = "screaming_snake")]
263 enum ArgChoice {
264 #[value(rename_all = "camel")]
265 FooBar,
266 }
267
268 #[derive(Parser, PartialEq, Debug)]
269 struct Opt {
270 #[arg(value_enum)]
271 arg: ArgChoice,
272 }
273
274 assert_eq!(
275 Opt {
276 arg: ArgChoice::FooBar
277 },
278 Opt::try_parse_from(["", "fooBar"]).unwrap()
279 );
280 assert!(Opt::try_parse_from(["", "FooBar"]).is_err());
281 assert!(Opt::try_parse_from(["", "FOO_BAR"]).is_err());
282 }
283
284 #[test]
ignore_case()285 fn ignore_case() {
286 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
287 enum ArgChoice {
288 Foo,
289 }
290
291 #[derive(Parser, PartialEq, Debug)]
292 struct Opt {
293 #[arg(value_enum, ignore_case(true))]
294 arg: ArgChoice,
295 }
296
297 assert_eq!(
298 Opt {
299 arg: ArgChoice::Foo
300 },
301 Opt::try_parse_from(["", "foo"]).unwrap()
302 );
303 assert_eq!(
304 Opt {
305 arg: ArgChoice::Foo
306 },
307 Opt::try_parse_from(["", "fOo"]).unwrap()
308 );
309 }
310
311 #[test]
ignore_case_set_to_false()312 fn ignore_case_set_to_false() {
313 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
314 enum ArgChoice {
315 Foo,
316 }
317
318 #[derive(Parser, PartialEq, Debug)]
319 struct Opt {
320 #[arg(value_enum, ignore_case(false))]
321 arg: ArgChoice,
322 }
323
324 assert_eq!(
325 Opt {
326 arg: ArgChoice::Foo
327 },
328 Opt::try_parse_from(["", "foo"]).unwrap()
329 );
330 assert!(Opt::try_parse_from(["", "fOo"]).is_err());
331 }
332
333 #[test]
alias()334 fn alias() {
335 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
336 enum ArgChoice {
337 #[value(alias = "TOTP")]
338 Totp,
339 }
340
341 #[derive(Parser, PartialEq, Debug)]
342 struct Opt {
343 #[arg(value_enum, ignore_case(false))]
344 arg: ArgChoice,
345 }
346
347 assert_eq!(
348 Opt {
349 arg: ArgChoice::Totp
350 },
351 Opt::try_parse_from(["", "totp"]).unwrap()
352 );
353 assert_eq!(
354 Opt {
355 arg: ArgChoice::Totp
356 },
357 Opt::try_parse_from(["", "TOTP"]).unwrap()
358 );
359 }
360
361 #[test]
multiple_alias()362 fn multiple_alias() {
363 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
364 enum ArgChoice {
365 #[value(alias = "TOTP", alias = "t")]
366 Totp,
367 }
368
369 #[derive(Parser, PartialEq, Debug)]
370 struct Opt {
371 #[arg(value_enum, ignore_case(false))]
372 arg: ArgChoice,
373 }
374
375 assert_eq!(
376 Opt {
377 arg: ArgChoice::Totp
378 },
379 Opt::try_parse_from(["", "totp"]).unwrap()
380 );
381 assert_eq!(
382 Opt {
383 arg: ArgChoice::Totp
384 },
385 Opt::try_parse_from(["", "TOTP"]).unwrap()
386 );
387 assert_eq!(
388 Opt {
389 arg: ArgChoice::Totp
390 },
391 Opt::try_parse_from(["", "t"]).unwrap()
392 );
393 }
394
395 #[test]
skip_variant()396 fn skip_variant() {
397 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
398 #[allow(dead_code)] // silence warning about `Baz` being unused
399 enum ArgChoice {
400 Foo,
401 Bar,
402 #[value(skip)]
403 Baz,
404 }
405
406 assert_eq!(
407 <ArgChoice as clap::ValueEnum>::value_variants()
408 .iter()
409 .map(clap::ValueEnum::to_possible_value)
410 .map(Option::unwrap)
411 .collect::<Vec<_>>(),
412 vec![
413 clap::builder::PossibleValue::new("foo"),
414 clap::builder::PossibleValue::new("bar")
415 ]
416 );
417
418 {
419 use clap::ValueEnum;
420 assert!(ArgChoice::from_str("foo", true).is_ok());
421 assert!(ArgChoice::from_str("bar", true).is_ok());
422 assert!(ArgChoice::from_str("baz", true).is_err());
423 }
424 }
425
426 #[test]
skip_non_unit_variant()427 fn skip_non_unit_variant() {
428 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
429 #[allow(dead_code)] // silence warning about `Baz` being unused
430 enum ArgChoice {
431 Foo,
432 Bar,
433 #[value(skip)]
434 Baz(usize),
435 }
436
437 assert_eq!(
438 <ArgChoice as clap::ValueEnum>::value_variants()
439 .iter()
440 .map(clap::ValueEnum::to_possible_value)
441 .map(Option::unwrap)
442 .collect::<Vec<_>>(),
443 vec![
444 clap::builder::PossibleValue::new("foo"),
445 clap::builder::PossibleValue::new("bar")
446 ]
447 );
448
449 {
450 use clap::ValueEnum;
451 assert!(ArgChoice::from_str("foo", true).is_ok());
452 assert!(ArgChoice::from_str("bar", true).is_ok());
453 assert!(ArgChoice::from_str("baz", true).is_err());
454 }
455 }
456
457 #[test]
from_str_invalid()458 fn from_str_invalid() {
459 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
460 enum ArgChoice {
461 Foo,
462 }
463
464 {
465 use clap::ValueEnum;
466 assert!(ArgChoice::from_str("bar", true).is_err());
467 }
468 }
469
470 #[test]
option_type()471 fn option_type() {
472 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
473 enum ArgChoice {
474 Foo,
475 Bar,
476 }
477
478 #[derive(Parser, PartialEq, Debug)]
479 struct Opt {
480 #[arg(value_enum)]
481 arg: Option<ArgChoice>,
482 }
483
484 assert_eq!(Opt { arg: None }, Opt::try_parse_from([""]).unwrap());
485 assert_eq!(
486 Opt {
487 arg: Some(ArgChoice::Foo)
488 },
489 Opt::try_parse_from(["", "foo"]).unwrap()
490 );
491 assert_eq!(
492 Opt {
493 arg: Some(ArgChoice::Bar)
494 },
495 Opt::try_parse_from(["", "bar"]).unwrap()
496 );
497 assert!(Opt::try_parse_from(["", "fOo"]).is_err());
498 }
499
500 #[test]
option_option_type()501 fn option_option_type() {
502 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
503 enum ArgChoice {
504 Foo,
505 Bar,
506 }
507
508 #[derive(Parser, PartialEq, Debug)]
509 struct Opt {
510 #[arg(value_enum, long)]
511 arg: Option<Option<ArgChoice>>,
512 }
513
514 assert_eq!(Opt { arg: None }, Opt::try_parse_from([""]).unwrap());
515 assert_eq!(
516 Opt { arg: Some(None) },
517 Opt::try_parse_from(["", "--arg"]).unwrap()
518 );
519 assert_eq!(
520 Opt {
521 arg: Some(Some(ArgChoice::Foo))
522 },
523 Opt::try_parse_from(["", "--arg", "foo"]).unwrap()
524 );
525 assert_eq!(
526 Opt {
527 arg: Some(Some(ArgChoice::Bar))
528 },
529 Opt::try_parse_from(["", "--arg", "bar"]).unwrap()
530 );
531 assert!(Opt::try_parse_from(["", "--arg", "fOo"]).is_err());
532 }
533
534 #[test]
vec_type()535 fn vec_type() {
536 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
537 enum ArgChoice {
538 Foo,
539 Bar,
540 }
541
542 #[derive(Parser, PartialEq, Debug)]
543 struct Opt {
544 #[arg(value_enum, short, long)]
545 arg: Vec<ArgChoice>,
546 }
547
548 assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from([""]).unwrap());
549 assert_eq!(
550 Opt {
551 arg: vec![ArgChoice::Foo]
552 },
553 Opt::try_parse_from(["", "-a", "foo"]).unwrap()
554 );
555 assert_eq!(
556 Opt {
557 arg: vec![ArgChoice::Foo, ArgChoice::Bar]
558 },
559 Opt::try_parse_from(["", "-a", "foo", "-a", "bar"]).unwrap()
560 );
561 assert!(Opt::try_parse_from(["", "-a", "fOo"]).is_err());
562 }
563
564 #[test]
option_vec_type()565 fn option_vec_type() {
566 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
567 enum ArgChoice {
568 Foo,
569 Bar,
570 }
571
572 #[derive(Parser, PartialEq, Debug)]
573 struct Opt {
574 #[arg(value_enum, short, long)]
575 arg: Option<Vec<ArgChoice>>,
576 }
577
578 assert_eq!(Opt { arg: None }, Opt::try_parse_from([""]).unwrap());
579 assert_eq!(
580 Opt {
581 arg: Some(vec![ArgChoice::Foo])
582 },
583 Opt::try_parse_from(["", "-a", "foo"]).unwrap()
584 );
585 assert_eq!(
586 Opt {
587 arg: Some(vec![ArgChoice::Foo, ArgChoice::Bar])
588 },
589 Opt::try_parse_from(["", "-a", "foo", "-a", "bar"]).unwrap()
590 );
591 assert!(Opt::try_parse_from(["", "-a", "fOo"]).is_err());
592 }
593
594 #[test]
vec_type_default_value()595 fn vec_type_default_value() {
596 #[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
597 enum ArgChoice {
598 Foo,
599 Bar,
600 Baz,
601 }
602
603 #[derive(Parser, PartialEq, Debug)]
604 struct Opt {
605 #[arg(
606 value_enum,
607 short,
608 long,
609 default_value = "foo,bar",
610 value_delimiter = ','
611 )]
612 arg: Vec<ArgChoice>,
613 }
614
615 assert_eq!(
616 Opt {
617 arg: vec![ArgChoice::Foo, ArgChoice::Bar]
618 },
619 Opt::try_parse_from([""]).unwrap()
620 );
621
622 assert_eq!(
623 Opt {
624 arg: vec![ArgChoice::Foo, ArgChoice::Baz]
625 },
626 Opt::try_parse_from(["", "-a", "foo,baz"]).unwrap()
627 );
628 }
629