1747ad3c4Slazypassion //! Test commands. 2747ad3c4Slazypassion //! 3747ad3c4Slazypassion //! A `.clif` file can begin with one or more *test commands* which specify what is to be tested. 4747ad3c4Slazypassion //! The general syntax is: 5747ad3c4Slazypassion //! 6747ad3c4Slazypassion //! <pre> 7d38d387aSAlex Crichton //! test <i><command></i> <i>[options]</i>... 8747ad3c4Slazypassion //! </pre> 9747ad3c4Slazypassion //! 10747ad3c4Slazypassion //! The options are either a single identifier flag, or setting values like `identifier=value`. 11747ad3c4Slazypassion //! 12747ad3c4Slazypassion //! The parser does not understand the test commands or which options are valid. It simply parses 13747ad3c4Slazypassion //! the general format into a `TestCommand` data structure. 14747ad3c4Slazypassion 15747ad3c4Slazypassion use std::fmt::{self, Display, Formatter}; 16747ad3c4Slazypassion 17747ad3c4Slazypassion /// A command appearing in a test file. 18747ad3c4Slazypassion #[derive(Clone, PartialEq, Eq, Debug)] 19747ad3c4Slazypassion pub struct TestCommand<'a> { 20747ad3c4Slazypassion /// The command name as a string. 21747ad3c4Slazypassion pub command: &'a str, 22747ad3c4Slazypassion /// The options following the command name. 23747ad3c4Slazypassion pub options: Vec<TestOption<'a>>, 24747ad3c4Slazypassion } 25747ad3c4Slazypassion 26747ad3c4Slazypassion /// An option on a test command. 27747ad3c4Slazypassion #[derive(Clone, PartialEq, Eq, Debug)] 28747ad3c4Slazypassion pub enum TestOption<'a> { 29747ad3c4Slazypassion /// Single identifier flag: `foo`. 30747ad3c4Slazypassion Flag(&'a str), 31747ad3c4Slazypassion /// A value assigned to an identifier: `foo=bar`. 32747ad3c4Slazypassion Value(&'a str, &'a str), 33747ad3c4Slazypassion } 34747ad3c4Slazypassion 35747ad3c4Slazypassion impl<'a> TestCommand<'a> { 36747ad3c4Slazypassion /// Create a new TestCommand by parsing `s`. 37747ad3c4Slazypassion /// The returned command contains references into `s`. new(s: &'a str) -> Self38747ad3c4Slazypassion pub fn new(s: &'a str) -> Self { 39747ad3c4Slazypassion let mut parts = s.split_whitespace(); 40747ad3c4Slazypassion let cmd = parts.next().unwrap_or(""); 41747ad3c4Slazypassion Self { 42747ad3c4Slazypassion command: cmd, 43747ad3c4Slazypassion options: parts 44747ad3c4Slazypassion .filter(|s| !s.is_empty()) 45747ad3c4Slazypassion .map(TestOption::new) 46747ad3c4Slazypassion .collect(), 47747ad3c4Slazypassion } 48747ad3c4Slazypassion } 49747ad3c4Slazypassion } 50747ad3c4Slazypassion 51747ad3c4Slazypassion impl<'a> Display for TestCommand<'a> { fmt(&self, f: &mut Formatter) -> fmt::Result52747ad3c4Slazypassion fn fmt(&self, f: &mut Formatter) -> fmt::Result { 53747ad3c4Slazypassion write!(f, "{}", self.command)?; 54747ad3c4Slazypassion for opt in &self.options { 55*a0442ea0SHamir Mahal write!(f, " {opt}")?; 56747ad3c4Slazypassion } 57747ad3c4Slazypassion writeln!(f) 58747ad3c4Slazypassion } 59747ad3c4Slazypassion } 60747ad3c4Slazypassion 61747ad3c4Slazypassion impl<'a> TestOption<'a> { 62747ad3c4Slazypassion /// Create a new TestOption by parsing `s`. 63747ad3c4Slazypassion /// The returned option contains references into `s`. new(s: &'a str) -> Self64747ad3c4Slazypassion pub fn new(s: &'a str) -> Self { 65747ad3c4Slazypassion match s.find('=') { 66747ad3c4Slazypassion None => TestOption::Flag(s), 67747ad3c4Slazypassion Some(p) => TestOption::Value(&s[0..p], &s[p + 1..]), 68747ad3c4Slazypassion } 69747ad3c4Slazypassion } 70747ad3c4Slazypassion } 71747ad3c4Slazypassion 72747ad3c4Slazypassion impl<'a> Display for TestOption<'a> { fmt(&self, f: &mut Formatter) -> fmt::Result73747ad3c4Slazypassion fn fmt(&self, f: &mut Formatter) -> fmt::Result { 74747ad3c4Slazypassion match *self { 75*a0442ea0SHamir Mahal TestOption::Flag(s) => write!(f, "{s}"), 76*a0442ea0SHamir Mahal TestOption::Value(s, v) => write!(f, "{s}={v}"), 77747ad3c4Slazypassion } 78747ad3c4Slazypassion } 79747ad3c4Slazypassion } 80747ad3c4Slazypassion 81747ad3c4Slazypassion #[cfg(test)] 82747ad3c4Slazypassion mod tests { 83747ad3c4Slazypassion use super::*; 84747ad3c4Slazypassion 85747ad3c4Slazypassion #[test] parse_option()86747ad3c4Slazypassion fn parse_option() { 87747ad3c4Slazypassion assert_eq!(TestOption::new(""), TestOption::Flag("")); 88747ad3c4Slazypassion assert_eq!(TestOption::new("foo"), TestOption::Flag("foo")); 89747ad3c4Slazypassion assert_eq!(TestOption::new("foo=bar"), TestOption::Value("foo", "bar")); 90747ad3c4Slazypassion } 91747ad3c4Slazypassion 92747ad3c4Slazypassion #[test] parse_command()93747ad3c4Slazypassion fn parse_command() { 94747ad3c4Slazypassion assert_eq!(&TestCommand::new("").to_string(), "\n"); 95747ad3c4Slazypassion assert_eq!(&TestCommand::new("cat").to_string(), "cat\n"); 96747ad3c4Slazypassion assert_eq!(&TestCommand::new("cat ").to_string(), "cat\n"); 97747ad3c4Slazypassion assert_eq!(&TestCommand::new("cat 1 ").to_string(), "cat 1\n"); 98747ad3c4Slazypassion assert_eq!( 99747ad3c4Slazypassion &TestCommand::new("cat one=4 two t").to_string(), 100747ad3c4Slazypassion "cat one=4 two t\n" 101747ad3c4Slazypassion ); 102747ad3c4Slazypassion } 103747ad3c4Slazypassion } 104