1 use std::collections::HashMap;
2
3 use serde::Deserialize;
4
5 use crate::{Docopt, ArgvMap, Error};
6 use crate::Value::{self, Switch, Plain};
7
get_args(doc: &str, argv: &[&'static str]) -> ArgvMap8 fn get_args(doc: &str, argv: &[&'static str]) -> ArgvMap {
9 let dopt = match Docopt::new(doc) {
10 Err(err) => panic!("Invalid usage: {}", err),
11 Ok(dopt) => dopt,
12 };
13 match dopt.argv(vec!["cmd"].iter().chain(argv.iter())).parse() {
14 Err(err) => panic!("{}", err),
15 Ok(vals) => vals,
16 }
17 }
18
map_from_alist(alist: Vec<(&'static str, Value)>) -> HashMap<String, Value>19 fn map_from_alist(alist: Vec<(&'static str, Value)>)
20 -> HashMap<String, Value> {
21 alist.into_iter().map(|(k, v)| (k.to_string(), v)).collect()
22 }
23
same_args(expected: &HashMap<String, Value>, got: &ArgvMap)24 fn same_args(expected: &HashMap<String, Value>, got: &ArgvMap) {
25 for (k, ve) in expected.iter() {
26 match got.map.find(k) {
27 None => panic!("EXPECTED has '{}' but GOT does not.", k),
28 Some(vg) => {
29 assert!(ve == vg,
30 "{}: EXPECTED = '{:?}' != '{:?}' = GOT", k, ve, vg)
31 }
32 }
33 }
34 for (k, vg) in got.map.iter() {
35 match got.map.find(k) {
36 None => panic!("GOT has '{}' but EXPECTED does not.", k),
37 Some(ve) => {
38 assert!(vg == ve,
39 "{}: GOT = '{:?}' != '{:?}' = EXPECTED", k, vg, ve)
40 }
41 }
42 }
43 }
44
45 macro_rules! test_expect(
46 ($name:ident, $doc:expr, $args:expr, $expected:expr) => (
47 #[test]
48 fn $name() {
49 let vals = get_args($doc, $args);
50 let expected = map_from_alist($expected);
51 same_args(&expected, &vals);
52 }
53 );
54 );
55
56 macro_rules! test_user_error(
57 ($name:ident, $doc:expr, $args:expr) => (
58 #[test]
59 #[should_panic]
60 fn $name() { get_args($doc, $args); }
61 );
62 );
63
64 test_expect!(test_issue_13, "Usage: prog file <file>", &["file", "file"],
65 vec![("file", Switch(true)),
66 ("<file>", Plain(Some("file".to_string())))]);
67
68 test_expect!(test_issue_129, "Usage: prog [options]
69
70 Options:
71 --foo ARG Foo foo.",
72 &["--foo=a b"],
73 vec![("--foo", Plain(Some("a b".into())))]);
74
75 #[test]
regression_issue_12()76 fn regression_issue_12() {
77 const USAGE: &'static str = "
78 Usage:
79 whisper info <file>
80 whisper update <file> <timestamp> <value>
81 whisper mark <file> <value>
82 ";
83
84 #[derive(Deserialize, Debug)]
85 struct Args {
86 arg_file: String,
87 cmd_info: bool,
88 cmd_update: bool,
89 arg_timestamp: u64,
90 arg_value: f64,
91 }
92
93 let dopt: Args = Docopt::new(USAGE)
94 .unwrap()
95 .argv(&["whisper", "mark", "./p/blah", "100"])
96 .deserialize()
97 .unwrap();
98 assert_eq!(dopt.arg_timestamp, 0);
99 }
100
101 #[test]
regression_issue_195()102 fn regression_issue_195() {
103 const USAGE: &'static str = "
104 Usage:
105 slow [-abcdefghijklmnopqrs...]
106 ";
107
108 let argv = &["slow", "-abcdefghijklmnopqrs"];
109 let dopt : Docopt = Docopt::new(USAGE).unwrap().argv(argv);
110
111 dopt.parse().unwrap();
112 }
113
114 #[test]
regression_issue_219()115 fn regression_issue_219() {
116 #[derive(Deserialize)]
117 struct Args {
118 arg_type: Vec<String>,
119 arg_param: Vec<String>,
120 }
121
122 const USAGE: &'static str = "
123 Usage:
124 encode [-v <type> <param>]...
125 ";
126
127 let argv = &["encode", "-v", "bool", "true", "string", "foo"];
128 let args: Args = Docopt::new(USAGE).unwrap().argv(argv).deserialize().unwrap();
129 assert_eq!(args.arg_type, vec!["bool".to_owned(), "string".to_owned()]);
130 assert_eq!(args.arg_param, vec!["true".to_owned(), "foo".to_owned()]);
131 }
132
133 #[test]
test_unit_struct()134 fn test_unit_struct() {
135 const USAGE: &'static str = "
136 Usage:
137 cargo version [options]
138
139 Options:
140 -h, --help Print this message
141 ";
142
143 #[derive(Deserialize)]
144 struct Options;
145
146 let argv = &["cargo", "version"];
147 let dopt: Result<Options, Error>= Docopt::new(USAGE)
148 .unwrap()
149 .argv(argv)
150 .deserialize();
151 assert!(dopt.is_ok());
152 }
153
154 mod testcases;
155 mod suggestions;
156