• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //
11 // This work was derived from Structopt (https://github.com/TeXitoi/structopt)
12 // commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
13 // MIT/Apache 2.0 license.
14 
15 use clap::{Parser, Subcommand};
16 
17 #[derive(Parser, PartialEq, Debug)]
18 struct Opt {
19     #[arg(short, long)]
20     force: bool,
21     #[arg(short, long, action = clap::ArgAction::Count)]
22     verbose: u8,
23     #[command(subcommand)]
24     cmd: Sub,
25 }
26 
27 #[derive(Subcommand, PartialEq, Debug)]
28 enum Sub {
29     Fetch {},
30     Add {},
31 }
32 
33 #[derive(Parser, PartialEq, Debug)]
34 struct Opt2 {
35     #[arg(short, long)]
36     force: bool,
37     #[arg(short, long, action = clap::ArgAction::Count)]
38     verbose: u8,
39     #[command(subcommand)]
40     cmd: Option<Sub>,
41 }
42 
43 #[test]
test_no_cmd()44 fn test_no_cmd() {
45     let result = Opt::try_parse_from(["test"]);
46     assert!(result.is_err());
47 
48     assert_eq!(
49         Opt2 {
50             force: false,
51             verbose: 0,
52             cmd: None
53         },
54         Opt2::try_parse_from(["test"]).unwrap()
55     );
56 }
57 
58 #[test]
test_fetch()59 fn test_fetch() {
60     assert_eq!(
61         Opt {
62             force: false,
63             verbose: 3,
64             cmd: Sub::Fetch {}
65         },
66         Opt::try_parse_from(["test", "-vvv", "fetch"]).unwrap()
67     );
68     assert_eq!(
69         Opt {
70             force: true,
71             verbose: 0,
72             cmd: Sub::Fetch {}
73         },
74         Opt::try_parse_from(["test", "--force", "fetch"]).unwrap()
75     );
76 }
77 
78 #[test]
test_add()79 fn test_add() {
80     assert_eq!(
81         Opt {
82             force: false,
83             verbose: 0,
84             cmd: Sub::Add {}
85         },
86         Opt::try_parse_from(["test", "add"]).unwrap()
87     );
88     assert_eq!(
89         Opt {
90             force: false,
91             verbose: 2,
92             cmd: Sub::Add {}
93         },
94         Opt::try_parse_from(["test", "-vv", "add"]).unwrap()
95     );
96 }
97 
98 #[test]
test_badinput()99 fn test_badinput() {
100     let result = Opt::try_parse_from(["test", "badcmd"]);
101     assert!(result.is_err());
102     let result = Opt::try_parse_from(["test", "add", "--verbose"]);
103     assert!(result.is_err());
104     let result = Opt::try_parse_from(["test", "--badopt", "add"]);
105     assert!(result.is_err());
106     let result = Opt::try_parse_from(["test", "add", "--badopt"]);
107     assert!(result.is_err());
108 }
109 
110 #[derive(Parser, PartialEq, Debug)]
111 struct Opt3 {
112     #[arg(short, long)]
113     all: bool,
114     #[command(subcommand)]
115     cmd: Sub2,
116 }
117 
118 #[derive(Subcommand, PartialEq, Debug)]
119 enum Sub2 {
120     Foo {
121         file: String,
122         #[command(subcommand)]
123         cmd: Sub3,
124     },
125     Bar {},
126 }
127 
128 #[derive(Subcommand, PartialEq, Debug)]
129 enum Sub3 {
130     Baz {},
131     Quux {},
132 }
133 
134 #[test]
test_subsubcommand()135 fn test_subsubcommand() {
136     assert_eq!(
137         Opt3 {
138             all: true,
139             cmd: Sub2::Foo {
140                 file: "lib.rs".to_string(),
141                 cmd: Sub3::Quux {}
142             }
143         },
144         Opt3::try_parse_from(["test", "--all", "foo", "lib.rs", "quux"]).unwrap()
145     );
146 }
147 
148 #[derive(Parser, PartialEq, Debug)]
149 enum SubSubCmdWithOption {
150     Remote {
151         #[command(subcommand)]
152         cmd: Option<Remote>,
153     },
154     Stash {
155         #[command(subcommand)]
156         cmd: Stash,
157     },
158 }
159 #[derive(Subcommand, PartialEq, Debug)]
160 enum Remote {
161     Add { name: String, url: String },
162     Remove { name: String },
163 }
164 
165 #[derive(Subcommand, PartialEq, Debug)]
166 enum Stash {
167     Save,
168     Pop,
169 }
170 
171 #[test]
sub_sub_cmd_with_option()172 fn sub_sub_cmd_with_option() {
173     fn make(args: &[&str]) -> Option<SubSubCmdWithOption> {
174         SubSubCmdWithOption::try_parse_from(args).ok()
175     }
176     assert_eq!(
177         Some(SubSubCmdWithOption::Remote { cmd: None }),
178         make(&["", "remote"])
179     );
180     assert_eq!(
181         Some(SubSubCmdWithOption::Remote {
182             cmd: Some(Remote::Add {
183                 name: "origin".into(),
184                 url: "http".into()
185             })
186         }),
187         make(&["", "remote", "add", "origin", "http"])
188     );
189     assert_eq!(
190         Some(SubSubCmdWithOption::Stash { cmd: Stash::Save }),
191         make(&["", "stash", "save"])
192     );
193     assert_eq!(None, make(&["", "stash"]));
194 }
195