diff options
| author | Graham Higgins <gjh@bel-epa.com> | 2022-03-24 13:59:46 +0000 |
|---|---|---|
| committer | Graham Higgins <gjh@bel-epa.com> | 2022-03-24 13:59:46 +0000 |
| commit | 3efcecba2756fa09c2165383b17b3cb9e5183659 (patch) | |
| tree | 95cfc237dd218bdf8b8f3749b30af4218d27ee58 /test/test_store | |
| parent | 06f03a905609b37a2e8f93abe8c7046e0c53afa7 (diff) | |
| download | rdflib-3efcecba2756fa09c2165383b17b3cb9e5183659.tar.gz | |
Migrate some tests to pytest
Preparatory work for dataset-rework, eases review
Diffstat (limited to 'test/test_store')
| -rw-r--r-- | test/test_store/test_store_auditable.py | 842 | ||||
| -rw-r--r-- | test/test_store/test_store_berkeleydb.py | 241 | ||||
| -rw-r--r-- | test/test_store/test_store_memorystore.py | 80 | ||||
| -rw-r--r-- | test/test_store/test_store_sparqlupdatestore.py | 624 | ||||
| -rw-r--r-- | test/test_store/test_store_triple_store.py | 49 |
5 files changed, 954 insertions, 882 deletions
diff --git a/test/test_store/test_store_auditable.py b/test/test_store/test_store_auditable.py index f5c1188c..803954fd 100644 --- a/test/test_store/test_store_auditable.py +++ b/test/test_store/test_store_auditable.py @@ -1,386 +1,472 @@ # -*- coding=utf8 -*- -import unittest +import shutil +import tempfile -from rdflib import Graph, Namespace +import pytest + +from rdflib import Graph, Namespace, plugin from rdflib.plugins.stores.auditable import AuditableStore +from rdflib.store import VALID_STORE EX = Namespace("http://example.org/") -class BaseTestAuditableStore(unittest.TestCase): - def assert_graph_equal(self, g1, g2): +def get_plugin_stores(): + pluginstores = [] + + for s in plugin.plugins(None, plugin.Store): + if s.name in ( + "default", + "Memory", + "Auditable", + "Concurrent", + "SimpleMemory", + "SPARQLStore", + "SPARQLUpdateStore", + ): + continue # excluded from these tests + try: - return self.assertSetEqual(set(g1), set(g2)) - except AttributeError: - # python2.6 does not have assertSetEqual - assert set(g1) == set(g2) - - -class TestAuditableStore(BaseTestAuditableStore): - def setUp(self): - self.g = Graph() - self.g.add((EX.s0, EX.p0, EX.o0)) - self.g.add((EX.s0, EX.p0, EX.o0bis)) - - self.t = Graph(AuditableStore(self.g.store), self.g.identifier) - - def test_add_commit(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - (EX.s1, EX.p1, EX.o1), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - (EX.s1, EX.p1, EX.o1), - ], - ) - - def test_remove_commit(self): - self.t.remove((EX.s0, EX.p0, EX.o0)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0bis), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_multiple_remove_commit(self): - self.t.remove((EX.s0, EX.p0, None)) - self.assert_graph_equal(self.t, []) - self.t.commit() - self.assert_graph_equal(self.g, []) - - def test_noop_add_commit(self): - self.t.add((EX.s0, EX.p0, EX.o0)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_noop_remove_commit(self): - self.t.add((EX.s0, EX.p0, EX.o0)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_add_remove_commit(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.t.remove((EX.s1, EX.p1, EX.o1)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_remove_add_commit(self): - self.t.remove((EX.s1, EX.p1, EX.o1)) - self.t.add((EX.s1, EX.p1, EX.o1)) - self.assert_graph_equal( - self.t, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - (EX.s1, EX.p1, EX.o1), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - (EX.s1, EX.p1, EX.o1), - ], - ) - - def test_add_rollback(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_remove_rollback(self): - self.t.remove((EX.s0, EX.p0, EX.o0)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_multiple_remove_rollback(self): - self.t.remove((EX.s0, EX.p0, None)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_noop_add_rollback(self): - self.t.add((EX.s0, EX.p0, EX.o0)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_noop_remove_rollback(self): - self.t.add((EX.s0, EX.p0, EX.o0)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_add_remove_rollback(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.t.remove((EX.s1, EX.p1, EX.o1)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_remove_add_rollback(self): - self.t.remove((EX.s1, EX.p1, EX.o1)) - self.t.add((EX.s1, EX.p1, EX.o1)) - self.t.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - -class TestAuditableStoreEmptyGraph(BaseTestAuditableStore): - def setUp(self): - self.g = Graph() - self.t = Graph(AuditableStore(self.g.store), self.g.identifier) - - def test_add_commit(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.assert_graph_equal( - self.t, - [ - (EX.s1, EX.p1, EX.o1), - ], - ) - self.t.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s1, EX.p1, EX.o1), - ], - ) - - def test_add_rollback(self): - self.t.add((EX.s1, EX.p1, EX.o1)) - self.t.rollback() - self.assert_graph_equal(self.g, []) - - -class TestAuditableStoreConccurent(BaseTestAuditableStore): - def setUp(self): - self.g = Graph() - self.g.add((EX.s0, EX.p0, EX.o0)) - self.g.add((EX.s0, EX.p0, EX.o0bis)) - self.t1 = Graph(AuditableStore(self.g.store), self.g.identifier) - self.t2 = Graph(AuditableStore(self.g.store), self.g.identifier) - self.t1.add((EX.s1, EX.p1, EX.o1)) - self.t2.add((EX.s2, EX.p2, EX.o2)) - self.t1.remove((EX.s0, EX.p0, EX.o0)) - self.t2.remove((EX.s0, EX.p0, EX.o0bis)) - - def test_commit_commit(self): - self.t1.commit() - self.t2.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s1, EX.p1, EX.o1), - (EX.s2, EX.p2, EX.o2), - ], - ) - - def test_commit_rollback(self): - self.t1.commit() - self.t2.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s1, EX.p1, EX.o1), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_rollback_commit(self): - self.t1.rollback() - self.t2.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s2, EX.p2, EX.o2), - ], - ) - - def test_rollback_rollback(self): - self.t1.rollback() - self.t2.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - -class TestAuditableStoreEmbeded(BaseTestAuditableStore): - def setUp(self): - self.g = Graph() - self.g.add((EX.s0, EX.p0, EX.o0)) - self.g.add((EX.s0, EX.p0, EX.o0bis)) - - self.t1 = Graph(AuditableStore(self.g.store), self.g.identifier) - self.t1.add((EX.s1, EX.p1, EX.o1)) - self.t1.remove((EX.s0, EX.p0, EX.o0bis)) - - self.t2 = Graph(AuditableStore(self.t1.store), self.t1.identifier) - self.t2.add((EX.s2, EX.p2, EX.o2)) - self.t2.remove((EX.s1, EX.p1, EX.o1)) - - def test_commit_commit(self): - self.assert_graph_equal( - self.t2, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s2, EX.p2, EX.o2), - ], - ) - self.t2.commit() - self.assert_graph_equal( - self.t1, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s2, EX.p2, EX.o2), - ], - ) - self.t1.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s2, EX.p2, EX.o2), - ], - ) - - def test_commit_rollback(self): - self.t2.commit() - self.t1.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) - - def test_rollback_commit(self): - self.t2.rollback() - self.assert_graph_equal( - self.t1, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s1, EX.p1, EX.o1), - ], - ) - self.t1.commit() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s1, EX.p1, EX.o1), - ], - ) - - def test_rollback_rollback(self): - self.t2.rollback() - self.t1.rollback() - self.assert_graph_equal( - self.g, - [ - (EX.s0, EX.p0, EX.o0), - (EX.s0, EX.p0, EX.o0bis), - ], - ) + graph = Graph(store=s.name) + pluginstores.append(s.name) + except ImportError: + pass + return pluginstores + + +@pytest.fixture( + scope="function", + params=get_plugin_stores(), +) +def get_graph(request): + storename = request.param + + g = Graph(store=storename) + + path = tempfile.mktemp() + + try: + shutil.rmtree(path) + except Exception: + pass + + rt = g.open(configuration=path, create=True) + assert rt == VALID_STORE, "The underlying store is corrupt" + + g.add((EX.s0, EX.p0, EX.o0)) + g.add((EX.s0, EX.p0, EX.o0bis)) + + t = Graph(AuditableStore(g.store), g.identifier) + + yield g, t + + g.close() + + g.destroy(configuration=path) + + try: + shutil.rmtree(path) + except Exception: + pass + + +def test_add_commit(get_graph): + g, t = get_graph + t.add((EX.s1, EX.p1, EX.o1)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + (EX.s1, EX.p1, EX.o1), + ] + ) + + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + (EX.s1, EX.p1, EX.o1), + ] + ) + + +def test_remove_commit(get_graph): + g, t = get_graph + t.remove((EX.s0, EX.p0, EX.o0)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0bis), + ] + ) + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_multiple_remove_commit(get_graph): + g, t = get_graph + t.remove((EX.s0, EX.p0, None)) + assert set(t) == set([]) + t.commit() + assert set(g) == set([]) + + +def test_noop_add_commit(get_graph): + g, t = get_graph + t.add((EX.s0, EX.p0, EX.o0)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_noop_remove_commit(get_graph): + g, t = get_graph + t.add((EX.s0, EX.p0, EX.o0)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_add_remove_commit(get_graph): + g, t = get_graph + t.add((EX.s1, EX.p1, EX.o1)) + t.remove((EX.s1, EX.p1, EX.o1)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_remove_add_commit(get_graph): + g, t = get_graph + t.remove((EX.s1, EX.p1, EX.o1)) + t.add((EX.s1, EX.p1, EX.o1)) + assert set(t) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + (EX.s1, EX.p1, EX.o1), + ] + ) + t.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + (EX.s1, EX.p1, EX.o1), + ] + ) + + +def test_add_rollback(get_graph): + g, t = get_graph + t.add((EX.s1, EX.p1, EX.o1)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_remove_rollback(get_graph): + g, t = get_graph + t.remove((EX.s0, EX.p0, EX.o0)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_multiple_remove_rollback(get_graph): + g, t = get_graph + t.remove((EX.s0, EX.p0, None)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_noop_add_rollback(get_graph): + g, t = get_graph + t.add((EX.s0, EX.p0, EX.o0)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_noop_remove_rollback(get_graph): + g, t = get_graph + t.add((EX.s0, EX.p0, EX.o0)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_add_remove_rollback(get_graph): + g, t = get_graph + t.add((EX.s1, EX.p1, EX.o1)) + t.remove((EX.s1, EX.p1, EX.o1)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_remove_add_rollback(get_graph): + g, t = get_graph + t.remove((EX.s1, EX.p1, EX.o1)) + t.add((EX.s1, EX.p1, EX.o1)) + t.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +@pytest.fixture( + scope="function", + params=get_plugin_stores(), +) +def get_empty_graph(request): + storename = request.param + + path = tempfile.mktemp() + + try: + shutil.rmtree(path) + except Exception: + pass + + g = Graph(store=storename) + rt = g.open(configuration=path, create=True) + assert rt == VALID_STORE, "The underlying store is corrupt" + + t = Graph(AuditableStore(g.store), g.identifier) + + yield g, t + g.close() + g.destroy(configuration=path) + + +def test_add_commit_empty(get_empty_graph): + g, t = get_empty_graph + t.add((EX.s1, EX.p1, EX.o1)) + assert set(t) == set( + [ + (EX.s1, EX.p1, EX.o1), + ] + ) + t.commit() + assert set(g) == set( + [ + (EX.s1, EX.p1, EX.o1), + ] + ) + + +def test_add_rollback_empty(get_empty_graph): + g, t = get_empty_graph + t.add((EX.s1, EX.p1, EX.o1)) + t.rollback() + assert set(g) == set([]) + + +@pytest.fixture +def get_concurrent_graph(): + g = Graph() + g.add((EX.s0, EX.p0, EX.o0)) + g.add((EX.s0, EX.p0, EX.o0bis)) + t1 = Graph(AuditableStore(g.store), g.identifier) + t2 = Graph(AuditableStore(g.store), g.identifier) + t1.add((EX.s1, EX.p1, EX.o1)) + t2.add((EX.s2, EX.p2, EX.o2)) + t1.remove((EX.s0, EX.p0, EX.o0)) + t2.remove((EX.s0, EX.p0, EX.o0bis)) + + yield g, t1, t2 + + +def test_commit_commit(get_concurrent_graph): + g, t1, t2 = get_concurrent_graph + t1.commit() + t2.commit() + assert set(g) == set( + [ + (EX.s1, EX.p1, EX.o1), + (EX.s2, EX.p2, EX.o2), + ] + ) + + +def test_commit_rollback(get_concurrent_graph): + g, t1, t2 = get_concurrent_graph + t1.commit() + t2.rollback() + assert set(g) == set( + [ + (EX.s1, EX.p1, EX.o1), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_rollback_commit(get_concurrent_graph): + g, t1, t2 = get_concurrent_graph + t1.rollback() + t2.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s2, EX.p2, EX.o2), + ] + ) + + +def test_rollback_rollback(get_concurrent_graph): + g, t1, t2 = get_concurrent_graph + t1.rollback() + t2.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +@pytest.fixture +def get_embedded_graph(): + g = Graph() + g.add((EX.s0, EX.p0, EX.o0)) + g.add((EX.s0, EX.p0, EX.o0bis)) + + t1 = Graph(AuditableStore(g.store), g.identifier) + t1.add((EX.s1, EX.p1, EX.o1)) + t1.remove((EX.s0, EX.p0, EX.o0bis)) + + t2 = Graph(AuditableStore(t1.store), t1.identifier) + t2.add((EX.s2, EX.p2, EX.o2)) + t2.remove((EX.s1, EX.p1, EX.o1)) + + yield g, t1, t2 + + +def test_commit_commit_embedded(get_embedded_graph): + g, t1, t2 = get_embedded_graph + assert set(t2) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s2, EX.p2, EX.o2), + ] + ) + t2.commit() + assert set(t1) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s2, EX.p2, EX.o2), + ] + ) + t1.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s2, EX.p2, EX.o2), + ] + ) + + +def test_commit_rollback_embedded(get_embedded_graph): + g, t1, t2 = get_embedded_graph + t2.commit() + t1.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) + + +def test_rollback_commit_embedded(get_embedded_graph): + g, t1, t2 = get_embedded_graph + t2.rollback() + assert set(t1) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s1, EX.p1, EX.o1), + ] + ) + t1.commit() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s1, EX.p1, EX.o1), + ] + ) + + +def test_rollback_rollback_embedded(get_embedded_graph): + g, t1, t2 = get_embedded_graph + t2.rollback() + t1.rollback() + assert set(g) == set( + [ + (EX.s0, EX.p0, EX.o0), + (EX.s0, EX.p0, EX.o0bis), + ] + ) diff --git a/test/test_store/test_store_berkeleydb.py b/test/test_store/test_store_berkeleydb.py index f96fb9bc..1b307c49 100644 --- a/test/test_store/test_store_berkeleydb.py +++ b/test/test_store/test_store_berkeleydb.py @@ -1,130 +1,147 @@ -import unittest from tempfile import mktemp + +import pytest + from rdflib import ConjunctiveGraph, URIRef -from rdflib.store import VALID_STORE from rdflib.plugins.stores.berkeleydb import has_bsddb +from rdflib.store import VALID_STORE - -class BerkeleyDBTestCase(unittest.TestCase): - def setUp(self): - if not has_bsddb: - self.skipTest("skipping as berkleydb is missing") - self.store_name = "BerkeleyDB" - self.path = mktemp() - self.g = ConjunctiveGraph(store=self.store_name) - self.rt = self.g.open(self.path, create=True) - assert self.rt == VALID_STORE, "The underlying store is corrupt" - assert ( - len(self.g) == 0 - ), "There must be zero triples in the graph just after store (file) creation" - data = """ - PREFIX : <https://example.org/> - - :a :b :c . - :d :e :f . - :d :g :h . - """ - self.g.parse(data=data, format="ttl") - - def tearDown(self): - self.g.close() - - def test_write(self): - assert ( - len(self.g) == 3 - ), "There must be three triples in the graph after the first data chunk parse" - data2 = """ - PREFIX : <https://example.org/> - - :d :i :j . - """ - self.g.parse(data=data2, format="ttl") - assert ( - len(self.g) == 4 - ), "There must be four triples in the graph after the second data chunk parse" - data3 = """ - PREFIX : <https://example.org/> - - :d :i :j . - """ - self.g.parse(data=data3, format="ttl") - assert ( - len(self.g) == 4 - ), "There must still be four triples in the graph after the thrd data chunk parse" - - def test_read(self): - sx = None - for s in self.g.subjects( - predicate=URIRef("https://example.org/e"), - object=URIRef("https://example.org/f"), - ): - sx = s - assert sx == URIRef("https://example.org/d") - - def test_sparql_query(self): - q = """ +pytestmark = pytest.mark.skipif( + not has_bsddb, reason="skipping berkeleydb tests, modile not available" +) + + +@pytest.fixture +def get_graph(): + path = mktemp() + g = ConjunctiveGraph("BerkeleyDB") + rt = g.open(path, create=True) + assert rt == VALID_STORE, "The underlying store is corrupt" + assert ( + len(g) == 0 + ), "There must be zero triples in the graph just after store (file) creation" + data = """ PREFIX : <https://example.org/> - SELECT (COUNT(*) AS ?c) - WHERE { - :d ?p ?o . - }""" + :a :b :c . + :d :e :f . + :d :g :h . + """ + g.parse(data=data, format="ttl") - c = 0 - for row in self.g.query(q): - c = int(row.c) - assert c == 2, "SPARQL COUNT must return 2" + yield path, g - def test_sparql_insert(self): - q = """ - PREFIX : <https://example.org/> + g.close() + g.destroy(path) - INSERT DATA { - :x :y :z . - }""" - self.g.update(q) - assert len(self.g) == 4, "After extra triple insert, length must be 4" +def test_write(get_graph): + path, g = get_graph + assert ( + len(g) == 3 + ), "There must be three triples in the graph after the first data chunk parse" + data2 = """ + PREFIX : <https://example.org/> - def test_multigraph(self): - q = """ + :d :i :j . + """ + g.parse(data=data2, format="ttl") + assert ( + len(g) == 4 + ), "There must be four triples in the graph after the second data chunk parse" + data3 = """ PREFIX : <https://example.org/> - INSERT DATA { - GRAPH :m { - :x :y :z . - } - GRAPH :n { - :x :y :z . - } - }""" + :d :i :j . + """ + g.parse(data=data3, format="ttl") + assert ( + len(g) == 4 + ), "There must still be four triples in the graph after the third data chunk parse" + + +def test_read(get_graph): + path, g = get_graph + sx = None + for s in g.subjects( + predicate=URIRef("https://example.org/e"), + object=URIRef("https://example.org/f"), + ): + sx = s + assert sx == URIRef("https://example.org/d") - self.g.update(q) - q = """ - SELECT (COUNT(?g) AS ?c) +def test_sparql_query(get_graph): + path, g = get_graph + q = """ + PREFIX : <https://example.org/> + + SELECT (COUNT(*) AS ?c) + WHERE { + :d ?p ?o . + }""" + + c = 0 + for row in g.query(q): + c = int(row.c) + assert c == 2, "SPARQL COUNT must return 2" + + +def test_sparql_insert(get_graph): + path, g = get_graph + q = """ + PREFIX : <https://example.org/> + + INSERT DATA { + :x :y :z . + }""" + + g.update(q) + assert len(g) == 4, "After extra triple insert, length must be 4" + + +def test_multigraph(get_graph): + path, g = get_graph + q = """ + PREFIX : <https://example.org/> + + INSERT DATA { + GRAPH :m { + :x :y :z . + } + GRAPH :n { + :x :y :z . + } + }""" + + g.update(q) + + q = """ + SELECT (COUNT(?g) AS ?c) + WHERE { + SELECT DISTINCT ?g WHERE { - SELECT DISTINCT ?g - WHERE { - GRAPH ?g { - ?s ?p ?o - } + GRAPH ?g { + ?s ?p ?o } } - """ - c = 0 - for row in self.g.query(q): - c = int(row.c) - assert c == 3, "SPARQL COUNT must return 3 (default, :m & :n)" - - def test_open_shut(self): - assert len(self.g) == 3, "Initially we must have 3 triples from setUp" - self.g.close() - self.g = None - - # reopen the graph - self.g = ConjunctiveGraph("BerkeleyDB") - self.g.open(self.path, create=False) - assert ( - len(self.g) == 3 - ), "After close and reopen, we should still have the 3 originally added triples" + } + """ + c = 0 + for row in g.query(q): + c = int(row.c) + assert c == 3, "SPARQL COUNT must return 3 (default, :m & :n)" + + +def test_open_shut(get_graph): + path, g = get_graph + assert len(g) == 3, "Initially we must have 3 triples from setUp" + g.close() + g = None + + # reopen the graph + g = ConjunctiveGraph("BerkeleyDB") + g.open(path, create=False) + assert ( + len(g) == 3 + ), "After close and reopen, we should still have the 3 originally added triples" diff --git a/test/test_store/test_store_memorystore.py b/test/test_store/test_store_memorystore.py index 41b60356..905dc58b 100644 --- a/test/test_store/test_store_memorystore.py +++ b/test/test_store/test_store_memorystore.py @@ -1,59 +1,31 @@ -import unittest -import rdflib - -rdflib.plugin.register( - "SimpleMemory", rdflib.store.Store, "rdflib.plugins.stores.memory", "SimpleMemory" -) -rdflib.plugin.register( - "Memory", rdflib.store.Store, "rdflib.plugins.stores.memory", "Memory" -) +import pytest - -class SimpleStoreTestCase(unittest.TestCase): - def test_memory_store(self): - g = rdflib.Graph("SimpleMemory") - subj1 = rdflib.URIRef("http://example.org/foo#bar1") - pred1 = rdflib.URIRef("http://example.org/foo#bar2") - obj1 = rdflib.URIRef("http://example.org/foo#bar3") - triple1 = (subj1, pred1, obj1) - triple2 = ( - subj1, - rdflib.URIRef("http://example.org/foo#bar4"), - rdflib.URIRef("http://example.org/foo#bar5"), - ) - g.add(triple1) - self.assertTrue(len(g) == 1) - g.add(triple2) - self.assertTrue(len(list(g.triples((subj1, None, None)))) == 2) - self.assertTrue(len(list(g.triples((None, pred1, None)))) == 1) - self.assertTrue(len(list(g.triples((None, None, obj1)))) == 1) - g.remove(triple1) - self.assertTrue(len(g) == 1) - g.serialize() +import rdflib -class MemoryStoreTestCase(unittest.TestCase): - def test_memory_store(self): - g = rdflib.Graph("Memory") - subj1 = rdflib.URIRef("http://example.org/foo#bar1") - pred1 = rdflib.URIRef("http://example.org/foo#bar2") - obj1 = rdflib.URIRef("http://example.org/foo#bar3") - triple1 = (subj1, pred1, obj1) - triple2 = ( - subj1, - rdflib.URIRef("http://example.org/foo#bar4"), - rdflib.URIRef("http://example.org/foo#bar5"), - ) - g.add(triple1) - self.assertTrue(len(g) == 1) - g.add(triple2) - self.assertTrue(len(list(g.triples((subj1, None, None)))) == 2) - self.assertTrue(len(list(g.triples((None, pred1, None)))) == 1) - self.assertTrue(len(list(g.triples((None, None, obj1)))) == 1) - g.remove(triple1) - self.assertTrue(len(g) == 1) - g.serialize() +@pytest.fixture(scope="function", params=["SimpleMemory", "Memory"]) +def get_graph(request): + g = rdflib.Graph(request.param) + yield g -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") +def test_memory_store(get_graph): + g = get_graph + subj1 = rdflib.URIRef("http://example.org/foo#bar1") + pred1 = rdflib.URIRef("http://example.org/foo#bar2") + obj1 = rdflib.URIRef("http://example.org/foo#bar3") + triple1 = (subj1, pred1, obj1) + triple2 = ( + subj1, + rdflib.URIRef("http://example.org/foo#bar4"), + rdflib.URIRef("http://example.org/foo#bar5"), + ) + g.add(triple1) + assert len(g) == 1 + g.add(triple2) + assert len(list(g.triples((subj1, None, None)))) == 2 + assert len(list(g.triples((None, pred1, None)))) == 1 + assert len(list(g.triples((None, None, obj1)))) == 1 + g.remove(triple1) + assert len(g) == 1 + assert len(g.serialize()) > 0 diff --git a/test/test_store/test_store_sparqlupdatestore.py b/test/test_store/test_store_sparqlupdatestore.py index 6c942f8e..c29a6ac6 100644 --- a/test/test_store/test_store_sparqlupdatestore.py +++ b/test/test_store/test_store_sparqlupdatestore.py @@ -1,11 +1,13 @@ # -*- coding: utf-8 -*- -import unittest import re - -from rdflib import ConjunctiveGraph, URIRef, Literal, BNode, Graph +from test.data import bob, cheese, hates, likes, michel, pizza, tarek from urllib.request import urlopen +import pytest + +from rdflib import BNode, ConjunctiveGraph, Graph, Literal, URIRef + HOST = "http://localhost:3031" DB = "/db/" @@ -21,342 +23,336 @@ DB = "/db/" # THIS WILL DELETE ALL DATA IN THE /db dataset -michel = URIRef("urn:example:michel") -tarek = URIRef("urn:example:tarek") -bob = URIRef("urn:example:bob") -likes = URIRef("urn:example:likes") -hates = URIRef("urn:example:hates") -pizza = URIRef("urn:example:pizza") -cheese = URIRef("urn:example:cheese") - graphuri = URIRef("urn:example:graph") othergraphuri = URIRef("urn:example:othergraph") try: assert len(urlopen(HOST).read()) > 0 - skip = False except: - skip = True - - -@unittest.skipIf(skip, HOST + " is unavailable.") -class TestSparql11(unittest.TestCase): - def setUp(self): - self.longMessage = True - self.graph = ConjunctiveGraph("SPARQLUpdateStore") + pytest.skip(f"{HOST} is unavailable.", allow_module_level=True) - root = HOST + DB - self.graph.open((root + "sparql", root + "update")) - # clean out the store - for c in self.graph.contexts(): - c.remove((None, None, None)) - assert len(c) == 0 +@pytest.fixture +def get_graph(): + longMessage = True + graph = ConjunctiveGraph("SPARQLUpdateStore") - def tearDown(self): - self.graph.close() + root = HOST + DB + graph.open((root + "sparql", root + "update")) - def testSimpleGraph(self): - g = self.graph.get_context(graphuri) - g.add((tarek, likes, pizza)) - g.add((bob, likes, pizza)) - g.add((bob, likes, cheese)) + # clean out the store + for c in graph.contexts(): + c.remove((None, None, None)) + assert len(c) == 0 - g2 = self.graph.get_context(othergraphuri) - g2.add((michel, likes, pizza)) + yield graph - self.assertEqual(3, len(g), "graph contains 3 triples") - self.assertEqual(1, len(g2), "other graph contains 1 triple") + graph.close() - r = g.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") - self.assertEqual(2, len(list(r)), "two people like pizza") - r = g.triples((None, likes, pizza)) - self.assertEqual(2, len(list(r)), "two people like pizza") +def test_simple_graph(get_graph): + graph = get_graph + g = graph.get_context(graphuri) + g.add((tarek, likes, pizza)) + g.add((bob, likes, pizza)) + g.add((bob, likes, cheese)) - # Test initBindings - r = g.query( - "SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }", initBindings={"s": tarek}, - ) - self.assertEqual(1, len(list(r)), "i was asking only about tarek") - - r = g.triples((tarek, likes, pizza)) - self.assertEqual(1, len(list(r)), "i was asking only about tarek") - - r = g.triples((tarek, likes, cheese)) - self.assertEqual(0, len(list(r)), "tarek doesn't like cheese") - - g2.add((tarek, likes, pizza)) - g.remove((tarek, likes, pizza)) - r = g.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") - self.assertEqual(1, len(list(r)), "only bob likes pizza") - - def testConjunctiveDefault(self): - g = self.graph.get_context(graphuri) - g.add((tarek, likes, pizza)) - g2 = self.graph.get_context(othergraphuri) - g2.add((bob, likes, pizza)) - g.add((tarek, hates, cheese)) - - self.assertEqual(2, len(g), "graph contains 2 triples") - - # the following are actually bad tests as they depend on your endpoint, - # as pointed out in the sparqlstore.py code: - # - # For ConjunctiveGraphs, reading is done from the "default graph" Exactly - # what this means depends on your endpoint, because SPARQL does not offer a - # simple way to query the union of all graphs as it would be expected for a - # ConjuntiveGraph. - ## - # Fuseki/TDB has a flag for specifying that the default graph - # is the union of all graphs (tdb:unionDefaultGraph in the Fuseki config). - self.assertEqual( - 3, - len(self.graph), - "default union graph should contain three triples but contains:\n" - "%s" % list(self.graph), - ) - - r = self.graph.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") - self.assertEqual(2, len(list(r)), "two people like pizza") + g2 = graph.get_context(othergraphuri) + g2.add((michel, likes, pizza)) - r = self.graph.query( - "SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }", initBindings={"s": tarek}, - ) - self.assertEqual(1, len(list(r)), "i was asking only about tarek") - - r = self.graph.triples((tarek, likes, pizza)) - self.assertEqual(1, len(list(r)), "i was asking only about tarek") + assert len(g) == 3, "graph contains 3 triples" + assert len(g2) == 1, "other graph contains 1 triple" - r = self.graph.triples((tarek, likes, cheese)) - self.assertEqual(0, len(list(r)), "tarek doesn't like cheese") + r = g.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") + assert len(list(r)) == 2, "two people like pizza" - g2.remove((bob, likes, pizza)) + r = g.triples((None, likes, pizza)) + assert len(list(r)) == 2, "two people like pizza" - r = self.graph.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") - self.assertEqual(1, len(list(r)), "only tarek likes pizza") + # Test initBindings + r = g.query( + "SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }", + initBindings={"s": tarek}, + ) + assert len(list(r)) == 1, "i was asking only about tarek" - def testUpdate(self): - self.graph.update( - "INSERT DATA { GRAPH <urn:example:graph> { <urn:example:michel> <urn:example:likes> <urn:example:pizza> . } }" - ) - - g = self.graph.get_context(graphuri) - self.assertEqual(1, len(g), "graph contains 1 triples") - - def testUpdateWithInitNs(self): - self.graph.update( - "INSERT DATA { GRAPH ns:graph { ns:michel ns:likes ns:pizza . } }", - initNs={"ns": URIRef("urn:example:")}, - ) - - g = self.graph.get_context(graphuri) - self.assertEqual( - set(g.triples((None, None, None))), - set([(michel, likes, pizza)]), - "only michel likes pizza", - ) - - def testUpdateWithInitBindings(self): - self.graph.update( - "INSERT { GRAPH <urn:example:graph> { ?a ?b ?c . } } WherE { }", - initBindings={ - "a": URIRef("urn:example:michel"), - "b": URIRef("urn:example:likes"), - "c": URIRef("urn:example:pizza"), - }, - ) - - g = self.graph.get_context(graphuri) - self.assertEqual( - set(g.triples((None, None, None))), - set([(michel, likes, pizza)]), - "only michel likes pizza", - ) - - def testUpdateWithBlankNode(self): - self.graph.update( - "INSERT DATA { GRAPH <urn:example:graph> { _:blankA <urn:example:type> <urn:example:Blank> } }" - ) - g = self.graph.get_context(graphuri) - for t in g.triples((None, None, None)): - self.assertTrue(isinstance(t[0], BNode)) - self.assertEqual(t[1].n3(), "<urn:example:type>") - self.assertEqual(t[2].n3(), "<urn:example:Blank>") - - def testUpdateWithBlankNodeSerializeAndParse(self): - self.graph.update( - "INSERT DATA { GRAPH <urn:example:graph> { _:blankA <urn:example:type> <urn:example:Blank> } }" - ) - g = self.graph.get_context(graphuri) - string = g.serialize(format="ntriples") - raised = False - try: - Graph().parse(data=string, format="ntriples") - except Exception as e: - raised = True - self.assertFalse(raised, "Exception raised when parsing: " + string) - - def testMultipleUpdateWithInitBindings(self): - self.graph.update( - "INSERT { GRAPH <urn:example:graph> { ?a ?b ?c . } } WHERE { };" - "INSERT { GRAPH <urn:example:graph> { ?d ?b ?c . } } WHERE { }", - initBindings={ - "a": URIRef("urn:example:michel"), - "b": URIRef("urn:example:likes"), - "c": URIRef("urn:example:pizza"), - "d": URIRef("urn:example:bob"), - }, - ) + r = g.triples((tarek, likes, pizza)) + assert len(list(r)) == 1, "i was asking only about tarek" - g = self.graph.get_context(graphuri) - self.assertEqual( - set(g.triples((None, None, None))), - set([(michel, likes, pizza), (bob, likes, pizza)]), - "michel and bob like pizza", - ) + r = g.triples((tarek, likes, cheese)) + assert len(list(r)) == 0, "tarek doesn't like cheese" + + g2.add((tarek, likes, pizza)) + g.remove((tarek, likes, pizza)) + r = g.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") + assert len(list(r)) == 1, "only bob likes pizza" - def testNamedGraphUpdate(self): - g = self.graph.get_context(graphuri) - r1 = "INSERT DATA { <urn:example:michel> <urn:example:likes> <urn:example:pizza> }" - g.update(r1) - self.assertEqual( - set(g.triples((None, None, None))), - set([(michel, likes, pizza)]), - "only michel likes pizza", - ) - r2 = ( - "DELETE { <urn:example:michel> <urn:example:likes> <urn:example:pizza> } " - + "INSERT { <urn:example:bob> <urn:example:likes> <urn:example:pizza> } WHERE {}" - ) - g.update(r2) - self.assertEqual( - set(g.triples((None, None, None))), - set([(bob, likes, pizza)]), - "only bob likes pizza", +def test_conjunctive_default(get_graph): + graph = get_graph + g = graph.get_context(graphuri) + g.add((tarek, likes, pizza)) + g2 = graph.get_context(othergraphuri) + g2.add((bob, likes, pizza)) + g.add((tarek, hates, cheese)) + + assert 2 == len(g), "graph contains 2 triples" + + # the following are actually bad tests as they depend on your endpoint, + # as pointed out in the sparqlstore.py code: + # + # For ConjunctiveGraphs, reading is done from the "default graph" Exactly + # what this means depends on your endpoint, because SPARQL does not offer a + # simple way to query the union of all graphs as it would be expected for a + # ConjuntiveGraph. + ## + # Fuseki/TDB has a flag for specifying that the default graph + # is the union of all graphs (tdb:unionDefaultGraph in the Fuseki config). + assert ( + len(graph) == 3 + ), "default union graph should contain three triples but contains:\n%s" % list( + graph + ) + + r = graph.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") + assert len(list(r)) == 2, "two people like pizza" + + r = graph.query( + "SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }", + initBindings={"s": tarek}, + ) + assert len(list(r)) == 1, "i was asking only about tarek" + + r = graph.triples((tarek, likes, pizza)) + assert len(list(r)) == 1, "i was asking only about tarek" + + r = graph.triples((tarek, likes, cheese)) + assert len(list(r)) == 0, "tarek doesn't like cheese" + + g2.remove((bob, likes, pizza)) + + r = graph.query("SELECT * WHERE { ?s <urn:example:likes> <urn:example:pizza> . }") + assert len(list(r)) == 1, "only tarek likes pizza" + + +def testU_update(get_graph): + graph = get_graph + graph.update( + "INSERT DATA { GRAPH <urn:example:graph> { <urn:example:michel> <urn:example:likes> <urn:example:pizza> . } }" + ) + + g = graph.get_context(graphuri) + assert 1 == len(g), "graph contains 1 triples" + + +def testU_update_with_initns(get_graph): + graph = get_graph + graph.update( + "INSERT DATA { GRAPH ns:graph { ns:michel ns:likes ns:pizza . } }", + initNs={"ns": URIRef("urn:example:")}, + ) + + g = graph.get_context(graphuri) + assert set(g.triples((None, None, None))) == set( + [(michel, likes, pizza)] + ), "only michel likes pizza" + + +def test_update_with_init_bindings(get_graph): + graph = get_graph + graph.update( + "INSERT { GRAPH <urn:example:graph> { ?a ?b ?c . } } WherE { }", + initBindings={ + "a": URIRef("urn:example:michel"), + "b": URIRef("urn:example:likes"), + "c": URIRef("urn:example:pizza"), + }, + ) + + g = graph.get_context(graphuri) + assert set(g.triples((None, None, None))) == set( + [(michel, likes, pizza)] + ), "only michel likes pizza" + + +def test_update_with_blank_node(get_graph): + graph = get_graph + graph.update( + "INSERT DATA { GRAPH <urn:example:graph> { _:blankA <urn:example:type> <urn:example:Blank> } }" + ) + g = graph.get_context(graphuri) + for t in g.triples((None, None, None)): + assert isinstance(t[0], BNode) + assert t[1].n3() == "<urn:example:type>" + assert t[2].n3() == "<urn:example:Blank>" + + +def test_updateW_with_blank_node_serialize_and_parse(get_graph): + graph = get_graph + graph.update( + "INSERT DATA { GRAPH <urn:example:graph> { _:blankA <urn:example:type> <urn:example:Blank> } }" + ) + g = graph.get_context(graphuri) + string = g.serialize(format="ntriples") + raised = False + try: + Graph().parse(data=string, format="ntriples") + except Exception as e: + raised = True + assert raised is False, "Exception raised when parsing: " + string + + +def test_multiple_update_with_init_bindings(get_graph): + graph = get_graph + graph.update( + "INSERT { GRAPH <urn:example:graph> { ?a ?b ?c . } } WHERE { };" + "INSERT { GRAPH <urn:example:graph> { ?d ?b ?c . } } WHERE { }", + initBindings={ + "a": URIRef("urn:example:michel"), + "b": URIRef("urn:example:likes"), + "c": URIRef("urn:example:pizza"), + "d": URIRef("urn:example:bob"), + }, + ) + + g = graph.get_context(graphuri) + assert set(g.triples((None, None, None))) == set( + [(michel, likes, pizza), (bob, likes, pizza)] + ), "michel and bob like pizza" + + +def test_named_graph_update(get_graph): + graph = get_graph + g = graph.get_context(graphuri) + r1 = "INSERT DATA { <urn:example:michel> <urn:example:likes> <urn:example:pizza> }" + g.update(r1) + assert set(g.triples((None, None, None))) == set( + [(michel, likes, pizza)] + ), "only michel likes pizza" + + r2 = ( + "DELETE { <urn:example:michel> <urn:example:likes> <urn:example:pizza> } " + + "INSERT { <urn:example:bob> <urn:example:likes> <urn:example:pizza> } WHERE {}" + ) + g.update(r2) + assert set(g.triples((None, None, None))) == set( + [(bob, likes, pizza)] + ), "only bob likes pizza" + + says = URIRef("urn:says") + + # Strings with unbalanced curly braces + tricky_strs = ["With an unbalanced curly brace %s " % brace for brace in ["{", "}"]] + for tricky_str in tricky_strs: + r3 = ( + """INSERT { ?b <urn:says> "%s" } + WHERE { ?b <urn:example:likes> <urn:example:pizza>} """ + % tricky_str ) - says = URIRef("urn:says") - - # Strings with unbalanced curly braces - tricky_strs = [ - "With an unbalanced curly brace %s " % brace for brace in ["{", "}"] - ] - for tricky_str in tricky_strs: - r3 = ( - """INSERT { ?b <urn:says> "%s" } - WHERE { ?b <urn:example:likes> <urn:example:pizza>} """ - % tricky_str + g.update(r3) + + values = set() + for v in g.objects(bob, says): + values.add(str(v)) + assert values == set(tricky_strs) + + # Complicated Strings + r4strings = [] + r4strings.append(r'''"1: adfk { ' \\\" \" { "''') + r4strings.append(r'''"2: adfk } <foo> #éï \\"''') + + r4strings.append(r"""'3: adfk { " \\\' \' { '""") + r4strings.append(r"""'4: adfk } <foo> #éï \\'""") + + r4strings.append(r'''"""5: adfk { ' \\\" \" { """''') + r4strings.append(r'''"""6: adfk } <foo> #éï \\"""''') + r4strings.append('"""7: ad adsfj \n { \n sadfj"""') + + r4strings.append(r"""'''8: adfk { " \\\' \' { '''""") + r4strings.append(r"""'''9: adfk } <foo> #éï \\'''""") + r4strings.append("'''10: ad adsfj \n { \n sadfj'''") + + r4 = "\n".join( + ["INSERT DATA { <urn:example:michel> <urn:says> %s } ;" % s for s in r4strings] + ) + g.update(r4) + values = set() + for v in g.objects(michel, says): + values.add(str(v)) + assert values == set( + [ + re.sub( + r"\\(.)", + r"\1", + re.sub(r"^'''|'''$|^'|'$|" + r'^"""|"""$|^"|"$', r"", s), ) - g.update(r3) - - values = set() - for v in g.objects(bob, says): - values.add(str(v)) - self.assertEqual(values, set(tricky_strs)) - - # Complicated Strings - r4strings = [] - r4strings.append(r'''"1: adfk { ' \\\" \" { "''') - r4strings.append(r'''"2: adfk } <foo> #éï \\"''') - - r4strings.append(r"""'3: adfk { " \\\' \' { '""") - r4strings.append(r"""'4: adfk } <foo> #éï \\'""") - - r4strings.append(r'''"""5: adfk { ' \\\" \" { """''') - r4strings.append(r'''"""6: adfk } <foo> #éï \\"""''') - r4strings.append('"""7: ad adsfj \n { \n sadfj"""') - - r4strings.append(r"""'''8: adfk { " \\\' \' { '''""") - r4strings.append(r"""'''9: adfk } <foo> #éï \\'''""") - r4strings.append("'''10: ad adsfj \n { \n sadfj'''") - - r4 = "\n".join( - ["INSERT DATA { <urn:example:michel> <urn:says> %s } ;" % s for s in r4strings] - ) - g.update(r4) - values = set() - for v in g.objects(michel, says): - values.add(str(v)) - self.assertEqual( - values, - set( - [ - re.sub( - r"\\(.)", - r"\1", - re.sub(r"^'''|'''$|^'|'$|" + r'^"""|"""$|^"|"$', r"", s), - ) - for s in r4strings - ] - ), - ) - - # IRI Containing ' or # - # The fragment identifier must not be misinterpreted as a comment - # (commenting out the end of the block). - # The ' must not be interpreted as the start of a string, causing the } - # in the literal to be identified as the end of the block. - r5 = """INSERT DATA { <urn:example:michel> <urn:example:hates> <urn:example:foo'bar?baz;a=1&b=2#fragment>, "'}" }""" - - g.update(r5) - values = set() - for v in g.objects(michel, hates): - values.add(str(v)) - self.assertEqual(values, set(["urn:example:foo'bar?baz;a=1&b=2#fragment", "'}"])) - - # Comments - r6 = """ - INSERT DATA { - <urn:example:bob> <urn:example:hates> <urn:example:bob> . # No closing brace: } - <urn:example:bob> <urn:example:hates> <urn:example:michel>. - } - #Final { } comment""" - - g.update(r6) - values = set() - for v in g.objects(bob, hates): - values.add(v) - self.assertEqual(values, set([bob, michel])) - - def testNamedGraphUpdateWithInitBindings(self): - g = self.graph.get_context(graphuri) - r = "INSERT { ?a ?b ?c } WHERE {}" - g.update(r, initBindings={"a": michel, "b": likes, "c": pizza}) - self.assertEqual( - set(g.triples((None, None, None))), - set([(michel, likes, pizza)]), - "only michel likes pizza", - ) - - def testEmptyNamedGraph(self): - empty_graph_iri = "urn:empty-graph-1" - self.graph.update("CREATE GRAPH <%s>" % empty_graph_iri) - named_graphs = [ - str(r[0]) for r in self.graph.query("SELECT ?name WHERE { GRAPH ?name {} }") + for s in r4strings ] - # Some SPARQL endpoint backends (like TDB) are not able to find empty named graphs - # (at least with this query) - if empty_graph_iri in named_graphs: - self.assertTrue( - empty_graph_iri in [str(g.identifier) for g in self.graph.contexts()] - ) - - def testEmptyLiteral(self): - # test for https://github.com/RDFLib/rdflib/issues/457 - # also see test_issue457.py which is sparql store independent! - g = self.graph.get_context(graphuri) - g.add( - ( - URIRef("http://example.com/s"), - URIRef("http://example.com/p"), - Literal(""), - ) + ) + + # IRI Containing ' or # + # The fragment identifier must not be misinterpreted as a comment + # (commenting out the end of the block). + # The ' must not be interpreted as the start of a string, causing the } + # in the literal to be identified as the end of the block. + r5 = """INSERT DATA { <urn:example:michel> <urn:example:hates> <urn:example:foo'bar?baz;a=1&b=2#fragment>, "'}" }""" + + g.update(r5) + values = set() + for v in g.objects(michel, hates): + values.add(str(v)) + assert values == set(["urn:example:foo'bar?baz;a=1&b=2#fragment", "'}"]) + + # Comments + r6 = """ + INSERT DATA { + <urn:example:bob> <urn:example:hates> <urn:example:bob> . # No closing brace: } + <urn:example:bob> <urn:example:hates> <urn:example:michel>. + } + #Final { } comment""" + + g.update(r6) + values = set() + for v in g.objects(bob, hates): + values.add(v) + assert values == set([bob, michel]) + + +def test_named_graph_update_with_init_bindings(get_graph): + graph = get_graph + g = graph.get_context(graphuri) + r = "INSERT { ?a ?b ?c } WHERE {}" + g.update(r, initBindings={"a": michel, "b": likes, "c": pizza}) + assert set(g.triples((None, None, None))) == set( + [(michel, likes, pizza)] + ), "only michel likes pizza" + + +def test_empty_named_graph(get_graph): + graph = get_graph + empty_graph_iri = "urn:empty-graph-1" + graph.update("CREATE GRAPH <%s>" % empty_graph_iri) + named_graphs = [ + str(r[0]) for r in graph.query("SELECT ?name WHERE { GRAPH ?name {} }") + ] + # Some SPARQL endpoint backends (like TDB) are not able to find empty named graphs + # (at least with this query) + if empty_graph_iri in named_graphs: + assert empty_graph_iri in [str(g.identifier) for g in graph.contexts()] + + +def test_empty_literal(get_graph): + graph = get_graph + # test for https://github.com/RDFLib/rdflib/issues/457 + # also see test_issue457.py which is sparql store independent! + g = graph.get_context(graphuri) + g.add( + ( + URIRef("http://example.com/s"), + URIRef("http://example.com/p"), + Literal(""), ) + ) - o = tuple(g)[0][2] - self.assertEqual(o, Literal(""), repr(o)) - - -if __name__ == "__main__": - unittest.main() + o = tuple(g)[0][2] + assert o == Literal(""), repr(o) diff --git a/test/test_store/test_store_triple_store.py b/test/test_store/test_store_triple_store.py index f37bea33..e3753064 100644 --- a/test/test_store/test_store_triple_store.py +++ b/test/test_store/test_store_triple_store.py @@ -1,35 +1,36 @@ -import unittest +import pytest -from rdflib.term import BNode, Literal -from rdflib.namespace import RDFS from rdflib.graph import Graph +from rdflib.namespace import RDFS +from rdflib.term import BNode, Literal + +remove_me = (BNode(), RDFS.label, Literal("remove_me")) + +@pytest.fixture(scope="function") +def get_store(request): + store = Graph(store="default") + store.open("store") + store.add(remove_me) -class GraphTest(unittest.TestCase): - backend = "default" - path = "store" + yield store - def setUp(self): - self.store = Graph(store=self.backend) - self.store.open(self.path) - self.remove_me = (BNode(), RDFS.label, Literal("remove_me")) - self.store.add(self.remove_me) + store.close() - def tearDown(self): - self.store.close() - def testAdd(self): - subject = BNode() - self.store.add((subject, RDFS.label, Literal("foo"))) +def test_add(get_store): + store = get_store + subject = BNode() + store.add((subject, RDFS.label, Literal("foo"))) - def testRemove(self): - self.store.remove(self.remove_me) - self.store.remove((None, None, None)) - def testTriples(self): - for s, p, o in self.store: - pass +def test_remove(get_store): + store = get_store + store.remove(remove_me) + store.remove((None, None, None)) -if __name__ == "__main__": - unittest.main() +def test_triples(get_store): + store = get_store + for s, p, o in store: + pass |
