aboutsummaryrefslogtreecommitdiffstats
path: root/test/graph/test_graph.py
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2022-12-18 14:21:11 +0100
committerMatthias Baumgartner <dev@igsor.net>2022-12-18 14:21:11 +0100
commit91437ba89d35bf482f3d9671bb99ef2fc69f5985 (patch)
treee9bfe27e5a641c040cfa8fe747a7cbb28091079c /test/graph/test_graph.py
parent87e4cd5a4581094f490f79d4f1cf91f51897660f (diff)
parente94368c75468e3e94382b12705e55d396249eaca (diff)
downloadbsfs-91437ba89d35bf482f3d9671bb99ef2fc69f5985.tar.gz
bsfs-91437ba89d35bf482f3d9671bb99ef2fc69f5985.tar.bz2
bsfs-91437ba89d35bf482f3d9671bb99ef2fc69f5985.zip
Merge branch 'develop' into main
Diffstat (limited to 'test/graph/test_graph.py')
-rw-r--r--test/graph/test_graph.py201
1 files changed, 201 insertions, 0 deletions
diff --git a/test/graph/test_graph.py b/test/graph/test_graph.py
new file mode 100644
index 0000000..33cf6aa
--- /dev/null
+++ b/test/graph/test_graph.py
@@ -0,0 +1,201 @@
+"""
+
+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
+from bsfs.namespace import ns
+from bsfs.triple_store import SparqlStore
+from bsfs.utils import URI, errors
+from bsfs.graph.nodes import Nodes
+
+# objects to test
+from bsfs.graph.graph import Graph
+
+
+## code ##
+
+class TestGraph(unittest.TestCase):
+ def setUp(self):
+ self.user = URI('http://example.com/me')
+ self.backend = SparqlStore.Open()
+ self.backend.schema = schema.Schema.from_string('''
+ prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+ prefix bsfs: <http://bsfs.ai/schema/>
+ bsfs:Entity rdfs:subClassOf bsfs:Node .
+ ''')
+
+ 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)')
+ # 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)')
+ # 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)')
+ # 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)')
+
+ def test_equality(self):
+ graph = Graph(self.backend, self.user)
+ # 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)))
+ # equality respects backend
+ self.assertNotEqual(graph, Graph(SparqlStore.Open(), self.user))
+ self.assertNotEqual(hash(graph), hash(Graph(SparqlStore.Open(), self.user)))
+ # 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)
+ # 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)
+ 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}))
+ # 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)
+ 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))
+ # node_type must be in the schema
+ self.assertRaises(KeyError, graph.nodes, ns.bsfs.Invalid, guids)
+
+ def test_migrate(self):
+ # setup
+ graph = Graph(self.backend, self.user)
+
+ # argument must be a schema
+ class Foo(): pass
+ self.assertRaises(TypeError, graph.migrate, 'hello world')
+ self.assertRaises(TypeError, graph.migrate, 1234)
+ self.assertRaises(TypeError, graph.migrate, Foo())
+
+ # cannot append inconsistent schema
+ self.assertRaises(errors.ConsistencyError, graph.migrate, schema.Schema({}, {
+ schema.Node(ns.bsfs.Entity,
+ schema.Node(ns.bsfs.Intermediate,
+ schema.Node(ns.bsfs.Node, None)))}), append=True)
+
+ # cannot migrate to inconsistent schema
+ self.assertRaises(errors.ConsistencyError, graph.migrate, schema.Schema({}, {
+ schema.Node(ns.bsfs.Entity,
+ schema.Node(ns.bsfs.Intermediate,
+ schema.Node(ns.bsfs.Node, None)))}), append=False)
+
+ # can migrate to compatible schema
+ target_1 = 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 .
+ xsd:string rdfs:subClassOf bsfs:Literal .
+ xsd:integer rdfs:subClassOf bsfs:Literal .
+
+ bse:filename 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 .
+
+ ''')
+ graph.migrate(target_1)
+ # new schema is applied
+ self.assertLess(target_1, graph.schema)
+ # graph appends its predicates
+ self.assertEqual(graph.schema, target_1 + 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 bsm: <http://bsfs.ai/schema/Meta#>
+ xsd:integer rdfs:subClassOf bsfs:Literal .
+ bsm:t_created rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Node ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ '''))
+
+ # can overwrite the current schema
+ target_2 = 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 .
+ xsd:string rdfs:subClassOf bsfs:Literal .
+ xsd:integer rdfs:subClassOf bsfs:Literal .
+
+ bse:filename rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range xsd:string ;
+ bsfs:unique "false"^^xsd:boolean .
+
+ bse:author rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range xsd:string ;
+ bsfs:unique "true"^^xsd:boolean .
+
+ ''')
+ graph.migrate(target_2, append=False)
+ # append overwrites existing predicates
+ self.assertFalse(target_1 <= graph.schema)
+ # new schema is applied
+ self.assertLess(target_2, graph.schema)
+ # graph appends its predicates
+ self.assertEqual(graph.schema, target_2 + 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 bsm: <http://bsfs.ai/schema/Meta#>
+ xsd:integer rdfs:subClassOf bsfs:Literal .
+ bsm:t_created rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Node ;
+ rdfs:range xsd:integer ;
+ bsfs:unique "true"^^xsd:boolean .
+ '''))
+
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##