@@ -48,13 +48,14 @@ pub struct Command {
4848pub enum CommandKind {
4949 Has ,
5050 Count ,
51+ Is ,
5152}
5253
5354impl CommandKind {
5455 fn validate ( & self , args : & [ String ] , command_num : usize , lineno : usize ) -> bool {
5556 let count = match self {
5657 CommandKind :: Has => ( 1 ..=3 ) . contains ( & args. len ( ) ) ,
57- CommandKind :: Count => 3 == args. len ( ) ,
58+ CommandKind :: Count | CommandKind :: Is => 3 == args. len ( ) ,
5859 } ;
5960
6061 if !count {
@@ -83,6 +84,7 @@ impl fmt::Display for CommandKind {
8384 let text = match self {
8485 CommandKind :: Has => "has" ,
8586 CommandKind :: Count => "count" ,
87+ CommandKind :: Is => "is" ,
8688 } ;
8789 write ! ( f, "{}" , text)
8890 }
@@ -127,6 +129,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
127129 let cmd = match cmd {
128130 "has" => CommandKind :: Has ,
129131 "count" => CommandKind :: Count ,
132+ "is" => CommandKind :: Is ,
130133 _ => {
131134 print_err ( & format ! ( "Unrecognized command name `@{}`" , cmd) , lineno) ;
132135 errors = true ;
@@ -180,6 +183,7 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
180183/// Performs the actual work of ensuring a command passes. Generally assumes the command
181184/// is syntactically valid.
182185fn check_command ( command : Command , cache : & mut Cache ) -> Result < ( ) , CkError > {
186+ // FIXME: Be more granular about why, (eg syntax error, count not equal)
183187 let result = match command. kind {
184188 CommandKind :: Has => {
185189 match command. args . len ( ) {
@@ -220,6 +224,18 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> {
220224 Err ( _) => false ,
221225 }
222226 }
227+ CommandKind :: Is => {
228+ // @has <path> <jsonpath> <value> = check *exactly one* item matched by path, and it equals value
229+ assert_eq ! ( command. args. len( ) , 3 ) ;
230+ let val = cache. get_value ( & command. args [ 0 ] ) ?;
231+ match select ( & val, & command. args [ 1 ] ) {
232+ Ok ( results) => {
233+ let pat: Value = serde_json:: from_str ( & command. args [ 2 ] ) . unwrap ( ) ;
234+ results. len ( ) == 1 && * results[ 0 ] == pat
235+ }
236+ Err ( _) => false ,
237+ }
238+ }
223239 } ;
224240
225241 if result == command. negated {
0 commit comments