PageRenderTime 70ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/opts.rs

https://github.com/kbknapp/clap-rs
Rust | 512 lines | 467 code | 45 blank | 0 comment | 0 complexity | 3036745ec377991771f0bbd3c3a1a56a MD5 | raw file
Possible License(s): MIT
  1. mod utils;
  2. use clap::{App, Arg, ArgMatches, ArgSettings, ErrorKind};
  3. #[cfg(feature = "suggestions")]
  4. static DYM: &str =
  5. "error: Found argument '--optio' which wasn't expected, or isn't valid in this context
  6. \tDid you mean '--option'?
  7. If you tried to supply `--optio` as a PATTERN use `-- --optio`
  8. USAGE:
  9. clap-test --option <opt>...
  10. For more information try --help";
  11. #[cfg(feature = "suggestions")]
  12. static DYM_ISSUE_1073: &str =
  13. "error: Found argument '--files-without-matches' which wasn't expected, or isn't valid in this context
  14. \tDid you mean '--files-without-match'?
  15. If you tried to supply `--files-without-matches` as a PATTERN use `-- --files-without-matches`
  16. USAGE:
  17. ripgrep-616 --files-without-match
  18. For more information try --help";
  19. #[test]
  20. fn require_equals_fail() {
  21. let res = App::new("prog")
  22. .arg(
  23. Arg::new("cfg")
  24. .setting(ArgSettings::RequireEquals)
  25. .setting(ArgSettings::TakesValue)
  26. .long("config"),
  27. )
  28. .try_get_matches_from(vec!["prog", "--config", "file.conf"]);
  29. assert!(res.is_err());
  30. assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
  31. }
  32. #[test]
  33. fn require_equals_min_values_zero() {
  34. let res = App::new("prog")
  35. .arg(
  36. Arg::new("cfg")
  37. .setting(ArgSettings::RequireEquals)
  38. .min_values(0)
  39. .long("config"),
  40. )
  41. .arg(Arg::new("cmd"))
  42. .try_get_matches_from(vec!["prog", "--config", "cmd"]);
  43. assert!(res.is_ok());
  44. let m = res.unwrap();
  45. assert!(m.is_present("cfg"));
  46. assert_eq!(m.value_of("cmd"), Some("cmd"));
  47. }
  48. #[test]
  49. fn double_hyphen_as_value() {
  50. let res = App::new("prog")
  51. .arg(
  52. Arg::new("cfg")
  53. .setting(ArgSettings::AllowHyphenValues)
  54. .long("config"),
  55. )
  56. .try_get_matches_from(vec!["prog", "--config", "--"]);
  57. assert!(res.is_ok(), "{:?}", res);
  58. assert_eq!(res.unwrap().value_of("cfg"), Some("--"));
  59. }
  60. #[test]
  61. fn require_equals_no_empty_values_fail() {
  62. let res = App::new("prog")
  63. .arg(
  64. Arg::new("cfg")
  65. .setting(ArgSettings::RequireEquals)
  66. .long("config"),
  67. )
  68. .arg(Arg::new("some"))
  69. .try_get_matches_from(vec!["prog", "--config=", "file.conf"]);
  70. assert!(res.is_err());
  71. assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
  72. }
  73. #[test]
  74. fn require_equals_empty_vals_pass() {
  75. let res = App::new("prog")
  76. .arg(
  77. Arg::new("cfg")
  78. .setting(ArgSettings::RequireEquals)
  79. .setting(ArgSettings::AllowEmptyValues)
  80. .long("config"),
  81. )
  82. .try_get_matches_from(vec!["prog", "--config="]);
  83. assert!(res.is_ok());
  84. }
  85. #[test]
  86. fn require_equals_pass() {
  87. let res = App::new("prog")
  88. .arg(
  89. Arg::new("cfg")
  90. .setting(ArgSettings::RequireEquals)
  91. .long("config"),
  92. )
  93. .try_get_matches_from(vec!["prog", "--config=file.conf"]);
  94. assert!(res.is_ok());
  95. }
  96. #[test]
  97. fn stdin_char() {
  98. let r = App::new("opts")
  99. .arg(Arg::from("-f [flag] 'some flag'"))
  100. .try_get_matches_from(vec!["", "-f", "-"]);
  101. assert!(r.is_ok());
  102. let m = r.unwrap();
  103. assert!(m.is_present("f"));
  104. assert_eq!(m.value_of("f").unwrap(), "-");
  105. }
  106. #[test]
  107. fn opts_using_short() {
  108. let r = App::new("opts")
  109. .args(&[
  110. Arg::from("-f [flag] 'some flag'"),
  111. Arg::from("-c [color] 'some other flag'"),
  112. ])
  113. .try_get_matches_from(vec!["", "-f", "some", "-c", "other"]);
  114. assert!(r.is_ok());
  115. let m = r.unwrap();
  116. assert!(m.is_present("f"));
  117. assert_eq!(m.value_of("f").unwrap(), "some");
  118. assert!(m.is_present("c"));
  119. assert_eq!(m.value_of("c").unwrap(), "other");
  120. }
  121. #[test]
  122. fn lots_o_vals() {
  123. let r = App::new("opts")
  124. .arg(Arg::from("-o [opt]... 'some opt'"))
  125. .try_get_matches_from(vec![
  126. "", "-o", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  127. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  128. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  129. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  130. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  131. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  132. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  133. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  134. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  135. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  136. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  137. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  138. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  139. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  140. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  141. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  142. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  143. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  144. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  145. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  146. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  147. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  148. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  149. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  150. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  151. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  152. "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
  153. "some", "some",
  154. ]);
  155. assert!(r.is_ok());
  156. let m = r.unwrap();
  157. assert!(m.is_present("o"));
  158. assert_eq!(m.values_of("o").unwrap().count(), 297); // i.e. more than u8
  159. }
  160. #[test]
  161. fn opts_using_long_space() {
  162. let r = App::new("opts")
  163. .args(&[
  164. Arg::from("--flag [flag] 'some flag'"),
  165. Arg::from("--color [color] 'some other flag'"),
  166. ])
  167. .try_get_matches_from(vec!["", "--flag", "some", "--color", "other"]);
  168. assert!(r.is_ok());
  169. let m = r.unwrap();
  170. assert!(m.is_present("flag"));
  171. assert_eq!(m.value_of("flag").unwrap(), "some");
  172. assert!(m.is_present("color"));
  173. assert_eq!(m.value_of("color").unwrap(), "other");
  174. }
  175. #[test]
  176. fn opts_using_long_equals() {
  177. let r = App::new("opts")
  178. .args(&[
  179. Arg::from("--flag [flag] 'some flag'"),
  180. Arg::from("--color [color] 'some other flag'"),
  181. ])
  182. .try_get_matches_from(vec!["", "--flag=some", "--color=other"]);
  183. assert!(r.is_ok());
  184. let m = r.unwrap();
  185. assert!(m.is_present("flag"));
  186. assert_eq!(m.value_of("flag").unwrap(), "some");
  187. assert!(m.is_present("color"));
  188. assert_eq!(m.value_of("color").unwrap(), "other");
  189. }
  190. #[test]
  191. fn opts_using_mixed() {
  192. let r = App::new("opts")
  193. .args(&[
  194. Arg::from("-f, --flag [flag] 'some flag'"),
  195. Arg::from("-c, --color [color] 'some other flag'"),
  196. ])
  197. .try_get_matches_from(vec!["", "-f", "some", "--color", "other"]);
  198. assert!(r.is_ok());
  199. let m = r.unwrap();
  200. assert!(m.is_present("flag"));
  201. assert_eq!(m.value_of("flag").unwrap(), "some");
  202. assert!(m.is_present("color"));
  203. assert_eq!(m.value_of("color").unwrap(), "other");
  204. }
  205. #[test]
  206. fn opts_using_mixed2() {
  207. let r = App::new("opts")
  208. .args(&[
  209. Arg::from("-f, --flag [flag] 'some flag'"),
  210. Arg::from("-c, --color [color] 'some other flag'"),
  211. ])
  212. .try_get_matches_from(vec!["", "--flag=some", "-c", "other"]);
  213. assert!(r.is_ok());
  214. let m = r.unwrap();
  215. assert!(m.is_present("flag"));
  216. assert_eq!(m.value_of("flag").unwrap(), "some");
  217. assert!(m.is_present("color"));
  218. assert_eq!(m.value_of("color").unwrap(), "other");
  219. }
  220. #[test]
  221. fn default_values_user_value() {
  222. let r = App::new("df")
  223. .arg(Arg::from("-o [opt] 'some opt'").default_value("default"))
  224. .try_get_matches_from(vec!["", "-o", "value"]);
  225. assert!(r.is_ok());
  226. let m = r.unwrap();
  227. assert!(m.is_present("o"));
  228. assert_eq!(m.value_of("o").unwrap(), "value");
  229. }
  230. #[test]
  231. fn multiple_vals_pos_arg_equals() {
  232. let r = App::new("mvae")
  233. .arg(Arg::from("-o [opt]... 'some opt'"))
  234. .arg(Arg::from("[file] 'some file'"))
  235. .try_get_matches_from(vec!["", "-o=1", "some"]);
  236. assert!(r.is_ok());
  237. let m = r.unwrap();
  238. assert!(m.is_present("o"));
  239. assert_eq!(m.value_of("o").unwrap(), "1");
  240. assert!(m.is_present("file"));
  241. assert_eq!(m.value_of("file").unwrap(), "some");
  242. }
  243. #[test]
  244. fn multiple_vals_pos_arg_delim() {
  245. let r = App::new("mvae")
  246. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::UseValueDelimiter))
  247. .arg(Arg::from("[file] 'some file'"))
  248. .try_get_matches_from(vec!["", "-o", "1,2", "some"]);
  249. assert!(r.is_ok());
  250. let m = r.unwrap();
  251. assert!(m.is_present("o"));
  252. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
  253. assert!(m.is_present("file"));
  254. assert_eq!(m.value_of("file").unwrap(), "some");
  255. }
  256. #[test]
  257. fn require_delims_no_delim() {
  258. let r = App::new("mvae")
  259. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::RequireDelimiter))
  260. .arg(Arg::from("[file] 'some file'"))
  261. .try_get_matches_from(vec!["mvae", "-o", "1", "2", "some"]);
  262. assert!(r.is_err());
  263. let err = r.unwrap_err();
  264. assert_eq!(err.kind, ErrorKind::UnknownArgument);
  265. }
  266. #[test]
  267. fn require_delims() {
  268. let r = App::new("mvae")
  269. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::RequireDelimiter))
  270. .arg(Arg::from("[file] 'some file'"))
  271. .try_get_matches_from(vec!["", "-o", "1,2", "some"]);
  272. assert!(r.is_ok());
  273. let m = r.unwrap();
  274. assert!(m.is_present("o"));
  275. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["1", "2"]);
  276. assert!(m.is_present("file"));
  277. assert_eq!(m.value_of("file").unwrap(), "some");
  278. }
  279. #[test]
  280. fn leading_hyphen_pass() {
  281. let r = App::new("mvae")
  282. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::AllowHyphenValues))
  283. .try_get_matches_from(vec!["", "-o", "-2", "3"]);
  284. assert!(r.is_ok());
  285. let m = r.unwrap();
  286. assert!(m.is_present("o"));
  287. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "3"]);
  288. }
  289. #[test]
  290. fn leading_hyphen_fail() {
  291. let r = App::new("mvae")
  292. .arg(Arg::from("-o [opt] 'some opt'"))
  293. .try_get_matches_from(vec!["", "-o", "-2"]);
  294. assert!(r.is_err());
  295. let m = r.unwrap_err();
  296. assert_eq!(m.kind, ErrorKind::UnknownArgument);
  297. }
  298. #[test]
  299. fn leading_hyphen_with_flag_after() {
  300. let r = App::new("mvae")
  301. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::AllowHyphenValues))
  302. .arg("-f 'some flag'")
  303. .try_get_matches_from(vec!["", "-o", "-2", "-f"]);
  304. assert!(r.is_ok());
  305. let m = r.unwrap();
  306. assert!(m.is_present("o"));
  307. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2", "-f"]);
  308. assert!(!m.is_present("f"));
  309. }
  310. #[test]
  311. fn leading_hyphen_with_flag_before() {
  312. let r = App::new("mvae")
  313. .arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::AllowHyphenValues))
  314. .arg("-f 'some flag'")
  315. .try_get_matches_from(vec!["", "-f", "-o", "-2"]);
  316. assert!(r.is_ok());
  317. let m = r.unwrap();
  318. assert!(m.is_present("o"));
  319. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
  320. assert!(m.is_present("f"));
  321. }
  322. #[test]
  323. fn leading_hyphen_with_only_pos_follows() {
  324. let r = App::new("mvae")
  325. .arg(
  326. Arg::from("-o [opt]... 'some opt'")
  327. .number_of_values(1)
  328. .setting(ArgSettings::AllowHyphenValues),
  329. )
  330. .arg("[arg] 'some arg'")
  331. .try_get_matches_from(vec!["", "-o", "-2", "--", "val"]);
  332. assert!(r.is_ok(), "{:?}", r);
  333. let m = r.unwrap();
  334. assert!(m.is_present("o"));
  335. assert_eq!(m.values_of("o").unwrap().collect::<Vec<_>>(), &["-2"]);
  336. assert_eq!(m.value_of("arg"), Some("val"));
  337. }
  338. #[test]
  339. #[cfg(feature = "suggestions")]
  340. fn did_you_mean() {
  341. assert!(utils::compare_output(
  342. utils::complex_app(),
  343. "clap-test --optio=foo",
  344. DYM,
  345. true
  346. ));
  347. }
  348. #[test]
  349. fn issue_665() {
  350. let res = App::new("tester")
  351. .arg("-v, --reroll-count=[N] 'Mark the patch series as PATCH vN'")
  352. .arg(Arg::from(
  353. "--subject-prefix [Subject-Prefix] 'Use [Subject-Prefix] instead of the standard [PATCH] prefix'") )
  354. .try_get_matches_from(vec!["test", "--subject-prefix", "-v", "2"]);
  355. assert!(res.is_err());
  356. assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
  357. }
  358. #[test]
  359. fn issue_1047_min_zero_vals_default_val() {
  360. let m = App::new("foo")
  361. .arg(
  362. Arg::new("del")
  363. .short('d')
  364. .long("del")
  365. .setting(ArgSettings::RequireEquals)
  366. .min_values(0)
  367. .default_value("default"),
  368. )
  369. .get_matches_from(vec!["foo", "-d"]);
  370. assert_eq!(m.occurrences_of("del"), 1);
  371. assert_eq!(m.value_of("del"), Some("default"));
  372. }
  373. fn issue_1105_setup(argv: Vec<&'static str>) -> Result<ArgMatches, clap::Error> {
  374. App::new("opts")
  375. .arg(Arg::from("-o, --option [opt] 'some option'").setting(ArgSettings::AllowEmptyValues))
  376. .arg(Arg::from("--flag 'some flag'"))
  377. .try_get_matches_from(argv)
  378. }
  379. #[test]
  380. fn issue_1105_empty_value_long_fail() {
  381. let r = issue_1105_setup(vec!["app", "--option", "--flag"]);
  382. assert!(r.is_err());
  383. assert_eq!(r.unwrap_err().kind, ErrorKind::EmptyValue);
  384. }
  385. #[test]
  386. fn issue_1105_empty_value_long_explicit() {
  387. let r = issue_1105_setup(vec!["app", "--option", ""]);
  388. assert!(r.is_ok());
  389. let m = r.unwrap();
  390. assert_eq!(m.value_of("option"), Some(""));
  391. }
  392. #[test]
  393. fn issue_1105_empty_value_long_equals() {
  394. let r = issue_1105_setup(vec!["app", "--option="]);
  395. assert!(r.is_ok());
  396. let m = r.unwrap();
  397. assert_eq!(m.value_of("option"), Some(""));
  398. }
  399. #[test]
  400. fn issue_1105_empty_value_short_fail() {
  401. let r = issue_1105_setup(vec!["app", "-o", "--flag"]);
  402. assert!(r.is_err());
  403. assert_eq!(r.unwrap_err().kind, ErrorKind::EmptyValue);
  404. }
  405. #[test]
  406. fn issue_1105_empty_value_short_explicit() {
  407. let r = issue_1105_setup(vec!["app", "-o", ""]);
  408. assert!(r.is_ok());
  409. let m = r.unwrap();
  410. assert_eq!(m.value_of("option"), Some(""));
  411. }
  412. #[test]
  413. fn issue_1105_empty_value_short_equals() {
  414. let r = issue_1105_setup(vec!["app", "-o="]);
  415. assert!(r.is_ok());
  416. let m = r.unwrap();
  417. assert_eq!(m.value_of("option"), Some(""));
  418. }
  419. #[test]
  420. fn issue_1105_empty_value_short_explicit_no_space() {
  421. let r = issue_1105_setup(vec!["app", "-o", ""]);
  422. assert!(r.is_ok());
  423. let m = r.unwrap();
  424. assert_eq!(m.value_of("option"), Some(""));
  425. }
  426. #[test]
  427. #[cfg(feature = "suggestions")]
  428. fn issue_1073_suboptimal_flag_suggestion() {
  429. let app = App::new("ripgrep-616")
  430. .arg(Arg::new("files-with-matches").long("files-with-matches"))
  431. .arg(Arg::new("files-without-match").long("files-without-match"));
  432. assert!(utils::compare_output(
  433. app,
  434. "ripgrep-616 --files-without-matches",
  435. DYM_ISSUE_1073,
  436. true
  437. ));
  438. }
  439. #[test]
  440. fn short_non_ascii_no_space() {
  441. let matches = App::new("app")
  442. .arg("<opt> -磨 <opt>")
  443. .get_matches_from(&["test", "-磨VALUE"]);
  444. assert_eq!("VALUE", matches.value_of("opt").unwrap());
  445. }
  446. #[test]
  447. fn short_eq_val_starts_with_eq() {
  448. let matches = App::new("app")
  449. .arg("<opt> -f <opt>")
  450. .get_matches_from(&["test", "-f==value"]);
  451. assert_eq!("=value", matches.value_of("opt").unwrap());
  452. }
  453. #[test]
  454. fn long_eq_val_starts_with_eq() {
  455. let matches = App::new("app")
  456. .arg("<opt> --foo <opt>")
  457. .get_matches_from(&["test", "--foo==value"]);
  458. assert_eq!("=value", matches.value_of("opt").unwrap());
  459. }