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

main: 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"})