blackjack/
check.rs

1// Copyright 2024 Ole Kliemann
2// SPDX-License-Identifier: Apache-2.0
3
4use 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}