diff options
Diffstat (limited to 'test/graph/test_graph.py')
-rw-r--r-- | test/graph/test_graph.py | 216 |
1 files changed, 146 insertions, 70 deletions
diff --git a/test/graph/test_graph.py b/test/graph/test_graph.py index 5db1fd2..167168d 100644 --- a/test/graph/test_graph.py +++ b/test/graph/test_graph.py @@ -1,14 +1,12 @@ -""" -Part of the bsfs test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # imports +from functools import reduce +import operator import unittest # bsie imports from bsfs import schema +from bsfs.graph.ac import NullAC from bsfs.graph.nodes import Nodes from bsfs.namespace import ns from bsfs.query import ast @@ -21,96 +19,95 @@ from bsfs.graph.graph import Graph ## code ## +ns.bse = ns.bsfs.Entity() + class TestGraph(unittest.TestCase): def setUp(self): - self.user = URI('http://example.com/me') self.backend = SparqlStore.Open() self.backend.schema = schema.from_string(''' prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> - prefix bsfs: <http://bsfs.ai/schema/> + prefix bsfs: <https://schema.bsfs.io/core/> bsfs:Entity rdfs:subClassOf bsfs:Node . ''') + self.user = URI('http://example.com/me') + self.ac = NullAC(self.backend, self.user) def test_str(self): - self.assertEqual(str(Graph(self.backend, self.user)), - 'Graph(SparqlStore(uri=None), http://example.com/me)') - self.assertEqual(repr(Graph(self.backend, self.user)), - 'Graph(backend=SparqlStore(uri=None), user=http://example.com/me)') + self.assertEqual(str(Graph(self.backend, self.ac)), + 'Graph(SparqlStore(uri=None))') + self.assertEqual(repr(Graph(self.backend, self.ac)), + 'Graph(SparqlStore(uri=None), NullAC(http://example.com/me))') # str respects backend class Foo(SparqlStore): pass - self.assertEqual(str(Graph(Foo.Open(), self.user)), - 'Graph(Foo(uri=None), http://example.com/me)') - self.assertEqual(repr(Graph(Foo.Open(), self.user)), - 'Graph(backend=Foo(uri=None), user=http://example.com/me)') + self.assertEqual(str(Graph(Foo.Open(), self.ac)), + 'Graph(Foo(uri=None))') + self.assertEqual(repr(Graph(Foo.Open(), self.ac)), + 'Graph(Foo(uri=None), NullAC(http://example.com/me))') # str respect user - self.assertEqual(str(Graph(self.backend, URI('http://example.com/you'))), - 'Graph(SparqlStore(uri=None), http://example.com/you)') - self.assertEqual(repr(Graph(self.backend, URI('http://example.com/you'))), - 'Graph(backend=SparqlStore(uri=None), user=http://example.com/you)') + self.assertEqual(str(Graph(self.backend, NullAC(self.backend, URI('http://example.com/you')))), + 'Graph(SparqlStore(uri=None))') + self.assertEqual(repr(Graph(self.backend, NullAC(self.backend, URI('http://example.com/you')))), + 'Graph(SparqlStore(uri=None), NullAC(http://example.com/you))') # str respects type class Bar(Graph): pass - self.assertEqual(str(Bar(self.backend, self.user)), - 'Bar(SparqlStore(uri=None), http://example.com/me)') - self.assertEqual(repr(Bar(self.backend, self.user)), - 'Bar(backend=SparqlStore(uri=None), user=http://example.com/me)') + self.assertEqual(str(Bar(self.backend, self.ac)), + 'Bar(SparqlStore(uri=None))') + self.assertEqual(repr(Bar(self.backend, self.ac)), + 'Bar(SparqlStore(uri=None), NullAC(http://example.com/me))') def test_equality(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # instance is equal to itself self.assertEqual(graph, graph) self.assertEqual(hash(graph), hash(graph)) # instance is equal to a clone - self.assertEqual(graph, Graph(self.backend, self.user)) - self.assertEqual(hash(graph), hash(Graph(self.backend, self.user))) + self.assertEqual(graph, Graph(self.backend, self.ac)) + self.assertEqual(hash(graph), hash(Graph(self.backend, self.ac))) # equality respects backend - self.assertNotEqual(graph, Graph(SparqlStore.Open(), self.user)) - self.assertNotEqual(hash(graph), hash(Graph(SparqlStore.Open(), self.user))) + self.assertNotEqual(graph, Graph(SparqlStore.Open(), self.ac)) + self.assertNotEqual(hash(graph), hash(Graph(SparqlStore.Open(), self.ac))) # equality respects user self.assertNotEqual(graph, Graph(self.backend, URI('http://example.com/you'))) self.assertNotEqual(hash(graph), hash(Graph(self.backend, URI('http://example.com/you')))) def test_essentials(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # schema self.assertEqual(graph.schema, self.backend.schema) self.assertRaises(AttributeError, setattr, graph, 'schema', None) def test_node(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) guid = URI('http://example.com/me/entity#1234') # returns a Nodes instance self.assertEqual( graph.node(ns.bsfs.Entity, guid), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), {guid})) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), {guid})) # node_type must be in the schema self.assertRaises(KeyError, graph.node, ns.bsfs.Invalid, guid) def test_nodes(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) guids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')} # returns a Nodes instance self.assertEqual( graph.nodes(ns.bsfs.Entity, guids), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), guids)) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), guids)) # node_type must be in the schema self.assertRaises(KeyError, graph.nodes, ns.bsfs.Invalid, guids) - def test_all(self): - graph = Graph(self.backend, self.user) - # resulting nodes can be empty - self.assertEqual(graph.all(ns.bsfs.Entity), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), set())) - # resulting nodes contains all nodes of the respective type - guids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')} - self.backend.create(graph.schema.node(ns.bsfs.Entity), guids) - self.assertEqual(graph.all(ns.bsfs.Entity), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), guids)) + def test_empty(self): + graph = Graph(self.backend, self.ac) + # returns a Nodes instance + self.assertEqual( + graph.empty(ns.bsfs.Entity), + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), set())) # node_type must be in the schema - self.assertRaises(KeyError, graph.all, ns.bsfs.Invalid) + self.assertRaises(KeyError, graph.empty, ns.bsfs.Invalid) def test_migrate(self): # setup - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # argument must be a schema class Foo(): pass @@ -134,12 +131,13 @@ class TestGraph(unittest.TestCase): target_1 = 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#> + prefix bsfs: <https://schema.bsfs.io/core/> + prefix bse: <https://schema.bsfs.io/core/Entity#> + prefix bsl: <https://schema.bsfs.io/core/Literal/> bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsl:Number . bse:filename rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Entity ; @@ -159,13 +157,14 @@ class TestGraph(unittest.TestCase): self.assertEqual(graph.schema, target_1 + 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 bsm: <http://bsfs.ai/schema/Meta#> - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . - bsm:t_created rdfs:subClassOf bsfs:Predicate ; + prefix bsfs: <https://schema.bsfs.io/core/> + prefix bsn: <https://schema.bsfs.io/core/Node#> + prefix bsl: <https://schema.bsfs.io/core/Literal/> + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:float rdfs:subClassOf bsl:Number . + bsn:t_created rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; - rdfs:range xsd:integer ; + rdfs:range xsd:float ; bsfs:unique "true"^^xsd:boolean . ''')) @@ -173,12 +172,13 @@ class TestGraph(unittest.TestCase): target_2 = 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#> + prefix bsfs: <http://schema.bsfs.io/core/> + prefix bse: <http://schema.bsfs.io/core/Node/Entity#> + prefix bsl: <https://schema.bsfs.io/core/Literal/> bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsl:Number . bse:filename rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Entity ; @@ -200,24 +200,25 @@ class TestGraph(unittest.TestCase): self.assertEqual(graph.schema, target_2 + 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 bsm: <http://bsfs.ai/schema/Meta#> - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . - bsm:t_created rdfs:subClassOf bsfs:Predicate ; + prefix bsfs: <https://schema.bsfs.io/core/> + prefix bsn: <https://schema.bsfs.io/core/Node#> + prefix bsl: <https://schema.bsfs.io/core/Literal/> + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:float rdfs:subClassOf bsl:Number . + bsn:t_created rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; - rdfs:range xsd:integer ; + rdfs:range xsd:float ; bsfs:unique "true"^^xsd:boolean . ''')) def test_get(self): # setup - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) graph.migrate(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#> + prefix bsfs: <https://schema.bsfs.io/core/> + prefix bse: <https://schema.bsfs.io/core/Entity#> bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Tag rdfs:subClassOf bsfs:Node . @@ -246,10 +247,10 @@ class TestGraph(unittest.TestCase): graph.node(ns.bsfs.Tag, URI('http://example.com/tag#1234')).set(ns.bse.comment, 'foo') graph.node(ns.bsfs.Tag, URI('http://example.com/tag#4321')).set(ns.bse.comment, 'bar') - # get exception for invalid query + # invalid query raises exception self.assertRaises(errors.ConsistencyError, graph.get, ns.bsfs.Entity, ast.filter.Any(ns.bse.tag, ast.filter.Equals('hello world'))) - # query returns nodes + # get returns nodes self.assertEqual(graph.get(ns.bsfs.Entity, ast.filter.Any(ns.bse.tag, ast.filter.Is(tags))), ents) self.assertEqual(graph.get(ns.bsfs.Entity, ast.filter.Any(ns.bse.comment, ast.filter.StartsWith('foo'))), graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234'))) @@ -260,6 +261,81 @@ class TestGraph(unittest.TestCase): ast.filter.Any(ns.bse.tag, ast.filter.All(ns.bse.comment, ast.filter.Equals('bar'))))), ents) + # query can be None + self.assertEqual(graph.get(ns.bsfs.Entity, None), ents) + + def test_sorted(self): + # setup + graph = Graph(self.backend, self.ac) + graph.migrate(schema.from_string(''' + prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> + prefix xsd: <http://www.w3.org/2001/XMLSchema#> + prefix bsfs: <https://schema.bsfs.io/core/> + prefix bse: <https://schema.bsfs.io/core/Entity#> + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Tag rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:tag rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Tag ; + bsfs:unique "false"^^xsd:boolean . + + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + + ''')) + # add some instances + ents = [ + # default is alphabetical order + graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234')), + graph.node(ns.bsfs.Entity, URI('http://example.com/entity#4321')), + ] + tags = graph.nodes(ns.bsfs.Tag, {URI('http://example.com/tag#1234'), URI('http://example.com/tag#4321')}) + # add some node links + reduce(operator.add, ents).set(ns.bse.tag, tags) + # add some literals + graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234')).set(ns.bse.comment, 'hello world') + graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234')).set(ns.bse.comment, 'foo') + graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234')).set(ns.bse.comment, 'foobar') + graph.node(ns.bsfs.Tag, URI('http://example.com/tag#1234')).set(ns.bse.comment, 'foo') + graph.node(ns.bsfs.Tag, URI('http://example.com/tag#4321')).set(ns.bse.comment, 'bar') + + # invalid query raises exception + self.assertRaises(errors.ConsistencyError, list, graph.sorted(ns.bsfs.Entity, ast.filter.Any(ns.bse.tag, ast.filter.Equals('hello world')))) + + # get returns nodes + self.assertListEqual(list(graph.sorted(ns.bsfs.Entity, ast.filter.Any(ns.bse.tag, ast.filter.Is(tags)))), ents) + self.assertListEqual(list(graph.sorted(ns.bsfs.Entity, ast.filter.Any(ns.bse.comment, ast.filter.StartsWith('foo')))), + [graph.node(ns.bsfs.Entity, URI('http://example.com/entity#1234'))]) + self.assertListEqual(list(graph.sorted(ns.bsfs.Node, ast.filter.Any(ns.bse.comment, ast.filter.StartsWith('foo')))), [ + graph.node(ns.bsfs.Node, URI('http://example.com/entity#1234')), + graph.node(ns.bsfs.Node, URI('http://example.com/tag#1234')), + ]) + self.assertListEqual(list(graph.sorted(ns.bsfs.Entity, ast.filter.Or( + ast.filter.Any(ns.bse.comment, ast.filter.EndsWith('bar')), + ast.filter.Any(ns.bse.tag, ast.filter.All(ns.bse.comment, ast.filter.Equals('bar')))))), + ents) + + # query can be None + self.assertListEqual(list(graph.sorted(ns.bsfs.Entity, None)), ents) + + + def test_all(self): + graph = Graph(self.backend, self.ac) + # resulting nodes can be empty + self.assertEqual(graph.all(ns.bsfs.Entity), + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), set())) + # resulting nodes contains all nodes of the respective type + guids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')} + self.backend.create(graph.schema.node(ns.bsfs.Entity), guids) + self.assertEqual(graph.all(ns.bsfs.Entity), + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), guids)) + # node_type must be in the schema + self.assertRaises(KeyError, graph.all, ns.bsfs.Invalid) |