diff options
Diffstat (limited to 'testing')
-rw-r--r-- | testing/test_abdl.py | 4 | ||||
-rw-r--r-- | testing/test_examples.py | 25 | ||||
-rw-r--r-- | testing/test_ops_abdl.py | 161 |
3 files changed, 186 insertions, 4 deletions
diff --git a/testing/test_abdl.py b/testing/test_abdl.py index 080ab3f..4f5241f 100644 --- a/testing/test_abdl.py +++ b/testing/test_abdl.py @@ -182,6 +182,10 @@ def test_param(foo, pat): yield {"X": x, "Z": z} assert all(LogAndCompare(pat.match(foo), deep(foo))) +def test_basic_value_subtree(): + matcher = abdl.match("(->foo'foo')(->bar'bar')", {'foo': 1, 'bar': 2}) + assert list(matcher) == [{'foo': ('foo', 1), 'bar': ('bar', 2)}] + # FIXME #@hypothesis.given(objtree, st.text()) #def test_exhaustive(foo, pat): diff --git a/testing/test_examples.py b/testing/test_examples.py index 7341341..02532cc 100644 --- a/testing/test_examples.py +++ b/testing/test_examples.py @@ -1,9 +1,26 @@ import abdl def test_basic_example(): - for m in abdl.match("->X:?$dict->Y", {"foo": 1, "bar": {"baz": 2}}, {'dict': dict}): - assert m['X'][0] == 'bar' and m['Y'][0] == 'baz' and m['Y'][1] == 2 + m = next(abdl.match("->X:?$dict->Y", {"foo": 1, "bar": {"baz": 2}}, {'dict': dict})) + assert m['X'][0] == 'bar' + assert m['Y'][0] == 'baz' + assert m['Y'][1] == 2 def test_basic_2(): - for m in abdl.match("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", {"projects": {"385e734a52e13949a7a5c71827f6de920dbfea43": {"https://soniex2.autistic.space/git-repos/ganarchy.git": {"HEAD": {"active": True}}}}}, {'d': dict}): - assert m['P'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" and m['U'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" and m['B'][0] == "HEAD" and m['B'][1] == {"active": True} + m = next(abdl.match("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", {"projects": {"385e734a52e13949a7a5c71827f6de920dbfea43": {"https://soniex2.autistic.space/git-repos/ganarchy.git": {"HEAD": {"active": True}}}}}, {'d': dict})) + assert m['P'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" + assert m['U'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" + assert m['B'][0] == "HEAD" + assert m['B'][1] == {"active": True} + +def test_spaces(): + pat = abdl.compile("""-> 'projects'? + -> commit /[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/? :?$dict + -> url :?$dict + -> branch :?$dict""", {'dict': dict}) + data = {"projects": {"385e734a52e13949a7a5c71827f6de920dbfea43": {"https://soniex2.autistic.space/git-repos/ganarchy.git": {"HEAD": {"active": True}}}}} + m = next(pat.match(data)) + assert m['commit'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" + assert m['url'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" + assert m['branch'][0] == "HEAD" + assert m['branch'][1] == {"active": True} diff --git a/testing/test_ops_abdl.py b/testing/test_ops_abdl.py new file mode 100644 index 0000000..fe50369 --- /dev/null +++ b/testing/test_ops_abdl.py @@ -0,0 +1,161 @@ +# Tests abdl.py internals + +import abdl + +import re + +class OpHelper: + def __init__(self, pat, ops=None): + self.pat = pat + if not ops: + self.ops = pat._ops + else: + self.ops = ops + self.pos = -1 + + def done(self): + assert self.pos + 1 == len(self.ops) + + def __enter__(self): + self.pos += 1 + first = self.pos + assert not isinstance(self.ops[first], abdl._End) + while not isinstance(self.ops[self.pos], abdl._End): + self.pos += 1 + assert isinstance(self.ops[self.pos], abdl._End) + return self.ops[first:self.pos] + + def __exit__(self, exc_type, exc_value, traceback): + pass + +def expect_types(seq, *tys): + assert len(seq) == len(tys) + assert(all(map(lambda x: isinstance(*x), zip(seq, tys)))) + +def expect_idents(oph, *idents): + for ident in idents: + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._Ident) + assert ops[1].key == ident + +def test_empty_iterator_pattern(): + oph = OpHelper(abdl.compile("")) + oph.done() + +def test_four_depths_pattern(): + oph = OpHelper(abdl.compile("->X->Y->Z->W")) + expect_idents(oph, "X", "Y", "Z", "W") + oph.done() + +def test_regex_pattern(): + oph = OpHelper(abdl.compile("->/.../")) + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._RegexKey) + assert ops[1].key == '...' + assert ops[1].compiled == re.compile('...') + assert ops[1].skippable == False + oph.done() + +def test_regex_skippable_pattern(): + oph = OpHelper(abdl.compile("->/.../?")) + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._RegexKey) + assert ops[1].key == '...' + assert ops[1].compiled == re.compile('...') + assert ops[1].skippable == True + oph.done() + +def test_regex_and_bind_pattern(): + oph = OpHelper(abdl.compile("->/.../->Y")) + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._RegexKey) + assert ops[1].key == '...' + assert ops[1].compiled == re.compile('...') + assert ops[1].skippable == False + expect_idents(oph, "Y") + oph.done() + +def test_empty_literal_skippable_and_bind_pattern(): + oph = OpHelper(abdl.compile("->''?->Y")) + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._StringKey) + assert ops[1].key == '' + assert ops[1].skippable == True + expect_idents(oph, "Y") + oph.done() + +def test_type_pattern(): + oph = OpHelper(abdl.compile("->X:?$a->Y", defs={'a': (dict, list, set)})) + assert oph.pat._defs['a'] == (dict, list, set) + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._Ident, abdl._Ty) + assert ops[1].key == 'X' + assert ops[2].key == 'a' + assert ops[2].skippable == True + expect_idents(oph, "Y") + oph.done() + +def test_multi_type_pattern(): + oph = OpHelper(abdl.compile("->X:$a:?$b:?$c->Y", defs={'a': (dict, list, set), 'b': (dict, set), 'c': dict})) + assert oph.pat._defs['a'] == (dict, list, set) + assert oph.pat._defs['b'] == (dict, set) + assert oph.pat._defs['c'] == dict + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._Ident, abdl._Ty, abdl._Ty, abdl._Ty) + assert ops[1].key == 'X' + assert ops[2].key == 'a' + assert ops[2].skippable == False + assert ops[3].key == 'b' + assert ops[3].skippable == True + assert ops[4].key == 'c' + assert ops[4].skippable == True + expect_idents(oph, "Y") + oph.done() + +def test_key_subtree_pattern(): + oph = OpHelper(abdl.compile("->[:?$set->A]->D", defs={'set': set})) + assert oph.pat._defs['set'] == set + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._KeySubtree) + oph2 = OpHelper(None, ops=ops[1].key) + with oph2 as ops2: + expect_types(ops2, abdl._Ty, abdl._Arrow, abdl._Ident) + assert ops2[0].key == 'set' + assert ops2[0].skippable == True + assert ops2[2].key == 'A' + oph2.done() + expect_idents(oph, "D") + oph.done() + +def test_param_pattern(): + oph = OpHelper(abdl.compile("->X->$a->Z", defs={'a': '0'})) + assert oph.pat._defs['a'] == '0' + expect_idents(oph, "X") + with oph as ops: + expect_types(ops, abdl._Arrow, abdl._Param) + assert ops[1].key == 'a' + assert ops[1].skippable == False + expect_idents(oph, "Z") + oph.done() + +def test_value_subtree_pattern(): + oph = OpHelper(abdl.compile("(->foo'foo')(->bar'bar')")) + with oph as ops: + expect_types(ops, abdl._ValueSubtree) + oph2 = OpHelper(None, ops=ops[0].key) + with oph2 as ops2: + expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) + assert ops2[1].key == 'foo' + assert ops2[2].key == 'foo' + assert ops2[2].skippable == False + oph2.done() + with oph as ops: + expect_types(ops, abdl._ValueSubtree) + oph2 = OpHelper(None, ops=ops[0].key) + with oph2 as ops2: + expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) + assert ops2[1].key == 'bar' + assert ops2[2].key == 'bar' + assert ops2[2].skippable == False + oph2.done() + oph.done() |