diff options
Diffstat (limited to 'test/graph/test_resolve.py')
-rw-r--r-- | test/graph/test_resolve.py | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/test/graph/test_resolve.py b/test/graph/test_resolve.py new file mode 100644 index 0000000..5bc99e4 --- /dev/null +++ b/test/graph/test_resolve.py @@ -0,0 +1,181 @@ +""" + +Part of the bsfs test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsfs import schema as bsc +from bsfs.graph import Graph, nodes +from bsfs.namespace import ns +from bsfs.query import ast +from bsfs.triple_store import SparqlStore +from bsfs.utils import URI, errors + +# objects to test +from bsfs.graph.resolve import Filter + + +## code ## + +class TestFilter(unittest.TestCase): + """ + + NOTE: The Filter resolver is relatively simple as it only checks and changes + ast.filter.Is instances. Hence, we don't test all methods individually but + all of them with respect to ast.filter.Is elements. + + """ + + def test_call(self): + schema = bsc.Schema.from_string(''' + prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> + prefix xsd: <http://www.w3.org/2001/XMLSchema#> + + prefix bsfs: <http://bsfs.ai/schema/> + prefix bse: <http://bsfs.ai/schema/Entity#> + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Tag rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Literal . + + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:integer ; + bsfs:unique "false"^^xsd:boolean . + + bse:tag rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Tag ; + bsfs:unique "false"^^xsd:boolean . + ''') + backend = SparqlStore.Open() + backend.schema = schema + graph = Graph(backend, URI('http://example.com/me')) + ents = graph.nodes(ns.bsfs.Entity, + {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')}) + tags = graph.nodes(ns.bsfs.Tag, + {URI('http://example.com/me/tag#1234'), URI('http://example.com/me/tag#4321')}) + invalid = nodes.Nodes(None, '', schema.node(ns.bsfs.Node).get_child(ns.bsfs.Invalid), + {'http://example.com/you/invalid#1234', 'http://example.com/you/invalid#4321'}) + resolver = Filter(schema) + + # immediate Is + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Is(ents)), + ast.filter.Or( + ast.filter.Is('http://example.com/me/entity#1234'), + ast.filter.Is('http://example.com/me/entity#4321') + )) + # only resolves nodes instances, not URIs + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Is('http://example.com/me/entity#1234')), + ast.filter.Is('http://example.com/me/entity#1234')) + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Is(1234)), + ast.filter.Is(1234)) + + # within And (also checks _value) + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.And( + ast.filter.Is(ents), + ast.filter.Any(ns.bse.comment, ast.filter.Equals('hello world')), + )), + ast.filter.And( + ast.filter.Or( + ast.filter.Is('http://example.com/me/entity#1234'), + ast.filter.Is('http://example.com/me/entity#4321')), + ast.filter.Any(ns.bse.comment, ast.filter.Equals('hello world')) + )) + # within Or (checks _bounded) + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Or( + ast.filter.Is(ents), + ast.filter.Any(ns.bse.filesize, ast.filter.LessThan(5)), + )), + ast.filter.Or( + ast.filter.Or( + ast.filter.Is('http://example.com/me/entity#1234'), + ast.filter.Is('http://example.com/me/entity#4321')), + ast.filter.Any(ns.bse.filesize, ast.filter.LessThan(5)) + )) + + # Any-branched Is + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Any(ns.bse.tag, ast.filter.Is(tags))), + ast.filter.Any(ns.bse.tag, ast.filter.Or( + ast.filter.Is('http://example.com/me/tag#1234'), + ast.filter.Is('http://example.com/me/tag#4321')), + )) + # All-branched Is + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.All(ns.bse.tag, ast.filter.Is(tags))), + ast.filter.All(ns.bse.tag, ast.filter.Or( + ast.filter.Is('http://example.com/me/tag#1234'), + ast.filter.Is('http://example.com/me/tag#4321')), + )) + # Negated predicate + self.assertEqual(resolver(schema.node(ns.bsfs.Tag), + ast.filter.Any(ast.filter.Predicate(ns.bse.tag, reverse=True), ast.filter.Is(ents))), + ast.filter.Any(ast.filter.Predicate(ns.bse.tag, reverse=True), ast.filter.Or( + ast.filter.Is('http://example.com/me/entity#1234'), + ast.filter.Is('http://example.com/me/entity#4321')), + )) + + # negated Is + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Not(ast.filter.Is(ents))), + ast.filter.Not( + ast.filter.Or( + ast.filter.Is('http://example.com/me/entity#1234'), + ast.filter.Is('http://example.com/me/entity#4321')), + )) + + # for sake of completeness: Has + self.assertEqual(resolver(schema.node(ns.bsfs.Entity), + ast.filter.Has(ns.bse.comment)), + ast.filter.Has(ns.bse.comment)) + # route errors + self.assertRaises(errors.BackendError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Predicate(ns.bse.comment)) + self.assertRaises(errors.BackendError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ast.filter.PredicateExpression(), ast.filter.Equals('foo'))) + self.assertRaises(errors.UnreachableError, resolver._one_of, ast.filter.OneOf(ast.filter.Predicate(ns.bsfs.Predicate))) + + # check schema consistency + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Is(invalid)) + # check immediate type compatibility + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Is(ents)) + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Entity), + ast.filter.Is(tags)) + # check type compatibility through branches + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ns.bse.comment, ast.filter.Is(tags))) + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ns.bse.invalid, ast.filter.Is(tags))) + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ast.filter.OneOf(ns.bse.comment, ns.bse.tag), ast.filter.Is(tags))) + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ast.filter.OneOf(ns.bse.comment, ns.bse.filesize), ast.filter.Is(tags))) + self.assertRaises(errors.ConsistencyError, resolver, schema.node(ns.bsfs.Tag), + ast.filter.Any(ast.filter.Predicate(ns.bse.tag, reverse=True), ast.filter.Is(tags))) + + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## |