|  | // Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu> | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | 
|  | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | 
|  | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | 
|  | // option. This file may not be copied, modified, or distributed | 
|  | // except according to those terms. | 
|  |  | 
|  | mod utils; | 
|  |  | 
|  | use structopt::StructOpt; | 
|  | use utils::*; | 
|  |  | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | enum Opt { | 
|  | /// Fetch stuff from GitHub | 
|  | Fetch { | 
|  | #[structopt(long)] | 
|  | all: bool, | 
|  | #[structopt(short, long)] | 
|  | /// Overwrite local branches. | 
|  | force: bool, | 
|  | repo: String, | 
|  | }, | 
|  |  | 
|  | Add { | 
|  | #[structopt(short, long)] | 
|  | interactive: bool, | 
|  | #[structopt(short, long)] | 
|  | verbose: bool, | 
|  | }, | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_fetch() { | 
|  | assert_eq!( | 
|  | Opt::Fetch { | 
|  | all: true, | 
|  | force: false, | 
|  | repo: "origin".to_string() | 
|  | }, | 
|  | Opt::from_clap(&Opt::clap().get_matches_from(&["test", "fetch", "--all", "origin"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt::Fetch { | 
|  | all: false, | 
|  | force: true, | 
|  | repo: "origin".to_string() | 
|  | }, | 
|  | Opt::from_clap(&Opt::clap().get_matches_from(&["test", "fetch", "-f", "origin"])) | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_add() { | 
|  | assert_eq!( | 
|  | Opt::Add { | 
|  | interactive: false, | 
|  | verbose: false | 
|  | }, | 
|  | Opt::from_clap(&Opt::clap().get_matches_from(&["test", "add"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt::Add { | 
|  | interactive: true, | 
|  | verbose: true | 
|  | }, | 
|  | Opt::from_clap(&Opt::clap().get_matches_from(&["test", "add", "-i", "-v"])) | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_no_parse() { | 
|  | let result = Opt::clap().get_matches_from_safe(&["test", "badcmd", "-i", "-v"]); | 
|  | assert!(result.is_err()); | 
|  |  | 
|  | let result = Opt::clap().get_matches_from_safe(&["test", "add", "--badoption"]); | 
|  | assert!(result.is_err()); | 
|  |  | 
|  | let result = Opt::clap().get_matches_from_safe(&["test"]); | 
|  | assert!(result.is_err()); | 
|  | } | 
|  |  | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | enum Opt2 { | 
|  | DoSomething { arg: String }, | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | /// This test is specifically to make sure that hyphenated subcommands get | 
|  | /// processed correctly. | 
|  | fn test_hyphenated_subcommands() { | 
|  | assert_eq!( | 
|  | Opt2::DoSomething { | 
|  | arg: "blah".to_string() | 
|  | }, | 
|  | Opt2::from_clap(&Opt2::clap().get_matches_from(&["test", "do-something", "blah"])) | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | enum Opt3 { | 
|  | Add, | 
|  | Init, | 
|  | Fetch, | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_null_commands() { | 
|  | assert_eq!( | 
|  | Opt3::Add, | 
|  | Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "add"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt3::Init, | 
|  | Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "init"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt3::Fetch, | 
|  | Opt3::from_clap(&Opt3::clap().get_matches_from(&["test", "fetch"])) | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | #[structopt(about = "Not shown")] | 
|  | struct Add { | 
|  | file: String, | 
|  | } | 
|  | /// Not shown | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | struct Fetch { | 
|  | remote: String, | 
|  | } | 
|  | #[derive(StructOpt, PartialEq, Debug)] | 
|  | enum Opt4 { | 
|  | // Not shown | 
|  | /// Add a file | 
|  | Add(Add), | 
|  | Init, | 
|  | /// download history from remote | 
|  | Fetch(Fetch), | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_tuple_commands() { | 
|  | assert_eq!( | 
|  | Opt4::Add(Add { | 
|  | file: "f".to_string() | 
|  | }), | 
|  | Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "add", "f"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt4::Init, | 
|  | Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "init"])) | 
|  | ); | 
|  | assert_eq!( | 
|  | Opt4::Fetch(Fetch { | 
|  | remote: "origin".to_string() | 
|  | }), | 
|  | Opt4::from_clap(&Opt4::clap().get_matches_from(&["test", "fetch", "origin"])) | 
|  | ); | 
|  |  | 
|  | let output = get_long_help::<Opt4>(); | 
|  |  | 
|  | assert!(output.contains("download history from remote")); | 
|  | assert!(output.contains("Add a file")); | 
|  | assert!(!output.contains("Not shown")); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn enum_in_enum_subsubcommand() { | 
|  | #[derive(StructOpt, Debug, PartialEq)] | 
|  | pub enum Opt { | 
|  | Daemon(DaemonCommand), | 
|  | } | 
|  |  | 
|  | #[derive(StructOpt, Debug, PartialEq)] | 
|  | pub enum DaemonCommand { | 
|  | Start, | 
|  | Stop, | 
|  | } | 
|  |  | 
|  | let result = Opt::clap().get_matches_from_safe(&["test"]); | 
|  | assert!(result.is_err()); | 
|  |  | 
|  | let result = Opt::clap().get_matches_from_safe(&["test", "daemon"]); | 
|  | assert!(result.is_err()); | 
|  |  | 
|  | let result = Opt::from_iter(&["test", "daemon", "start"]); | 
|  | assert_eq!(Opt::Daemon(DaemonCommand::Start), result); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn flatten_enum() { | 
|  | #[derive(StructOpt, Debug, PartialEq)] | 
|  | struct Opt { | 
|  | #[structopt(flatten)] | 
|  | sub_cmd: SubCmd, | 
|  | } | 
|  | #[derive(StructOpt, Debug, PartialEq)] | 
|  | enum SubCmd { | 
|  | Foo, | 
|  | Bar, | 
|  | } | 
|  |  | 
|  | assert!(Opt::from_iter_safe(&["test"]).is_err()); | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "foo"]), | 
|  | Opt { | 
|  | sub_cmd: SubCmd::Foo | 
|  | } | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn external_subcommand() { | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | struct Opt { | 
|  | #[structopt(subcommand)] | 
|  | sub: Subcommands, | 
|  | } | 
|  |  | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | enum Subcommands { | 
|  | Add, | 
|  | Remove, | 
|  | #[structopt(external_subcommand)] | 
|  | Other(Vec<String>), | 
|  | } | 
|  |  | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "add"]), | 
|  | Opt { | 
|  | sub: Subcommands::Add | 
|  | } | 
|  | ); | 
|  |  | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "remove"]), | 
|  | Opt { | 
|  | sub: Subcommands::Remove | 
|  | } | 
|  | ); | 
|  |  | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "git", "status"]), | 
|  | Opt { | 
|  | sub: Subcommands::Other(vec!["git".into(), "status".into()]) | 
|  | } | 
|  | ); | 
|  |  | 
|  | assert!(Opt::from_iter_safe(&["test"]).is_err()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn external_subcommand_os_string() { | 
|  | use std::ffi::OsString; | 
|  |  | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | struct Opt { | 
|  | #[structopt(subcommand)] | 
|  | sub: Subcommands, | 
|  | } | 
|  |  | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | enum Subcommands { | 
|  | #[structopt(external_subcommand)] | 
|  | Other(Vec<OsString>), | 
|  | } | 
|  |  | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "git", "status"]), | 
|  | Opt { | 
|  | sub: Subcommands::Other(vec!["git".into(), "status".into()]) | 
|  | } | 
|  | ); | 
|  |  | 
|  | assert!(Opt::from_iter_safe(&["test"]).is_err()); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn external_subcommand_optional() { | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | struct Opt { | 
|  | #[structopt(subcommand)] | 
|  | sub: Option<Subcommands>, | 
|  | } | 
|  |  | 
|  | #[derive(Debug, PartialEq, StructOpt)] | 
|  | enum Subcommands { | 
|  | #[structopt(external_subcommand)] | 
|  | Other(Vec<String>), | 
|  | } | 
|  |  | 
|  | assert_eq!( | 
|  | Opt::from_iter(&["test", "git", "status"]), | 
|  | Opt { | 
|  | sub: Some(Subcommands::Other(vec!["git".into(), "status".into()])) | 
|  | } | 
|  | ); | 
|  |  | 
|  | assert_eq!(Opt::from_iter(&["test"]), Opt { sub: None }); | 
|  | } |