audit-labs/audit-report
Turn audit-tools evidence packages into control-mapped, auditor-ready reports.
clone: git clone https://gitbay.org/audit-labs/audit-report.git
v1.0.0: tests/test_rules.py · raw
1"""Unit tests for the condition language in audit_report.rules."""
2
3import pytest
4
5from audit_report.rules import match
6
7
8@pytest.mark.parametrize(
9 ("condition", "row", "expected"),
10 [
11 ({"column": "x", "op": "equals", "value": "read"}, {"x": "read"}, True),
12 ({"column": "x", "op": "equals", "value": "Read"}, {"x": "read"}, True), # case-insensitive
13 ({"column": "x", "op": "not_equals", "value": "read"}, {"x": "write"}, True),
14 ({"column": "x", "op": "is_true"}, {"x": "True"}, True),
15 ({"column": "x", "op": "is_true"}, {"x": "yes"}, True),
16 ({"column": "x", "op": "is_false"}, {"x": "False"}, True),
17 ({"column": "x", "op": "is_false"}, {"x": ""}, True), # empty reads as false
18 ({"column": "x", "op": "gt", "value": 90}, {"x": "404"}, True),
19 ({"column": "x", "op": "gt", "value": 90}, {"x": "30"}, False),
20 ({"column": "x", "op": "lte", "value": 90}, {"x": "90"}, True),
21 ({"column": "x", "op": "gt", "value": 90}, {"x": ""}, False), # non-numeric -> False
22 ({"column": "x", "op": "in", "value": ["read", "none"]}, {"x": "none"}, True),
23 ({"column": "x", "op": "not_in", "value": ["read", "none"]}, {"x": "admin"}, True),
24 ({"column": "x", "op": "empty"}, {"x": " "}, True),
25 ({"column": "x", "op": "not_empty"}, {"x": "v"}, True),
26 ],
27)
28def test_leaf_conditions(condition, row, expected):
29 assert match(condition, row) is expected
30
31
32def test_boolean_combinators():
33 row = {"console_password": "True", "mfa_enabled": "False"}
34 cond = {
35 "all": [
36 {"column": "console_password", "op": "is_true"},
37 {"column": "mfa_enabled", "op": "is_false"},
38 ]
39 }
40 assert match(cond, row) is True
41 assert match({"any": [{"column": "mfa_enabled", "op": "is_true"}]}, row) is False
42 assert match({"not": {"column": "mfa_enabled", "op": "is_true"}}, row) is True
43
44
45def test_malformed_condition_raises():
46 with pytest.raises(ValueError, match="malformed condition"):
47 match({"value": "x"}, {"x": "y"})
48
49
50def test_unknown_operator_raises():
51 with pytest.raises(ValueError, match="unknown operator"):
52 match({"column": "x", "op": "wat"}, {"x": "y"})