about summary refs log tree commit diff
path: root/tests/unit/test_privileges_spec_parsing.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/test_privileges_spec_parsing.py')
-rw-r--r--tests/unit/test_privileges_spec_parsing.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/tests/unit/test_privileges_spec_parsing.py b/tests/unit/test_privileges_spec_parsing.py
new file mode 100644
index 0000000..7b563e1
--- /dev/null
+++ b/tests/unit/test_privileges_spec_parsing.py
@@ -0,0 +1,141 @@
+"""Tests for parsing the privileges checks specification."""
+import pytest
+
+from gn_libs.privileges import parse, SpecificationValueError
+
+
+## NOTE: Should we limit depth of nesting of checks, e.g. don't do more than
+## 3 levels or so?
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec",
+    ("",
+     "(AND)",
+     "(AND (OR))",
+     "(OR (AND))",
+     "(OR (AND (OR (AND ))))"))
+def test_empty_spec(spec):
+    """
+    GIVEN: An effectively empty specification
+    WHEN: The specification is parsed
+    THEN: Raise a `SpecificationValueError`
+    """
+    with pytest.raises(SpecificationValueError):
+        parse(spec)
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    (("(AND priv1)", ("AND", ("priv1",))),
+     ("(AND priv1 priv2)", ("AND", ("priv1", "priv2"))),
+     ("(AND priv1 priv2 priv3)", ("AND", ("priv1", "priv2", "priv3"))),
+     ("(and priv1)", ("AND", ("priv1",))),
+     ("(and priv1 priv2)", ("AND", ("priv1", "priv2"))),
+     ("(and priv1 priv2 priv3)", ("AND", ("priv1", "priv2", "priv3"))),
+     ("(and priv1 priv2 (and priv3 priv4))",
+      ("AND", ("priv1", "priv2", "priv3", "priv4")))))
+def test_and(spec, expected):
+    """
+    GIVEN: A simple 'AND' privileges check specification `spec`
+    WHEN: The specification is parsed
+    THEN: Verify the parsed output gives an 'AND' check object
+    """
+    assert parse(spec) == expected
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    (("(OR priv1)", ("OR", ("priv1",))),
+     ("(OR priv1 priv2)", ("OR", ("priv1", "priv2"))),
+     ("(OR priv1 priv2 priv3)", ("OR", ("priv1", "priv2", "priv3"))),
+     ("(or priv1)", ("OR", ("priv1",))),
+     ("(or priv1 priv2)", ("OR", ("priv1", "priv2"))),
+     ("(or priv1 priv2 priv3)", ("OR", ("priv1", "priv2", "priv3")))))
+def test_or(spec, expected):
+    """
+    GIVEN: A simple 'OR' privileges check specification `spec`
+    WHEN: The specification is parsed
+    THEN: Verify the parsed output gives an 'OR' check object
+    """
+    assert parse(spec) == expected
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    (("(or priv1 priv2 (or priv3 priv4))",
+      ("OR", ("priv1", "priv2", "priv3", "priv4"))),
+     ("(and priv1 priv2 (and priv3 priv4))",
+      ("AND", ("priv1", "priv2", "priv3", "priv4")))))
+def test_merging(spec, expected):
+    """
+    GIVEN:
+    - A nested specification where 2 or more of subsequent operators are
+    - the same
+    WHEN: The specification is parsed
+    THEN: Verify the parsed output merges the checks into a single object
+    """
+    # NOTE: The "given-when-then" description above does not please me.
+    assert parse(spec) == expected
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    ())
+def test_and_or(spec, expected):
+    """
+    GIVEN:
+    - A specification beginning with an "AND" operator followed by an "OR"
+    - operator
+    WHEN: The specification is parsed
+    THEN: Verify the parsed output is correct
+    """
+    assert parse(spec) == expected
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    ())
+def test_or_and(spec, expected):
+    """
+    GIVEN:
+    - A specification beginning with an "OR" operator followed by an "AND"
+    - operator
+    WHEN: The specification is parsed
+    THEN: Verify the parsed output is correct
+    """
+    assert parse(spec) == expected
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec",
+    ())
+def test_invalid(spec):
+    """
+    GIVEN: An invalid specification
+    WHEN: The specification is parsed
+    THEN: Verify that the `SpecificationValueError` is raised
+    """
+    # NOTE: Maybe use hypothesis to generate random strings?
+    with pytest.raises(SpecificationValueError):
+        assert parse(spec)
+
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "spec,expected",
+    ())
+def test_complex(spec, expected):
+    """
+    GIVEN: An valid, but more complex specification
+    WHEN: The specification is parsed
+    THEN: Verify that the specification parses correctly
+    """
+    assert parse(spec) == expected