-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_caveats.py
85 lines (74 loc) · 2.33 KB
/
test_caveats.py
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
import pytest
from pyparsing import ParseException
from caveats import parse, evaluate, VALID_OPERATIONS
from hypothesis import given
from hypothesis.strategies import text
TEST_CONTEXT = {"user_id": 1, "expires": 100, "username": "alice", "op": "READ"}
@pytest.mark.parametrize(
"caveat,expected",
[
("k = v", ["k", "=", "v"]),
("k != v", ["k", "!=", "v"]),
("k < v", ["k", "<", "v"]),
("k > v", ["k", ">", "v"]),
("k <= v", ["k", "<=", "v"]),
("k >= v", ["k", ">=", "v"]),
("foo != bar", ["foo", "!=", "bar"]),
("k in [a]", ["k", "in", ["a"]]),
("k in []", ["k", "in", []]),
("curtime <= 123", ["curtime", "<=", 123]),
("abc in [1 2 3]", ["abc", "in", [1, 2, 3]]),
("urn:foo:bar.baz_baz = a:b-c", ["urn:foo:bar.baz_baz", "=", "a:b-c"]),
],
)
def test_parser(caveat, expected):
result = parse(caveat)
assert len(expected) == 3
assert result[0] == expected[0]
assert result[1] == expected[1]
assert result[2] == expected[2]
@pytest.mark.parametrize(
"caveat",
[
"bad",
"foo == bar",
"123 = not a valid key",
"foo = [1, not_a_number]",
"foo = [string, 123]",
"foo = [[heheh]]",
"foo = 1.0",
"A" * 100 + " = foo",
" = bar",
"foo = ",
],
)
def test_invalid_strings(caveat):
with pytest.raises(ParseException):
print(parse(caveat))
@pytest.mark.parametrize(
"s,context,expected",
[
("user_id = 1", TEST_CONTEXT, True),
("missing_context_key = dne", TEST_CONTEXT, False),
("expires <= 100", TEST_CONTEXT, True),
("username != bob", TEST_CONTEXT, True),
("op in [READ WRITE]", TEST_CONTEXT, True),
("op in [WRITE]", TEST_CONTEXT, False),
],
)
def test_evaluate(s, context, expected):
assert evaluate(context, s) == expected
def _type_check(types, o):
# check if an object is one of many types
return any([isinstance(o, t) for t in types])
@given(text())
def test_fuzz_invalid(caveat):
try:
result = parse(caveat)
except ParseException:
# parse errors are probably a good thing. keep moving along.
return
key, opr, val = result
assert opr in VALID_OPERATIONS
assert _type_check([str], key)
assert _type_check([str, int, list], val)