diff options
author | Matthias Baumgartner <dev@igsor.net> | 2023-01-20 18:01:17 +0100 |
---|---|---|
committer | Matthias Baumgartner <dev@igsor.net> | 2023-01-20 18:01:17 +0100 |
commit | e2f08efc0d8a3c875994bdb69623c30cce5079d9 (patch) | |
tree | 0870ac597a55431e63a20e05bb11cf913a5f3e3d /test | |
parent | a4789394e40aaa3152ad6009955709a6c7d277c2 (diff) | |
download | bsfs-e2f08efc0d8a3c875994bdb69623c30cce5079d9.tar.gz bsfs-e2f08efc0d8a3c875994bdb69623c30cce5079d9.tar.bz2 bsfs-e2f08efc0d8a3c875994bdb69623c30cce5079d9.zip |
fetch AST validation
Diffstat (limited to 'test')
-rw-r--r-- | test/query/test_validator.py | 215 |
1 files changed, 214 insertions, 1 deletions
diff --git a/test/query/test_validator.py b/test/query/test_validator.py index dc9d913..fec3d23 100644 --- a/test/query/test_validator.py +++ b/test/query/test_validator.py @@ -14,7 +14,7 @@ from bsfs.query import ast from bsfs.utils import errors # objects to test -from bsfs.query.validator import Filter +from bsfs.query.validator import Filter, Fetch ## code ## @@ -286,6 +286,219 @@ class TestFilter(unittest.TestCase): self.assertIsNone(self.validate._distance(self.schema.literal(ns.bsfs.Colors), ast.filter.Distance([1,2,3,4,5], 1, False))) +class TestFetch(unittest.TestCase): + def setUp(self): + self.schema = _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 . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range xsd:string . + + bse:tag rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Tag . + + bse:label rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Tag ; + rdfs:range xsd:string . + + ''') + self.validate = Fetch(self.schema) + + def test_call(self): + # call accepts correct expressions + self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.Value(ns.bse.label, 'value')))) + self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this')))) + self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity), + ast.fetch.This('this'))) + self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.This('this'), ast.fetch.Node(ns.bse.tag, 'node'), ast.fetch.Value(ns.bse.filename, 'value')))) + # type must be a Node + self.assertRaises(TypeError, self.validate, 1234, ast.fetch.This('this')) + self.assertRaises(TypeError, self.validate, 'foobar', ast.fetch.This('this')) + self.assertRaises(TypeError, self.validate, self.schema.literal(ns.bsfs.Literal), ast.fetch.This('this')) + # type must be in the schema + self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch.FetchExpression()) + # expression must be a fetch expression + self.assertRaises(TypeError, self.validate, self.schema.node(ns.bsfs.Entity), 1234) + self.assertRaises(TypeError, self.validate, self.schema.node(ns.bsfs.Entity), 'hello') + self.assertRaises(TypeError, self.validate, self.schema.node(ns.bsfs.Entity), ast.filter.FilterExpression()) + # expression must be valid + self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.Node(ns.bse.label, 'node'))) + self.assertRaises(errors.ConsistencyError, self.validate, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.tag, 'value')) + + def test_routing(self): + # Node passes _branch, _named, and _node checks + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Node), + ast.fetch.Node(ns.bse.tag, 'node')) # fails in _branch + self.assertRaises(errors.BackendError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.tag, '')) # fails in _named + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.label, 'node')) # fails in _node + # Value passes _branch, _named, and _value checks + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Node), + ast.fetch.Value(ns.bse.label, 'value')) # fails in _branch + self.assertRaises(errors.BackendError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, '')) # fails in _named + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.tag, 'value')) # fails in _value + # Fetch passes _branch and _fetch checks + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this'))) # fails in _branch + self.assertRaises(errors.ConsistencyError, self.validate._parse_fetch_expression, self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.filename, ast.fetch.This('this'))) # fails in _fetch + # invalid expressions cannot be parsed + type_ = self.schema.node(ns.bsfs.Node) + self.assertRaises(errors.BackendError, self.validate._parse_fetch_expression, type_, + ast.filter.FilterExpression()) + self.assertRaises(errors.BackendError, self.validate._parse_fetch_expression, type_, + 1234) + self.assertRaises(errors.BackendError, self.validate._parse_fetch_expression, type_, + 'hello world') + + def test_all(self): + # all accepts correct expressions + self.assertIsNone(self.validate._all(self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.Value(ns.bse.filename, 'value'), ast.fetch.Node(ns.bse.tag, 'node')))) + # child expressions must be valid + self.assertRaises(errors.ConsistencyError, self.validate._all, self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.Value(ns.bse.tag, 'value'))) + self.assertRaises(errors.ConsistencyError, self.validate._all, self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.Value(ns.bse.filename, 'value'), ast.fetch.Node(ns.bse.filename, 'node'))) + self.assertRaises(errors.ConsistencyError, self.validate._all, self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.Value(ns.bse.tag, 'value'), ast.fetch.Node(ns.bse.tag, 'node'))) + self.assertRaises(errors.ConsistencyError, self.validate._all, self.schema.node(ns.bsfs.Entity), + ast.fetch.All(ast.fetch.Value(ns.bse.tag, 'value'), ast.fetch.Node(ns.bse.filename, 'node'))) + + def test_branch(self): + # branch accepts correct expressions + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch._Branch(ns.bse.filename))) + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this')))) + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, 'value'))) + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.tag, 'node'))) + # type must be a node + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.literal(ns.bsfs.Literal), + ast.fetch._Branch(ns.bse.filename)) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.literal(ns.bsfs.Literal), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this'))) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.literal(ns.bsfs.Literal), + ast.fetch.Value(ns.bse.filename, 'value')) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.literal(ns.bsfs.Literal), + ast.fetch.Node(ns.bse.tag, 'node')) + # type must be in the schema + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch._Branch(ns.bse.filename)) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this'))) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch.Value(ns.bse.filename, 'value')) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch.Node(ns.bse.tag, 'node')) + # predicate must be in the schema + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch._Branch(ns.bse.invalid)) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.invalid, ast.fetch.This('this'))) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.invalid, 'value')) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.invalid, 'node')) + # predicate's domain must be related to the type + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch._Branch(ns.bse.label)) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Fetch(ns.bse.label, ast.fetch.This('this'))) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.label, 'node')) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.label, 'value')) + # predicate's domain cannot be a supertype + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node), + ast.fetch._Branch(ns.bse.tag)) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.This('this'))) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node), + ast.fetch.Node(ns.bse.tag, 'node')) + self.assertRaises(errors.ConsistencyError, self.validate._branch, self.schema.node(ns.bsfs.Node), + ast.fetch.Value(ns.bse.tag, 'value')) + # predicate's domain can be a subtype + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch._Branch(ns.bse.filename))) + self.assertIsNone(self.validate._branch(self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, 'value'))) + + def test_fetch(self): + # fetch accepts correct expressions + self.assertIsNone(self.validate._fetch(self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.Value(ns.bse.label, 'value')))) + # range must be a node + self.assertRaises(errors.ConsistencyError, self.validate._fetch, self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.filename, ast.fetch.This('this'))) + # child expression must be valid + self.assertRaises(errors.ConsistencyError, self.validate._fetch, self.schema.node(ns.bsfs.Node), + ast.fetch.Fetch(ns.bse.tag, ast.fetch.Node(ns.bse.label, 'node'))) + + def test_named(self): + # named accepts correct expressions + self.assertIsNone(self.validate._named(self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.tag, 'node'))) + self.assertIsNone(self.validate._named(self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, 'value'))) + # name must be non-empty + self.assertRaises(errors.BackendError, self.validate._named, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.tag, '')) + self.assertRaises(errors.BackendError, self.validate._named, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, '')) + + def test_node(self): + # node accepts correct expressions + self.assertIsNone(self.validate._node(self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.tag, 'node'))) + # range must be a node + self.assertRaises(errors.ConsistencyError, self.validate._node, self.schema.node(ns.bsfs.Entity), + ast.fetch.Node(ns.bse.filename, 'node')) + + def test_value(self): + # value accepts correct expressions + self.assertIsNone(self.validate._value(self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.filename, 'value'))) + # range must be a literal + self.assertRaises(errors.ConsistencyError, self.validate._value, self.schema.node(ns.bsfs.Entity), + ast.fetch.Value(ns.bse.tag, 'value')) + + def test_this(self): + # this accepts correct expressions + self.assertIsNone(self.validate._this(self.schema.node(ns.bsfs.Entity), ast.fetch.This('this'))) + # type must be a node + self.assertRaises(errors.ConsistencyError, self.validate._this, self.schema.literal(ns.bsfs.Literal), + ast.fetch.This('this')) + self.assertRaises(errors.ConsistencyError, self.validate._this, self.schema.predicate(ns.bsfs.Predicate), + ast.fetch.This('this')) + # type must be in the schema + self.assertRaises(errors.ConsistencyError, self.validate._this, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), + ast.fetch.This('this')) + # name must be non-empty + self.assertRaises(errors.BackendError, self.validate._this, self.schema.node(ns.bsfs.Entity), ast.fetch.This('')) + + ## main ## if __name__ == '__main__': |