blackjack/
check.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2024 Ole Kliemann
// SPDX-License-Identifier: Apache-2.0

use crate::error::AssertDiagnostic;
use crate::match_object;
use crate::test_spec::Expr;
use serde_json;

pub fn assert_expr(input: &Vec<&serde_json::Value>, expr: &Expr) -> Result<(), AssertDiagnostic> {
    log::trace!("checking {input:?} for condition {expr:?}");
    match expr {
        Expr::OneExpr { one } => input
            .iter()
            .any(|item| match_object::contains(item, one))
            .then_some(())
            .ok_or_else(|| AssertDiagnostic {
                input: input.iter().cloned().cloned().collect(),
                expr: expr.clone(),
            }),
        Expr::AllExpr { all } => input
            .iter()
            .all(|item| match_object::contains(item, all))
            .then_some(())
            .ok_or_else(|| AssertDiagnostic {
                input: input.iter().cloned().cloned().collect(),
                expr: expr.clone(),
            }),
        Expr::SizeExpr { size } => {
            (input.len() == *size)
                .then_some(())
                .ok_or_else(|| AssertDiagnostic {
                    input: input.iter().cloned().cloned().collect(),
                    expr: expr.clone(),
                })
        }
        Expr::AndExpr { and } => and
            .iter()
            .map(|e| assert_expr(input, e))
            .collect::<Result<Vec<()>, AssertDiagnostic>>()
            .map(|_| ()),
        Expr::OrExpr { or } => or
            .iter()
            .any(|e| assert_expr(input, e).is_ok())
            .then_some(())
            .ok_or_else(|| AssertDiagnostic {
                input: input.iter().cloned().cloned().collect(),
                expr: expr.clone(),
            }),
        Expr::NotExpr { not } => assert_expr(input, not)
            .is_err()
            .then_some(())
            .ok_or_else(|| AssertDiagnostic {
                input: input.iter().cloned().cloned().collect(),
                expr: expr.clone(),
            }),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rstest::rstest;
    use serde_json::json;

    #[rstest]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
        Expr::OneExpr { one: json!({"status": "Ready"}) },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
        Expr::AllExpr { all: json!({"status": "Ready"}) },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
        Expr::AllExpr { all: json!({"status": "Ready"}) },
        false
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
        Expr::SizeExpr { size: 2 },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "Ready"})],
        Expr::SizeExpr { size: 1 },
        false
    )]
    #[case(
        vec![json!({"status": "Ready"})],
        Expr::NotExpr { not: Box::new(Expr::SizeExpr { size: 0 }) },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
        Expr::AndExpr { and: vec![
            Expr::SizeExpr { size: 2 },
            Expr::OneExpr { one: json!({"status": "Ready"}) },
            Expr::OneExpr { one: json!({"status": "NotReady"}) },
        ] },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"})],
        Expr::OrExpr { or: vec![
            Expr::SizeExpr { size: 0 },
            Expr::SizeExpr { size: 1 },
        ] },
        true
    )]
    #[case(
        vec![json!({"status": "Ready"}), json!({"status": "NotReady"})],
        Expr::OrExpr { or: vec![
            Expr::SizeExpr { size: 3 },
            Expr::AllExpr { all: json!({"status": "Ready"}) },
        ] },
        false
    )]
    fn test_assert_expr(
        #[case] input: Vec<serde_json::Value>,
        #[case] expr: Expr,
        #[case] expected: bool,
    ) {
        let v = input.iter().collect::<Vec<&serde_json::Value>>();
        let result = assert_expr(&v, &expr);
        assert_eq!(result.is_ok(), expected);
    }
}