1use clap::{arg, Arg, ArgAction, Command};
2
3#[cfg(feature = "error-context")]
4use super::utils;
5
6#[test]
7fn flag_using_short() {
8    let m = Command::new("flag")
9        .args([
10            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
11            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
12        ])
13        .try_get_matches_from(vec!["", "-f", "-c"])
14        .unwrap();
15    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
16    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
17}
18
19#[test]
20fn lots_o_flags_sep() {
21    let r = Command::new("opts")
22        .args_override_self(true)
23        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
24        .try_get_matches_from(vec![
25            "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
26            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
27            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
28            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
29            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
30            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
31            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
32            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
33            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
34            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
35            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
36            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
37            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
38            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
39            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
40            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
41            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
42            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
43            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
44            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
45            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
46            "-o", "-o", "-o",
47        ]);
48    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
49    let m = r.unwrap();
50    assert!(m.contains_id("o"));
51    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
52}
53
54#[test]
55fn lots_o_flags_combined() {
56    let r = Command::new("opts")
57        .args_override_self(true)
58        .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue))
59        .try_get_matches_from(vec![
60            "",
61            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
62            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
63            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
64            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
65            "-ooooooooooooooooooooooooooooooooooooooooo",
66        ]);
67    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
68    let m = r.unwrap();
69    assert!(m.contains_id("o"));
70    assert!(*m.get_one::<bool>("o").expect("defaulted by clap"));
71}
72
73#[test]
74fn flag_using_long() {
75    let m = Command::new("flag")
76        .args([
77            arg!(--flag "some flag").action(ArgAction::SetTrue),
78            arg!(--color "some other flag").action(ArgAction::SetTrue),
79        ])
80        .try_get_matches_from(vec!["", "--flag", "--color"])
81        .unwrap();
82    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
83    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
84}
85
86#[test]
87fn flag_using_long_with_literals() {
88    use clap::error::ErrorKind;
89
90    let m = Command::new("flag")
91        .arg(
92            Arg::new("rainbow")
93                .long("rainbow")
94                .action(ArgAction::SetTrue),
95        )
96        .try_get_matches_from(vec!["", "--rainbow=false"]);
97    assert!(m.is_err(), "{:#?}", m.unwrap());
98    assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
99}
100
101#[test]
102fn flag_using_mixed() {
103    let m = Command::new("flag")
104        .args([
105            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
106            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
107        ])
108        .try_get_matches_from(vec!["", "-f", "--color"])
109        .unwrap();
110    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
111    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
112
113    let m = Command::new("flag")
114        .args([
115            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
116            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
117        ])
118        .try_get_matches_from(vec!["", "--flag", "-c"])
119        .unwrap();
120    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
121    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
122}
123
124#[test]
125fn multiple_flags_in_single() {
126    let m = Command::new("multe_flags")
127        .args([
128            arg!(-f --flag "some flag").action(ArgAction::SetTrue),
129            arg!(-c --color "some other flag").action(ArgAction::SetTrue),
130            arg!(-d --debug "another other flag").action(ArgAction::SetTrue),
131        ])
132        .try_get_matches_from(vec!["", "-fcd"])
133        .unwrap();
134    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
135    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
136    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
137}
138
139#[test]
140#[cfg(feature = "error-context")]
141fn unexpected_value_error() {
142    const USE_FLAG_AS_ARGUMENT: &str = "\
143error: unexpected value 'foo' for '--a-flag' found; no more were expected
144
145Usage: mycat --a-flag [filename]
146
147For more information, try '--help'.
148";
149
150    let cmd = Command::new("mycat")
151        .arg(Arg::new("filename"))
152        .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue));
153
154    utils::assert_output(cmd, "mycat --a-flag=foo", USE_FLAG_AS_ARGUMENT, true);
155}
156
157#[test]
158#[cfg(feature = "error-context")]
159fn issue_1284_argument_in_flag_style() {
160    const USE_FLAG_AS_ARGUMENT: &str = "\
161error: unexpected argument '--another-flag' found
162
163  note: to pass '--another-flag' as a value, use '-- --another-flag'
164
165Usage: mycat [OPTIONS] [filename]
166
167For more information, try '--help'.
168";
169
170    let cmd = Command::new("mycat")
171        .arg(Arg::new("filename"))
172        .arg(Arg::new("a-flag").long("a-flag").action(ArgAction::SetTrue));
173
174    let m = cmd
175        .clone()
176        .try_get_matches_from(vec!["", "--", "--another-flag"])
177        .unwrap();
178    assert_eq!(
179        m.get_one::<String>("filename").map(|v| v.as_str()),
180        Some("--another-flag")
181    );
182
183    let m = cmd
184        .clone()
185        .try_get_matches_from(vec!["", "--a-flag"])
186        .unwrap();
187    assert!(*m.get_one::<bool>("a-flag").expect("defaulted by clap"));
188
189    let m = cmd
190        .clone()
191        .try_get_matches_from(vec!["", "--", "--a-flag"])
192        .unwrap();
193    assert_eq!(
194        m.get_one::<String>("filename").map(|v| v.as_str()),
195        Some("--a-flag")
196    );
197
198    utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true);
199}
200
201#[test]
202#[cfg(feature = "error-context")]
203fn issue_2308_multiple_dashes() {
204    static MULTIPLE_DASHES: &str = "\
205error: unexpected argument '-----' found
206
207  note: to pass '-----' as a value, use '-- -----'
208
209Usage: test <arg>
210
211For more information, try '--help'.
212";
213    let cmd = Command::new("test").arg(Arg::new("arg").action(ArgAction::Set).required(true));
214
215    utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true);
216}
217
218#[test]
219#[cfg(debug_assertions)]
220#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"]
221fn leading_dash_stripped() {
222    let cmd = Command::new("mycat").arg(Arg::new("filename").long("--filename"));
223    cmd.debug_assert();
224}
225