1use clap::{arg, error::ErrorKind, Arg, ArgAction, Command};
2
3#[test]
4fn flag_overrides_itself() {
5    let res = Command::new("posix")
6        .arg(
7            arg!(--flag  "some flag"
8            )
9            .action(ArgAction::SetTrue)
10            .overrides_with("flag"),
11        )
12        .try_get_matches_from(vec!["", "--flag", "--flag"]);
13    assert!(res.is_ok(), "{}", res.unwrap_err());
14    let m = res.unwrap();
15    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
16}
17
18#[test]
19fn option_overrides_itself() {
20    let res = Command::new("posix")
21        .arg(
22            arg!(--opt <val> "some option")
23                .required(false)
24                .overrides_with("opt"),
25        )
26        .try_get_matches_from(vec!["", "--opt=some", "--opt=other"]);
27    assert!(res.is_ok(), "{}", res.unwrap_err());
28    let m = res.unwrap();
29    assert!(m.contains_id("opt"));
30    assert_eq!(
31        m.get_one::<String>("opt").map(|v| v.as_str()),
32        Some("other")
33    );
34}
35
36#[test]
37fn posix_compatible_flags_long() {
38    let m = Command::new("posix")
39        .arg(
40            arg!(--flag  "some flag")
41                .overrides_with("color")
42                .action(ArgAction::SetTrue),
43        )
44        .arg(arg!(--color "some other flag").action(ArgAction::SetTrue))
45        .try_get_matches_from(vec!["", "--flag", "--color"])
46        .unwrap();
47    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
48    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
49}
50
51#[test]
52fn posix_compatible_flags_long_rev() {
53    let m = Command::new("posix")
54        .arg(
55            arg!(--flag  "some flag")
56                .overrides_with("color")
57                .action(ArgAction::SetTrue),
58        )
59        .arg(arg!(--color "some other flag").action(ArgAction::SetTrue))
60        .try_get_matches_from(vec!["", "--color", "--flag"])
61        .unwrap();
62    assert!(!*m.get_one::<bool>("color").expect("defaulted by clap"));
63    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
64}
65
66#[test]
67fn posix_compatible_flags_short() {
68    let m = Command::new("posix")
69        .arg(
70            arg!(-f --flag  "some flag")
71                .overrides_with("color")
72                .action(ArgAction::SetTrue),
73        )
74        .arg(arg!(-c --color "some other flag").action(ArgAction::SetTrue))
75        .try_get_matches_from(vec!["", "-f", "-c"])
76        .unwrap();
77    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
78    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
79}
80
81#[test]
82fn posix_compatible_flags_short_rev() {
83    let m = Command::new("posix")
84        .arg(
85            arg!(-f --flag  "some flag")
86                .overrides_with("color")
87                .action(ArgAction::SetTrue),
88        )
89        .arg(arg!(-c --color "some other flag").action(ArgAction::SetTrue))
90        .try_get_matches_from(vec!["", "-c", "-f"])
91        .unwrap();
92    assert!(!*m.get_one::<bool>("color").expect("defaulted by clap"));
93    assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
94}
95
96#[test]
97fn posix_compatible_opts_long() {
98    let m = Command::new("posix")
99        .arg(arg!(--flag <flag> "some flag").overrides_with("color"))
100        .arg(arg!(--color <color> "some other flag"))
101        .try_get_matches_from(vec!["", "--flag", "some", "--color", "other"])
102        .unwrap();
103    assert!(m.contains_id("color"));
104    assert_eq!(
105        m.get_one::<String>("color").map(|v| v.as_str()).unwrap(),
106        "other"
107    );
108    assert!(!m.contains_id("flag"));
109}
110
111#[test]
112fn posix_compatible_opts_long_rev() {
113    let m = Command::new("posix")
114        .arg(arg!(--flag <flag> "some flag").overrides_with("color"))
115        .arg(arg!(--color <color> "some other flag"))
116        .try_get_matches_from(vec!["", "--color", "some", "--flag", "other"])
117        .unwrap();
118    assert!(!m.contains_id("color"));
119    assert!(m.contains_id("flag"));
120    assert_eq!(
121        m.get_one::<String>("flag").map(|v| v.as_str()).unwrap(),
122        "other"
123    );
124}
125
126#[test]
127fn posix_compatible_opts_long_equals() {
128    let m = Command::new("posix")
129        .arg(arg!(--flag <flag> "some flag").overrides_with("color"))
130        .arg(arg!(--color <color> "some other flag"))
131        .try_get_matches_from(vec!["", "--flag=some", "--color=other"])
132        .unwrap();
133    assert!(m.contains_id("color"));
134    assert_eq!(
135        m.get_one::<String>("color").map(|v| v.as_str()).unwrap(),
136        "other"
137    );
138    assert!(!m.contains_id("flag"));
139}
140
141#[test]
142fn posix_compatible_opts_long_equals_rev() {
143    let m = Command::new("posix")
144        .arg(arg!(--flag <flag> "some flag").overrides_with("color"))
145        .arg(arg!(--color <color> "some other flag"))
146        .try_get_matches_from(vec!["", "--color=some", "--flag=other"])
147        .unwrap();
148    assert!(!m.contains_id("color"));
149    assert!(m.contains_id("flag"));
150    assert_eq!(
151        m.get_one::<String>("flag").map(|v| v.as_str()).unwrap(),
152        "other"
153    );
154}
155
156#[test]
157fn posix_compatible_opts_short() {
158    let m = Command::new("posix")
159        .arg(arg!(f: -f <flag>  "some flag").overrides_with("c"))
160        .arg(arg!(c: -c <color> "some other flag"))
161        .try_get_matches_from(vec!["", "-f", "some", "-c", "other"])
162        .unwrap();
163    assert!(m.contains_id("c"));
164    assert_eq!(
165        m.get_one::<String>("c").map(|v| v.as_str()).unwrap(),
166        "other"
167    );
168    assert!(!m.contains_id("f"));
169}
170
171#[test]
172fn posix_compatible_opts_short_rev() {
173    let m = Command::new("posix")
174        .arg(arg!(f: -f <flag>  "some flag").overrides_with("c"))
175        .arg(arg!(c: -c <color> "some other flag"))
176        .try_get_matches_from(vec!["", "-c", "some", "-f", "other"])
177        .unwrap();
178    assert!(!m.contains_id("c"));
179    assert!(m.contains_id("f"));
180    assert_eq!(
181        m.get_one::<String>("f").map(|v| v.as_str()).unwrap(),
182        "other"
183    );
184}
185
186#[test]
187fn conflict_overridden() {
188    let m = Command::new("conflict_overridden")
189        .arg(
190            arg!(-f --flag "some flag")
191                .conflicts_with("debug")
192                .action(ArgAction::SetTrue),
193        )
194        .arg(arg!(-d --debug "other flag").action(ArgAction::SetTrue))
195        .arg(
196            arg!(-c --color "third flag")
197                .overrides_with("flag")
198                .action(ArgAction::SetTrue),
199        )
200        .try_get_matches_from(vec!["", "-f", "-c", "-d"])
201        .unwrap();
202    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
203    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
204    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
205}
206
207#[test]
208fn conflict_overridden_2() {
209    let result = Command::new("conflict_overridden")
210        .arg(
211            arg!(-f --flag "some flag")
212                .conflicts_with("debug")
213                .action(ArgAction::SetTrue),
214        )
215        .arg(arg!(-d --debug "other flag").action(ArgAction::SetTrue))
216        .arg(
217            arg!(-c --color "third flag")
218                .overrides_with("flag")
219                .action(ArgAction::SetTrue),
220        )
221        .try_get_matches_from(vec!["", "-f", "-d", "-c"]);
222    assert!(result.is_ok(), "{}", result.unwrap_err());
223    let m = result.unwrap();
224    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
225    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
226    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
227}
228
229#[test]
230fn conflict_overridden_3() {
231    let result = Command::new("conflict_overridden")
232        .arg(arg!(-f --flag "some flag").conflicts_with("debug"))
233        .arg(arg!(-d --debug "other flag"))
234        .arg(arg!(-c --color "third flag").overrides_with("flag"))
235        .try_get_matches_from(vec!["", "-d", "-c", "-f"]);
236    assert!(result.is_err());
237    let err = result.err().unwrap();
238    assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
239}
240
241#[test]
242fn conflict_overridden_4() {
243    let m = Command::new("conflict_overridden")
244        .arg(
245            arg!(-f --flag "some flag")
246                .conflicts_with("debug")
247                .action(ArgAction::SetTrue),
248        )
249        .arg(arg!(-d --debug "other flag").action(ArgAction::SetTrue))
250        .arg(
251            arg!(-c --color "third flag")
252                .overrides_with("flag")
253                .action(ArgAction::SetTrue),
254        )
255        .try_get_matches_from(vec!["", "-d", "-f", "-c"])
256        .unwrap();
257    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
258    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
259    assert!(*m.get_one::<bool>("debug").expect("defaulted by clap"));
260}
261
262#[test]
263fn pos_required_overridden_by_flag() {
264    let result = Command::new("require_overridden")
265        .arg(Arg::new("pos").index(1).required(true))
266        .arg(arg!(-c --color "some flag").overrides_with("pos"))
267        .try_get_matches_from(vec!["", "test", "-c"]);
268    assert!(result.is_ok(), "{:?}", result.unwrap_err());
269}
270
271#[test]
272fn require_overridden_2() {
273    let m = Command::new("require_overridden")
274        .arg(Arg::new("req_pos").required(true))
275        .arg(
276            arg!(-c --color "other flag")
277                .overrides_with("req_pos")
278                .action(ArgAction::SetTrue),
279        )
280        .try_get_matches_from(vec!["", "-c", "req_pos"])
281        .unwrap();
282    assert!(!*m.get_one::<bool>("color").expect("defaulted by clap"));
283    assert!(m.contains_id("req_pos"));
284}
285
286#[test]
287fn require_overridden_3() {
288    let m = Command::new("require_overridden")
289        .arg(
290            arg!(-f --flag "some flag")
291                .requires("debug")
292                .action(ArgAction::SetTrue),
293        )
294        .arg(arg!(-d --debug "other flag").action(ArgAction::SetTrue))
295        .arg(
296            arg!(-c --color "third flag")
297                .overrides_with("flag")
298                .action(ArgAction::SetTrue),
299        )
300        .try_get_matches_from(vec!["", "-f", "-c"])
301        .unwrap();
302    assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
303    assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
304    assert!(!*m.get_one::<bool>("debug").expect("defaulted by clap"));
305}
306
307#[test]
308fn require_overridden_4() {
309    let result = Command::new("require_overridden")
310        .arg(arg!(-f --flag "some flag").requires("debug"))
311        .arg(arg!(-d --debug "other flag"))
312        .arg(arg!(-c --color "third flag").overrides_with("flag"))
313        .try_get_matches_from(vec!["", "-c", "-f"]);
314    assert!(result.is_err());
315    let err = result.err().unwrap();
316    assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
317}
318
319#[test]
320fn incremental_override() {
321    let mut cmd = Command::new("test")
322        .arg(arg!(--name <NAME> ...).required(true))
323        .arg(
324            arg!(--"no-name")
325                .overrides_with("name")
326                .action(ArgAction::SetTrue),
327        );
328    let m = cmd
329        .try_get_matches_from_mut(["test", "--name=ahmed", "--no-name", "--name=ali"])
330        .unwrap();
331    assert_eq!(
332        m.get_many::<String>("name")
333            .unwrap()
334            .map(|v| v.as_str())
335            .collect::<Vec<_>>(),
336        ["ali"]
337    );
338    assert!(!*m.get_one::<bool>("no-name").expect("defaulted by clap"));
339}
340
341#[cfg(debug_assertions)]
342#[test]
343#[should_panic = "Argument or group 'extra' specified in 'overrides_with*' for 'config' does not exist"]
344fn overrides_with_invalid_arg() {
345    let _ = Command::new("prog")
346        .arg(Arg::new("config").long("config").overrides_with("extra"))
347        .try_get_matches_from(vec!["", "--config"]);
348}
349