summary refs log tree commit diff stats
path: root/testing
diff options
context:
space:
mode:
Diffstat (limited to 'testing')
-rw-r--r--testing/test_abdl.py4
-rw-r--r--testing/test_examples.py25
-rw-r--r--testing/test_ops_abdl.py161
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()