diff options
| author | Nixon Enraght-Moony <nixon.emoony@gmail.com> | 2022-07-19 16:54:53 +0100 |
|---|---|---|
| committer | Nixon Enraght-Moony <nixon.emoony@gmail.com> | 2022-08-12 18:11:55 +0100 |
| commit | 64f790f030494f586a0754536dc85a50aedb77f6 (patch) | |
| tree | a927bdb713916c65c4add37683396d4454bc1080 | |
| parent | dacffd22a0a6803fb38e2c50cbbd726d52c94ad3 (diff) | |
| download | rust-64f790f030494f586a0754536dc85a50aedb77f6.tar.gz rust-64f790f030494f586a0754536dc85a50aedb77f6.zip | |
Jsondocck: New `@ismany` command
| -rw-r--r-- | src/tools/jsondocck/src/main.rs | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index c4462466646..022f7eb8e02 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -50,6 +50,7 @@ pub enum CommandKind { Has, Count, Is, + IsMany, Set, } @@ -57,6 +58,7 @@ impl CommandKind { fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool { let count = match self { CommandKind::Has => (1..=3).contains(&args.len()), + CommandKind::IsMany => args.len() >= 3, CommandKind::Count | CommandKind::Is => 3 == args.len(), CommandKind::Set => 4 == args.len(), }; @@ -89,6 +91,7 @@ impl fmt::Display for CommandKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let text = match self { CommandKind::Has => "has", + CommandKind::IsMany => "ismany", CommandKind::Count => "count", CommandKind::Is => "is", CommandKind::Set => "set", @@ -137,6 +140,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> { "has" => CommandKind::Has, "count" => CommandKind::Count, "is" => CommandKind::Is, + "ismany" => CommandKind::IsMany, "set" => CommandKind::Set, _ => { print_err(&format!("Unrecognized command name `@{}`", cmd), lineno); @@ -227,6 +231,44 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { _ => unreachable!(), } } + CommandKind::IsMany => { + // @ismany <path> <jsonpath> <value>... + let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] { + (path, query, values) + } else { + unreachable!("Checked in CommandKind::validate") + }; + let val = cache.get_value(path)?; + let got_values = select(&val, &query).unwrap(); + assert!(!command.negated, "`@!ismany` is not supported"); + + // Serde json doesn't implement Ord or Hash for Value, so we must + // use a Vec here. While in theory that makes setwize equality + // O(n^2), in practice n will never be large enought to matter. + let expected_values = + values.iter().map(|v| string_to_value(v, cache)).collect::<Vec<_>>(); + if expected_values.len() != got_values.len() { + return Err(CkError::FailedCheck( + format!( + "Expected {} values, but `{}` matched to {} values ({:?})", + expected_values.len(), + query, + got_values.len(), + got_values + ), + command, + )); + }; + for got_value in got_values { + if !expected_values.iter().any(|exp| &**exp == got_value) { + return Err(CkError::FailedCheck( + format!("`{}` has match {:?}, which was not expected", query, got_value), + command, + )); + } + } + true + } CommandKind::Count => { // @count <path> <jsonpath> <count> = Check that the jsonpath matches exactly [count] times assert_eq!(command.args.len(), 3); |
