1use crate::error::AssertDiagnostic;
5use crate::match_object;
6use crate::test_spec::Expr;
7use serde_json;
8
9pub fn assert_expr(input: &Vec<&serde_json::Value>, expr: &Expr) -> Result<(), AssertDiagnostic> {
10 log::trace!("checking for condition {expr:?}");
11 match expr {
12 Expr::OneExpr { one } => input
13 .iter()
14 .any(|item| match_object::contains(item, one))
15 .then_some(())
16 .ok_or_else(|| AssertDiagnostic {
17 input: input.iter().cloned().cloned().collect(),
18 expr: expr.clone(),
19 }),
20 Expr::AllExpr { all } => input
21 .iter()
22 .all(|item| match_object::contains(item, all))
23 .then_some(())
24 .ok_or_else(|| AssertDiagnostic {
25 input: input.iter().cloned().cloned().collect(),
26 expr: expr.clone(),
27 }),
28 Expr::SizeExpr { size } => {
29 (input.len() == *size)
30 .then_some(())
31 .ok_or_else(|| AssertDiagnostic {
32 input: vec![serde_json::json!(input.len())],
33 expr: expr.clone(),
34 })
35 }
36 Expr::AndExpr { and } => and
37 .iter()
38 .map(|e| assert_expr(input, e))
39 .collect::<Result<Vec<()>, AssertDiagnostic>>()
40 .map(|_| ()),
41 Expr::OrExpr { or } => or
42 .iter()
43 .any(|e| assert_expr(input, e).is_ok())
44 .then_some(())
45 .ok_or_else(|| AssertDiagnostic {
46 input: input.iter().cloned().cloned().collect(),
47 expr: expr.clone(),
48 }),
49 Expr::NotExpr { not } => assert_expr(input, not)
50 .is_err()
51 .then_some(())
52 .ok_or_else(|| AssertDiagnostic {
53 input: input.iter().cloned().cloned().collect(),
54 expr: expr.clone(),
55 }),
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use rstest::rstest;
63 use serde_json::json;
64
65 #[rstest]
66 #[case(
67 vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
68 Expr::OneExpr { one: json!({"status": "Ready"}) },
69 true
70 )]
71 #[case(
72 vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
73 Expr::AllExpr { all: json!({"status": "Ready"}) },
74 true
75 )]
76 #[case(
77 vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
78 Expr::AllExpr { all: json!({"status": "Ready"}) },
79 false
80 )]
81 #[case(
82 vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
83 Expr::SizeExpr { size: 2 },
84 true
85 )]
86 #[case(
87 vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
88 Expr::SizeExpr { size: 1 },
89 false
90 )]
91 #[case(
92 vec![json!({"status": "Ready"})],
93 Expr::NotExpr { not: Box::new(Expr::SizeExpr { size: 0 }) },
94 true
95 )]
96 #[case(
97 vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
98 Expr::AndExpr { and: vec![
99 Expr::SizeExpr { size: 2 },
100 Expr::OneExpr { one: json!({"status": "Ready"}) },
101 Expr::OneExpr { one: json!({"status": "NotReady"}) },
102 ] },
103 true
104 )]
105 #[case(
106 vec![json!({"status": "Ready"})],
107 Expr::OrExpr { or: vec![
108 Expr::SizeExpr { size: 0 },
109 Expr::SizeExpr { size: 1 },
110 ] },
111 true
112 )]
113 #[case(
114 vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
115 Expr::OrExpr { or: vec![
116 Expr::SizeExpr { size: 3 },
117 Expr::AllExpr { all: json!({"status": "Ready"}) },
118 ] },
119 false
120 )]
121 fn test_assert_expr(
122 #[case] input: Vec<serde_json::Value>,
123 #[case] expr: Expr,
124 #[case] expected: bool,
125 ) {
126 let v = input.iter().collect::<Vec<&serde_json::Value>>();
127 let result = assert_expr(&v, &expr);
128 assert_eq!(result.is_ok(), expected);
129 }
130}