diff options
author | Matthias Baumgartner <dev@igsor.net> | 2022-12-18 14:22:31 +0100 |
---|---|---|
committer | Matthias Baumgartner <dev@igsor.net> | 2022-12-18 14:22:31 +0100 |
commit | 7582c280ad5324a2f0427999911c7e7abc14a6ab (patch) | |
tree | 0a59bbfe1c44d3497daad9f25ff9e7eb2bf9eb82 /test | |
parent | cb49e4567a18de6851286ff672e54f9a91865fe9 (diff) | |
parent | 057e09d6537bf5c39815661a75819081e3e5fda7 (diff) | |
download | bsie-7582c280ad5324a2f0427999911c7e7abc14a6ab.tar.gz bsie-7582c280ad5324a2f0427999911c7e7abc14a6ab.tar.bz2 bsie-7582c280ad5324a2f0427999911c7e7abc14a6ab.zip |
Merge branch 'develop' into main
Diffstat (limited to 'test')
35 files changed, 1474 insertions, 0 deletions
diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/__init__.py diff --git a/test/apps/__init__.py b/test/apps/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/apps/__init__.py diff --git a/test/apps/test_index.py b/test/apps/test_index.py new file mode 100644 index 0000000..9cdc656 --- /dev/null +++ b/test/apps/test_index.py @@ -0,0 +1,159 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import contextlib +import io +import os +import rdflib +import unittest + +# bsie imports +from bsie.utils import ns + +# objects to test +from bsie.apps.index import main + + +## code ## + +class TestIndex(unittest.TestCase): + def test_main(self): + bsfs = main([ + '-r', + '--user', 'http://example.com/me', + os.path.join(os.path.dirname(__file__), 'testdir'), + os.path.join(os.path.dirname(__file__), 'testfile'), + ]) + + prefix = 'http://example.com/me/file#' + self.assertTrue(set(bsfs._backend._graph).issuperset({ + (rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('alpha_second', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('696', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('omega_second', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('503', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('td_first', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('911', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('testfile', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('885', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('bar_first', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('956', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('omega_first', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('648', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('alpha_first', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('754', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('foo_second', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('585', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('bar_second', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('636', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('foo_first', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('546', datatype=rdflib.XSD.integer)), + (rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), rdflib.RDF.type, rdflib.URIRef(ns.bsfs.File)), + (rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), rdflib.URIRef(ns.bse.author), rdflib.Literal('Me, myself, and I', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('td_second', datatype=rdflib.XSD.string)), + (rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), rdflib.URIRef(ns.bse.filesize), rdflib.Literal('703', datatype=rdflib.XSD.integer)), + })) + + # NOTE: we don't check ns.bsm.t_created since it depends on the execution time. Triples would look like this: + # (rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # (rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), rdflib.URIRef(ns.bsm.t_created), rdflib.Literal('1670..........', datatype=rdflib.XSD.integer)), + # instead, we simply check if there's such a predicate for each file + self.assertSetEqual({sub for sub, _ in bsfs._backend._graph.subject_objects(rdflib.URIRef(ns.bsm.t_created))}, { + rdflib.URIRef(prefix + '2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647'), + rdflib.URIRef(prefix + '441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece'), + rdflib.URIRef(prefix + '69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871'), + rdflib.URIRef(prefix + '78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926'), + rdflib.URIRef(prefix + '80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3'), + rdflib.URIRef(prefix + '976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795'), + rdflib.URIRef(prefix + '997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3'), + rdflib.URIRef(prefix + 'a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d'), + rdflib.URIRef(prefix + 'b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70'), + rdflib.URIRef(prefix + 'd43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d'), + rdflib.URIRef(prefix + 'd803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1'), + }) + + def test_print(self): + outbuf = io.StringIO() + with contextlib.redirect_stdout(outbuf): + bsfs = main([ + '--print', + '-r', + '--user', 'http://example.com/me', + os.path.join(os.path.dirname(__file__), 'testdir'), + os.path.join(os.path.dirname(__file__), 'testfile'), + ]) + self.assertSetEqual(set(outbuf.getvalue().split('\n')) - {''}, { + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647) Predicate({ns.bse.filename}) alpha_second', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#2f4109b40107cc50e0884755a1a961ed126887e49b8dbaf0e146b2e226aa6647) Predicate({ns.bse.filesize}) 696', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece) Predicate({ns.bse.filename}) omega_second', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#441f3d10c8ff489fe8e33e639606512f6c463151cc429de7e554b9af670c2ece) Predicate({ns.bse.filesize}) 503', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871) Predicate({ns.bse.filename}) td_first', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#69b98ecf7aff3e95b09688ba93331678eb8397817111f674c9558e6dd8f5e871) Predicate({ns.bse.filesize}) 911', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926) Predicate({ns.bse.filename}) testfile', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#78f7eb7f0d8221cdb2cb26c978fa42a11f75eb87becc768f4474134cb1e06926) Predicate({ns.bse.filesize}) 885', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3) Predicate({ns.bse.filename}) bar_first', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#80818b8ec2ee1919116dba9c8a7e0a4608313cf3b463cd88e9ed77a700dd92d3) Predicate({ns.bse.filesize}) 956', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795) Predicate({ns.bse.filename}) omega_first', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#976d2ea0e58488678cc7e435fbfadabfb6eb6cf50ad51862f38f73729ed11795) Predicate({ns.bse.filesize}) 648', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3) Predicate({ns.bse.filename}) alpha_first', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#997e2fbb7494a3818ec782d2bc87bf1cffafba6b9c0f658e4a6c18a723e944d3) Predicate({ns.bse.filesize}) 754', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d) Predicate({ns.bse.filename}) foo_second', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#a8af899ecdab60dfaea8ec7f934053624c80a1054539e163f2c7eaa986c2777d) Predicate({ns.bse.filesize}) 585', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70) Predicate({ns.bse.filename}) bar_second', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#b8fd7fba818254166a6043195004138ebda6923e012442f819a2c49671136c70) Predicate({ns.bse.filesize}) 636', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d) Predicate({ns.bse.filename}) foo_first', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d43758ace82154a1cc10ca0dfef63cb20dd831f9c87edd6dc06539eefe67371d) Predicate({ns.bse.filesize}) 546', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1) Predicate({ns.bse.author}) Me, myself, and I', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1) Predicate({ns.bse.filename}) td_second', + f'Node(http://bsfs.ai/schema/File, http://example.com/me/file#d803187cbf3676ae9d38126270a6152c60431589aa3bb3824baf8954e9c097f1) Predicate({ns.bse.filesize}) 703', + }) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/apps/test_info.py b/test/apps/test_info.py new file mode 100644 index 0000000..6f4d98f --- /dev/null +++ b/test/apps/test_info.py @@ -0,0 +1,42 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import argparse +import contextlib +import io +import unittest + +# objects to test +from bsie.apps.info import main + + +## code ## + +class TestIndex(unittest.TestCase): + def test_predicates(self): + outbuf = io.StringIO() + with contextlib.redirect_stdout(outbuf): + # show predicates infos + main(['predicates']) + # verify output + self.assertSetEqual({pred for pred in outbuf.getvalue().split('\n') if pred != ''}, { + 'http://bsfs.ai/schema/Entity#author', + 'http://bsfs.ai/schema/Predicate', + 'http://bsfs.ai/schema/Entity#filename', + 'http://bsfs.ai/schema/Entity#filesize', + }) + + def test_invalid(self): + with contextlib.redirect_stderr(io.StringIO()): + self.assertRaises(SystemExit, main, ['foobar']) + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/apps/testdir/alpha/alpha_first b/test/apps/testdir/alpha/alpha_first new file mode 100644 index 0000000..f96fdee --- /dev/null +++ b/test/apps/testdir/alpha/alpha_first @@ -0,0 +1,16 @@ +Turpis tincidunt id aliquet risus feugiat in ante metus. +Vel turpis nunc eget lorem dolor. +Lorem mollis aliquam ut porttitor leo a diam sollicitudin. +Sit amet mattis vulputate enim nulla aliquet porttitor lacus luctus. +Vitae et leo duis ut diam. +Integer eget aliquet nibh praesent tristique magna sit. +Volutpat sed cras ornare arcu dui. +Consectetur adipiscing elit duis tristique sollicitudin nibh. +Interdum varius sit amet mattis vulputate. +A arcu cursus vitae congue. +Risus nec feugiat in fermentum posuere urna nec tincidunt praesent. +Sit amet dictum sit amet justo donec enim diam. +Maecenas accumsan lacus vel facilisis. +Erat velit scelerisque in dictum non consectetur a. +Tempor orci dapibus ultrices in iaculis nunc. +Nisi lacus sed viverra tellus. diff --git a/test/apps/testdir/alpha/alpha_second b/test/apps/testdir/alpha/alpha_second new file mode 100644 index 0000000..ae83ce8 --- /dev/null +++ b/test/apps/testdir/alpha/alpha_second @@ -0,0 +1,12 @@ +Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. +Orci dapibus ultrices in iaculis nunc sed augue. +Tincidunt vitae semper quis lectus nulla at. +Maecenas ultricies mi eget mauris pharetra et. +Porttitor massa id neque aliquam vestibulum morbi blandit. +Et magnis dis parturient montes nascetur ridiculus mus mauris. +Ac orci phasellus egestas tellus rutrum tellus pellentesque. +Donec ac odio tempor orci dapibus. +Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. +Potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed. +Orci porta non pulvinar neque laoreet suspendisse interdum consectetur. +Mauris pellentesque pulvinar pellentesque habitant morbi tristique. diff --git a/test/apps/testdir/alpha/omega/omega_first b/test/apps/testdir/alpha/omega/omega_first new file mode 100644 index 0000000..e594737 --- /dev/null +++ b/test/apps/testdir/alpha/omega/omega_first @@ -0,0 +1,14 @@ +Neque gravida in fermentum et sollicitudin. +Sodales ut eu sem integer vitae justo eget magna fermentum. +Amet nulla facilisi morbi tempus iaculis. +Proin sagittis nisl rhoncus mattis rhoncus urna neque. +Aliquam sem fringilla ut morbi tincidunt augue interdum velit euismod. +Sagittis eu volutpat odio facilisis. +Aliquet porttitor lacus luctus accumsan tortor posuere ac ut. +Sed arcu non odio euismod lacinia. +Faucibus et molestie ac feugiat. +Urna neque viverra justo nec ultrices dui sapien eget. +Amet commodo nulla facilisi nullam. +Pretium lectus quam id leo in vitae. +A cras semper auctor neque. +Sed arcu non odio euismod lacinia at quis risus sed. diff --git a/test/apps/testdir/alpha/omega/omega_second b/test/apps/testdir/alpha/omega/omega_second new file mode 100644 index 0000000..0c9857d --- /dev/null +++ b/test/apps/testdir/alpha/omega/omega_second @@ -0,0 +1,10 @@ +Commodo sed egestas egestas fringilla phasellus. +Ac tortor dignissim convallis aenean et tortor at risus. +Lorem dolor sed viverra ipsum nunc aliquet bibendum enim. +Quis lectus nulla at volutpat diam ut. +Tincidunt id aliquet risus feugiat in ante metus. +Tincidunt arcu non sodales neque. +Amet est placerat in egestas erat imperdiet sed euismod. +Duis tristique sollicitudin nibh sit amet. +Sed arcu non odio euismod lacinia at. +Ullamcorper morbi tincidunt ornare massa eget egestas purus viverra accumsan. diff --git a/test/apps/testdir/foo/bar/bar_first b/test/apps/testdir/foo/bar/bar_first new file mode 100644 index 0000000..e9edb3f --- /dev/null +++ b/test/apps/testdir/foo/bar/bar_first @@ -0,0 +1,20 @@ +Elementum eu facilisis sed odio morbi quis commodo. +Enim nunc faucibus a pellentesque sit amet porttitor. +Etiam non quam lacus suspendisse faucibus interdum. +Viverra aliquet eget sit amet tellus. +Arcu vitae elementum curabitur vitae. +Feugiat vivamus at augue eget arcu dictum. +Commodo quis imperdiet massa tincidunt nunc. +Urna duis convallis convallis tellus id interdum. +Commodo sed egestas egestas fringilla phasellus. +Sodales neque sodales ut etiam sit amet nisl. +Sem integer vitae justo eget magna fermentum iaculis. +Id diam maecenas ultricies mi. +Aliquet nibh praesent tristique magna sit amet purus gravida. +Ut enim blandit volutpat maecenas volutpat. +Ipsum a arcu cursus vitae congue mauris. +Donec ultrices tincidunt arcu non. +Nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus. +Egestas maecenas pharetra convallis posuere. +Feugiat in fermentum posuere urna nec. +Nulla malesuada pellentesque elit eget gravida cum sociis. diff --git a/test/apps/testdir/foo/bar/bar_second b/test/apps/testdir/foo/bar/bar_second new file mode 100644 index 0000000..fb95896 --- /dev/null +++ b/test/apps/testdir/foo/bar/bar_second @@ -0,0 +1,14 @@ +Augue ut lectus arcu bibendum at varius vel pharetra vel. +Mattis aliquam faucibus purus in. +In tellus integer feugiat scelerisque. +Eget velit aliquet sagittis id consectetur purus ut faucibus pulvinar. +Augue mauris augue neque gravida. +Pulvinar neque laoreet suspendisse interdum consectetur libero id faucibus. +Tellus elementum sagittis vitae et leo duis. +Eget est lorem ipsum dolor sit amet consectetur. +Volutpat sed cras ornare arcu. +Faucibus a pellentesque sit amet. +Turpis egestas maecenas pharetra convallis. +Faucibus interdum posuere lorem ipsum dolor sit amet. +Id semper risus in hendrerit. +Amet volutpat consequat mauris nunc. diff --git a/test/apps/testdir/foo/foo_first b/test/apps/testdir/foo/foo_first new file mode 100644 index 0000000..ed1e052 --- /dev/null +++ b/test/apps/testdir/foo/foo_first @@ -0,0 +1,11 @@ +Venenatis tellus in metus vulputate eu scelerisque felis imperdiet proin. +Orci phasellus egestas tellus rutrum. +Feugiat vivamus at augue eget arcu dictum varius. +Justo eget magna fermentum iaculis eu non. +A erat nam at lectus urna duis. +Quam quisque id diam vel quam elementum pulvinar etiam. +Amet commodo nulla facilisi nullam vehicula ipsum a. +Sapien faucibus et molestie ac feugiat. +Aliquam vestibulum morbi blandit cursus risus at ultrices. +Purus faucibus ornare suspendisse sed nisi. +In massa tempor nec feugiat nisl pretium fusce id velit. diff --git a/test/apps/testdir/foo/foo_second b/test/apps/testdir/foo/foo_second new file mode 100644 index 0000000..95e46ae --- /dev/null +++ b/test/apps/testdir/foo/foo_second @@ -0,0 +1,12 @@ +Sit amet consectetur adipiscing elit ut aliquam purus. +Vulputate dignissim suspendisse in est ante in nibh. +Eu feugiat pretium nibh ipsum consequat nisl vel pretium. +Egestas purus viverra accumsan in nisl. +Ac odio tempor orci dapibus ultrices. +At imperdiet dui accumsan sit amet. +Elementum integer enim neque volutpat ac tincidunt vitae semper. +Mi in nulla posuere sollicitudin aliquam ultrices sagittis. +Aliquam sem et tortor consequat. +Tristique senectus et netus et malesuada fames ac turpis. +Quis hendrerit dolor magna eget est lorem ipsum. +Ut consequat semper viverra nam libero. diff --git a/test/apps/testdir/td_first b/test/apps/testdir/td_first new file mode 100644 index 0000000..21eab9c --- /dev/null +++ b/test/apps/testdir/td_first @@ -0,0 +1,18 @@ +Urna duis convallis convallis tellus id interdum velit. +Risus in hendrerit gravida rutrum. +Odio pellentesque diam volutpat commodo sed. +Duis convallis convallis tellus id interdum velit laoreet id donec. +Duis at tellus at urna. +Egestas maecenas pharetra convallis posuere morbi leo urna molestie at. +Et leo duis ut diam quam nulla porttitor massa id. +Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. +Sodales ut etiam sit amet nisl purus in. +Ac felis donec et odio pellentesque diam volutpat commodo. +Nunc mi ipsum faucibus vitae aliquet. +Volutpat ac tincidunt vitae semper quis lectus nulla at volutpat. +Mollis aliquam ut porttitor leo. +Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras. +Pulvinar proin gravida hendrerit lectus a. +Ultrices dui sapien eget mi proin. +Dui vivamus arcu felis bibendum ut. +Aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices sagittis. diff --git a/test/apps/testdir/td_second b/test/apps/testdir/td_second new file mode 100644 index 0000000..496ff0e --- /dev/null +++ b/test/apps/testdir/td_second @@ -0,0 +1,14 @@ +Egestas purus viverra accumsan in. +Auctor urna nunc id cursus metus aliquam eleifend. +Morbi tincidunt augue interdum velit. +In egestas erat imperdiet sed euismod nisi porta lorem mollis. +Sed augue lacus viverra vitae congue eu consequat. +Ut pharetra sit amet aliquam id. +Aenean euismod elementum nisi quis eleifend. +Hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. +Eget nunc lobortis mattis aliquam faucibus purus. +Sit amet luctus venenatis lectus magna fringilla. +Placerat orci nulla pellentesque dignissim enim sit amet venenatis. +Montes nascetur ridiculus mus mauris. +Morbi enim nunc faucibus a pellentesque sit amet. +Et netus et malesuada fames ac turpis egestas. diff --git a/test/apps/testfile b/test/apps/testfile new file mode 100644 index 0000000..b56928e --- /dev/null +++ b/test/apps/testfile @@ -0,0 +1,16 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +Fames ac turpis egestas maecenas pharetra convallis posuere morbi. +Etiam erat velit scelerisque in dictum non consectetur a erat. +Dolor purus non enim praesent elementum facilisis. +Nulla porttitor massa id neque aliquam vestibulum morbi blandit cursus. +Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna neque. +Aenean pharetra magna ac placerat. +Pulvinar proin gravida hendrerit lectus a. +Iaculis nunc sed augue lacus viverra vitae. +Ac tortor vitae purus faucibus ornare suspendisse sed. +Purus in mollis nunc sed id semper. +Non consectetur a erat nam at lectus urna. +In ante metus dictum at tempor commodo ullamcorper. +Auctor augue mauris augue neque gravida in fermentum. +Nunc scelerisque viverra mauris in. +Morbi leo urna molestie at elementum. diff --git a/test/base/__init__.py b/test/base/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/base/__init__.py diff --git a/test/base/test_extractor.py b/test/base/test_extractor.py new file mode 100644 index 0000000..30974ef --- /dev/null +++ b/test/base/test_extractor.py @@ -0,0 +1,70 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsie.utils import bsfs, ns + +# objects to test +from bsie.base import extractor + + +## code ## + +class StubExtractor(extractor.Extractor): + def __init__(self): + super().__init__(bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + def extract(self, subject, content, predicates): + raise NotImplementedError() + +class StubSub(StubExtractor): + pass + +class TestExtractor(unittest.TestCase): + def test_essentials(self): + ext = StubExtractor() + self.assertEqual(str(ext), 'StubExtractor') + self.assertEqual(repr(ext), 'StubExtractor()') + self.assertEqual(ext, StubExtractor()) + self.assertEqual(hash(ext), hash(StubExtractor())) + + sub = StubSub() + self.assertEqual(str(sub), 'StubSub') + self.assertEqual(repr(sub), 'StubSub()') + self.assertEqual(sub, StubSub()) + self.assertEqual(hash(sub), hash(StubSub())) + self.assertNotEqual(ext, sub) + self.assertNotEqual(hash(ext), hash(sub)) + + def test_principals(self): + schema = bsfs.schema.Schema.Empty() + entity = schema.node(ns.bsfs.Node).get_child(ns.bsfs.Entity) + string = schema.literal(ns.bsfs.Literal).get_child(bsfs.URI('http://www.w3.org/2001/XMLSchema#string')) + p_author = schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.author, domain=entity, range=string) + p_comment = schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.comment, domain=entity, range=string) + ext = StubExtractor() + self.assertSetEqual(set(ext.principals), + {p_author, p_comment} | set(schema.predicates()) - {schema.predicate(ns.bsfs.Predicate)}) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/base/test_reader.py b/test/base/test_reader.py new file mode 100644 index 0000000..a907eb9 --- /dev/null +++ b/test/base/test_reader.py @@ -0,0 +1,45 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# objects to test +from bsie import base + + +## code ## + +class StubReader(base.Reader): + def __call__(self, path): + raise NotImplementedError() + +class StubSub(StubReader): + pass + +class TestReader(unittest.TestCase): + def test_essentials(self): + ext = StubReader() + self.assertEqual(str(ext), 'StubReader') + self.assertEqual(repr(ext), 'StubReader()') + self.assertEqual(ext, StubReader()) + self.assertEqual(hash(ext), hash(StubReader())) + + sub = StubSub() + self.assertEqual(str(sub), 'StubSub') + self.assertEqual(repr(sub), 'StubSub()') + self.assertEqual(sub, StubSub()) + self.assertEqual(hash(sub), hash(StubSub())) + self.assertNotEqual(ext, sub) + self.assertNotEqual(hash(ext), hash(sub)) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/extractor/__init__.py b/test/extractor/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/extractor/__init__.py diff --git a/test/extractor/generic/__init__.py b/test/extractor/generic/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/extractor/generic/__init__.py diff --git a/test/extractor/generic/test_constant.py b/test/extractor/generic/test_constant.py new file mode 100644 index 0000000..9dbaced --- /dev/null +++ b/test/extractor/generic/test_constant.py @@ -0,0 +1,124 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsie.utils import node as _node, ns + +# objects to test +from bsie.extractor.generic.constant import Constant + + +## code ## + +class TestConstant(unittest.TestCase): + def test_extract(self): + schema = ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''' + tuples = [ + (ns.bse.author, 'Me, myself, and I'), + (ns.bse.comment, 'the quick brown fox jumps over the lazy dog.'), + ] + ext = Constant(schema, tuples) + node = _node.Node(ns.bsfs.Entity, '') # Blank node + p_author = ext.schema.predicate(ns.bse.author) + p_comment = ext.schema.predicate(ns.bse.comment) + entity = ext.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Entity) + string = ext.schema.literal(ns.bsfs.Literal).get_child(ns.xsd.string) + # baseline + self.assertSetEqual(set(ext.extract(node, None, (p_author, p_comment))), + {(node, p_author, 'Me, myself, and I'), + (node, p_comment, 'the quick brown fox jumps over the lazy dog.')}) + # predicates is respected + p_foobar = ext.schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.foobar, domain=entity, range=entity) + self.assertSetEqual(set(ext.extract(node, None, (p_author, p_foobar))), + {(node, p_author, 'Me, myself, and I')}) + self.assertSetEqual(set(ext.extract(node, None, (p_comment, p_foobar))), + {(node, p_comment, 'the quick brown fox jumps over the lazy dog.')}) + p_barfoo = ext.schema.predicate(ns.bse.author).get_child(ns.bse.comment, domain=entity, range=string) + self.assertSetEqual(set(ext.extract(node, None, (p_foobar, p_barfoo))), set()) + + def test_construct(self): + # schema compliance + schema = ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''' + # can create a schema + self.assertIsInstance(Constant(schema, [ + (ns.bse.author, 'Me, myself, and I'), + (ns.bse.comment, 'the quick brown fox jumps over the lazy dog.'), + ]), Constant) + # predicates are validated + self.assertRaises(KeyError, Constant, schema, [ + (ns.bse.author, 'Me, myself, and I'), + (ns.bse.foobar, 'foobar!')]) + # FIXME: values are validated + #class Foo(): pass # not string compatible + #self.assertRaises(ValueError, Constant, schema, [ + # (ns.bse.author, Foo())]) + + def test_eq(self): + schema_a = ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''' + schema_b = ''' + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''' + tuples_a = [(ns.bse.author, 'Me, myself, and I')] + tuples_b = [(ns.bse.comment, 'the quick brown fox jumps over the lazy dog.') ] + # distinct instances, same data + self.assertEqual( + Constant(schema_a, tuples_a), + Constant(schema_a, tuples_a)) + self.assertEqual( + hash(Constant(schema_a, tuples_a)), + hash(Constant(schema_a, tuples_a))) + # different data + self.assertNotEqual( + Constant(schema_a, tuples_a), + Constant(schema_b, tuples_b)) + self.assertNotEqual( + hash(Constant(schema_a, tuples_a)), + hash(Constant(schema_b, tuples_b))) + # different objects + class Foo(): pass + self.assertNotEqual(Constant(schema_a, tuples_a), Foo()) + self.assertNotEqual(hash(Constant(schema_a, tuples_a)), hash(Foo())) + self.assertNotEqual(Constant(schema_a, tuples_a), 123) + self.assertNotEqual(hash(Constant(schema_a, tuples_a)), hash(123)) + self.assertNotEqual(Constant(schema_a, tuples_a), None) + self.assertNotEqual(hash(Constant(schema_a, tuples_a)), hash(None)) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/extractor/generic/test_path.py b/test/extractor/generic/test_path.py new file mode 100644 index 0000000..820f402 --- /dev/null +++ b/test/extractor/generic/test_path.py @@ -0,0 +1,74 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsie.base import extractor +from bsie.utils import bsfs, node as _node, ns + +# objects to test +from bsie.extractor.generic.path import Path + + +## code ## + +class TestPath(unittest.TestCase): + def test_eq(self): + # distinct instances, same data + self.assertEqual(Path(), Path()) + # different classes + class Foo(): pass + self.assertNotEqual(Path(), Foo()) + self.assertNotEqual(Path(), 123) + self.assertNotEqual(Path(), None) + + def test_schema(self): + self.assertEqual(Path().schema, + bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + def test_extract(self): + ext = Path() + node = _node.Node(ns.bsfs.File, '') # Blank node + content = '/tmp/foo/bar' + p_filename = ext.schema.predicate(ns.bse.filename) + entity = ext.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Entity) + string = ext.schema.literal(ns.bsfs.Literal).get_child(ns.xsd.string) + + # baseline + self.assertSetEqual(set(ext.extract(node, content, (p_filename, ))), + {(node, p_filename, 'bar')}) + # predicates parameter is respected + p_foo = ext.schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.foo, domain=entity, range=string) # unsupported predicate + self.assertSetEqual(set(ext.extract(node, content, (p_filename, p_foo))), + {(node, p_filename, 'bar')}) + self.assertSetEqual(set(ext.extract(node, content, (p_foo, ))), set()) + # predicates are validated + p_bar = p_foo.get_child(ns.bse.filename) # same URI but different hierarchy + self.assertSetEqual(set(ext.extract(node, content, (p_filename, p_bar))), + {(node, p_filename, 'bar')}) + self.assertSetEqual(set(ext.extract(node, content, (p_bar, ))), set()) + # path variations + self.assertSetEqual(set(ext.extract(node, 'bar', (p_filename, ))), + {(node, p_filename, 'bar')}) + self.assertSetEqual(set(ext.extract(node, '', (p_filename, ))), + {(node, p_filename, '')}) + # errors are suppressed + self.assertSetEqual(set(ext.extract(node, None, (p_filename, ))), set()) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/extractor/generic/test_stat.py b/test/extractor/generic/test_stat.py new file mode 100644 index 0000000..3441438 --- /dev/null +++ b/test/extractor/generic/test_stat.py @@ -0,0 +1,73 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import os +import unittest + +# bsie imports +from bsie.base import extractor +from bsie.utils import bsfs, node as _node, ns + +# objects to test +from bsie.extractor.generic.stat import Stat + + +## code ## + +class TestStat(unittest.TestCase): + def test_eq(self): + # distinct instances, same data + self.assertEqual(Stat(), Stat()) + # different classes + class Foo(): pass + self.assertNotEqual(Stat(), Foo()) + self.assertNotEqual(Stat(), 123) + self.assertNotEqual(Stat(), None) + + def test_schema(self): + self.assertEqual(Stat().schema, + bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + def test_extract(self): + ext = Stat() + node = _node.Node(ns.bsfs.File, '') # Blank node + content = os.stat(__file__) + p_filesize = ext.schema.predicate(ns.bse.filesize) + entity = ext.schema.node(ns.bsfs.Node).get_child(ns.bsfs.Entity) + string = ext.schema.literal(ns.bsfs.Literal).get_child(ns.xsd.string) + + # baseline + self.assertSetEqual(set(ext.extract(node, content, (p_filesize, ))), + {(node, p_filesize, content.st_size)}) + # predicates parameter is respected + p_foo = ext.schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.foo, domain=entity, range=string) # unsupported predicate + self.assertSetEqual(set(ext.extract(node, content, (p_filesize, p_foo))), + {(node, p_filesize, content.st_size)}) + self.assertSetEqual(set(ext.extract(node, content, (p_foo, ))), set()) + # predicates are validated + p_bar = p_foo.get_child(ns.bse.filesizse) # same URI but different hierarchy + self.assertSetEqual(set(ext.extract(node, content, (p_filesize, p_bar))), + {(node, p_filesize, content.st_size)}) + self.assertSetEqual(set(ext.extract(node, content, (p_bar, ))), set()) + # content variations + self.assertSetEqual(set(ext.extract(node, os.stat_result([12345] * len(content)), (p_filesize, p_bar))), + {(node, p_filesize, 12345)}) + # errors are suppressed + self.assertSetEqual(set(ext.extract(node, None, (p_filesize, ))), set()) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/lib/__init__.py b/test/lib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/lib/__init__.py diff --git a/test/lib/test_bsie.py b/test/lib/test_bsie.py new file mode 100644 index 0000000..771a0c2 --- /dev/null +++ b/test/lib/test_bsie.py @@ -0,0 +1,179 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import os +import unittest + +# bsie imports +from bsie.base import extractor +from bsie.tools import builder +from bsie.utils import bsfs, node, ns + +# objects to test +from bsie.lib.bsie import BSIE + + +## code ## + +class TestBSIE(unittest.TestCase): + def setUp(self): + # reader builder + rbuild = builder.ReaderBuilder({}) + # extractor builder + ebuild = builder.ExtractorBuilder([ + {'bsie.extractor.generic.path.Path': {}}, + {'bsie.extractor.generic.stat.Stat': {}}, + {'bsie.extractor.generic.constant.Constant': dict( + tuples=[('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I')], + schema=''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''', + )}, + ]) + # build pipeline + self.prefix = bsfs.Namespace('http://example.com/local/') + pbuild = builder.PipelineBuilder(self.prefix, rbuild, ebuild) + self.pipeline = pbuild.build() + + def test_construction(self): + # pipeline only + lib = BSIE(self.pipeline) + self.assertSetEqual(set(lib.principals), { + ns.bse.filename, + ns.bse.filesize, + ns.bse.author, + }) + self.assertEqual(lib.schema, bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer; + bsfs:unique "false"^^xsd:boolean . + + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''')) + + # specify collect + lib = BSIE(self.pipeline, collect={ + ns.bse.filesize, + ns.bse.author, + ns.bse.inexistent, + }) + self.assertSetEqual(set(lib.principals), { + ns.bse.filesize, + ns.bse.author, + }) + self.assertEqual(lib.schema, bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer; + bsfs:unique "false"^^xsd:boolean . + + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''')) + # empty collect is disregarded + lib = BSIE(self.pipeline, collect={}) + self.assertSetEqual(set(lib.principals), { + ns.bse.filename, + ns.bse.filesize, + ns.bse.author, + }) + self.assertEqual(lib.schema, bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer; + bsfs:unique "false"^^xsd:boolean . + + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + + ''')) + + # specify discard + lib = BSIE(self.pipeline, discard={ + ns.bse.filesize, + ns.bse.filename, + ns.bse.inexistent, + }) + self.assertSetEqual(set(lib.principals), { + ns.bse.author, + }) + self.assertEqual(lib.schema, bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''')) + + # specify collect and discard + lib = BSIE(self.pipeline, + collect={ns.bse.filesize, ns.bse.author, ns.bse.foo, ns.bse.bar}, + discard={ns.bse.author, ns.bse.foo, ns.bse.foobar}, + ) + self.assertSetEqual(set(lib.principals), { + ns.bse.filesize, + }) + self.assertEqual(lib.schema, bsfs.schema.Schema.from_string(extractor.SCHEMA_PREAMBLE + ''' + bse:filesize rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer; + bsfs:unique "false"^^xsd:boolean . + + ''')) + + + def test_from_file(self): + # setup + lib = BSIE(self.pipeline) + self.assertSetEqual(set(lib.principals), { + ns.bse.filesize, + ns.bse.filename, + ns.bse.author, + }) + content_hash = 'a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447' + subject = node.Node(ns.bsfs.File, (self.prefix + 'file#')[content_hash]) + testfile = os.path.join(os.path.dirname(__file__), 'testfile.t') + + # from_file extracts all available triples + self.assertSetEqual(set(lib.from_file(testfile)), { + (subject, lib.schema.predicate(ns.bse.filename), 'testfile.t'), + (subject, lib.schema.predicate(ns.bse.filesize), 12), + (subject, lib.schema.predicate(ns.bse.author), 'Me, myself, and I'), + }) + + # from_file respects predicate argument + self.assertSetEqual(set(lib.from_file(testfile, {ns.bse.filename, ns.bse.invalid})), { + (subject, lib.schema.predicate(ns.bse.filename), 'testfile.t'), + }) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/lib/testfile.t b/test/lib/testfile.t new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/test/lib/testfile.t @@ -0,0 +1 @@ +hello world diff --git a/test/reader/__init__.py b/test/reader/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/reader/__init__.py diff --git a/test/reader/test_path.py b/test/reader/test_path.py new file mode 100644 index 0000000..fd7bc5a --- /dev/null +++ b/test/reader/test_path.py @@ -0,0 +1,28 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# objects to test +from bsie.reader.path import Path + + +## code ## + +class TestPath(unittest.TestCase): + def test_call(self): + self.assertEqual('', Path()('')) + self.assertEqual('/tmp/foo/bar', Path()('/tmp/foo/bar')) + self.assertEqual('/home/myself/some file', Path()('/home/myself/some file')) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/test_stat.py b/test/reader/test_stat.py new file mode 100644 index 0000000..d12ad9c --- /dev/null +++ b/test/reader/test_stat.py @@ -0,0 +1,34 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import os +import unittest + +# bsie imports +from bsie.base import errors + +# objects to test +from bsie.reader.stat import Stat + + +## code ## + +class TestPath(unittest.TestCase): + def test_call(self): + # test self + self.assertEqual(os.stat(__file__), Stat()(__file__)) + # test invalid file + self.assertRaises(errors.ReaderError, Stat(), '') + self.assertRaises(errors.ReaderError, Stat(), None) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/tools/__init__.py b/test/tools/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/tools/__init__.py diff --git a/test/tools/test_builder.py b/test/tools/test_builder.py new file mode 100644 index 0000000..62c637c --- /dev/null +++ b/test/tools/test_builder.py @@ -0,0 +1,246 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import logging +import unittest + +# bsie imports +from bsie import base +from bsie.utils import bsfs + +# objects to test +from bsie.tools.builder import ExtractorBuilder +from bsie.tools.builder import PipelineBuilder +from bsie.tools.builder import ReaderBuilder +from bsie.tools.builder import _safe_load +from bsie.tools.builder import _unpack_name + + +## code ## + +class TestUtils(unittest.TestCase): + def test_safe_load(self): + # invalid module + self.assertRaises(base.errors.LoaderError, _safe_load, 'dBGHMSAYOoKeKMpywDoKZQycENFPvN', 'foobar') + self.assertRaises(base.errors.LoaderError, _safe_load, 'dBGHMSAYOoKeKMpywDoKZQycENFPvN.bar', 'foobar') + # partially valid module + self.assertRaises(base.errors.LoaderError, _safe_load, 'os.foo', 'foobar') + # invalid class + self.assertRaises(base.errors.LoaderError, _safe_load, 'os.path', 'foo') + # valid module and class + cls = _safe_load('collections.abc', 'Container') + import collections.abc + self.assertEqual(cls, collections.abc.Container) + + def test_unpack_name(self): + self.assertRaises(TypeError, _unpack_name, 123) + self.assertRaises(TypeError, _unpack_name, None) + self.assertRaises(ValueError, _unpack_name, '') + self.assertRaises(ValueError, _unpack_name, 'path') + self.assertRaises(ValueError, _unpack_name, '.Path') + self.assertEqual(_unpack_name('path.Path'), ('path', 'Path')) + self.assertEqual(_unpack_name('path.foo.bar.Path'), ('path.foo.bar', 'Path')) + + +class TestReaderBuilder(unittest.TestCase): + def test_build(self): + builder = ReaderBuilder({'bsie.reader.path.Path': {}}) + # build configured reader + cls = builder.build('bsie.reader.path.Path') + import bsie.reader.path + self.assertIsInstance(cls, bsie.reader.path.Path) + # build unconfigured reader + cls = builder.build('bsie.reader.stat.Stat') + import bsie.reader.stat + self.assertIsInstance(cls, bsie.reader.stat.Stat) + # re-build previous reader (test cache) + self.assertEqual(cls, builder.build('bsie.reader.stat.Stat')) + # test invalid + self.assertRaises(TypeError, builder.build, 123) + self.assertRaises(TypeError, builder.build, None) + self.assertRaises(ValueError, builder.build, '') + self.assertRaises(ValueError, builder.build, 'Path') + self.assertRaises(base.errors.BuilderError, builder.build, 'path.Path') + # invalid config + builder = ReaderBuilder({'bsie.reader.stat.Stat': dict(foo=123)}) + self.assertRaises(base.errors.BuilderError, builder.build, 'bsie.reader.stat.Stat') + builder = ReaderBuilder({'bsie.reader.stat.Stat': 123}) + self.assertRaises(TypeError, builder.build, 'bsie.reader.stat.Stat') + # no instructions + builder = ReaderBuilder({}) + cls = builder.build('bsie.reader.stat.Stat') + self.assertIsInstance(cls, bsie.reader.stat.Stat) + + + +class TestExtractorBuilder(unittest.TestCase): + def test_iter(self): + # no specifications + self.assertListEqual(list(ExtractorBuilder([])), []) + # some specifications + builder = ExtractorBuilder([ + {'bsie.extractor.generic.path.Path': {}}, + {'bsie.extractor.generic.stat.Stat': {}}, + {'bsie.extractor.generic.path.Path': {}}, + ]) + self.assertListEqual(list(builder), [0, 1, 2]) + + def test_build(self): + # simple and repeated extractors + builder = ExtractorBuilder([ + {'bsie.extractor.generic.path.Path': {}}, + {'bsie.extractor.generic.stat.Stat': {}}, + {'bsie.extractor.generic.path.Path': {}}, + ]) + ext = [builder.build(0), builder.build(1), builder.build(2)] + import bsie.extractor.generic.path + import bsie.extractor.generic.stat + self.assertListEqual(ext, [ + bsie.extractor.generic.path.Path(), + bsie.extractor.generic.stat.Stat(), + bsie.extractor.generic.path.Path(), + ]) + # out-of-bounds raises KeyError + self.assertRaises(IndexError, builder.build, 3) + + # building with args + builder = ExtractorBuilder([ + {'bsie.extractor.generic.constant.Constant': { + 'schema': ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + bse:rating rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:integer ; + bsfs:unique "true"^^xsd:boolean . + ''', + 'tuples': [ + ('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I'), + ('http://bsfs.ai/schema/Entity#rating', 123), + ], + }}]) + obj = builder.build(0) + import bsie.extractor.generic.constant + self.assertEqual(obj, bsie.extractor.generic.constant.Constant(''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + bse:rating rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:integer ; + bsfs:unique "true"^^xsd:boolean . + ''', [ + ('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I'), + ('http://bsfs.ai/schema/Entity#rating', 123), + ])) + + # building with invalid args + self.assertRaises(base.errors.BuilderError, ExtractorBuilder( + [{'bsie.extractor.generic.path.Path': {'foo': 123}}]).build, 0) + # non-dict build specification + self.assertRaises(TypeError, ExtractorBuilder( + [('bsie.extractor.generic.path.Path', {})]).build, 0) + # multiple keys per build specification + self.assertRaises(TypeError, ExtractorBuilder( + [{'bsie.extractor.generic.path.Path': {}, + 'bsie.extractor.generic.stat.Stat': {}}]).build, 0) + # non-dict value for kwargs + self.assertRaises(TypeError, ExtractorBuilder( + [{'bsie.extractor.generic.path.Path': 123}]).build, 0) + + + + +class TestPipelineBuilder(unittest.TestCase): + def test_build(self): + prefix = bsfs.URI('http://example.com/local/file#') + c_schema = ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''' + c_tuples = [('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I')] + # prepare builders + rbuild = ReaderBuilder({}) + ebuild = ExtractorBuilder([ + {'bsie.extractor.generic.path.Path': {}}, + {'bsie.extractor.generic.stat.Stat': {}}, + {'bsie.extractor.generic.constant.Constant': dict( + schema=c_schema, + tuples=c_tuples, + )}, + ]) + # build pipeline + builder = PipelineBuilder(prefix, rbuild, ebuild) + pipeline = builder.build() + # delayed import + import bsie.reader.path + import bsie.reader.stat + import bsie.extractor.generic.path + import bsie.extractor.generic.stat + import bsie.extractor.generic.constant + # check pipeline + self.assertDictEqual(pipeline._ext2rdr, { + bsie.extractor.generic.path.Path(): bsie.reader.path.Path(), + bsie.extractor.generic.stat.Stat(): bsie.reader.stat.Stat(), + bsie.extractor.generic.constant.Constant(c_schema, c_tuples): None, + }) + + # fail to load extractor + ebuild_err = ExtractorBuilder([ + {'bsie.extractor.generic.foo.Foo': {}}, + {'bsie.extractor.generic.path.Path': {}}, + ]) + with self.assertLogs(logging.getLogger('bsie.tools.builder'), logging.ERROR): + pipeline = PipelineBuilder(prefix, rbuild, ebuild_err).build() + self.assertDictEqual(pipeline._ext2rdr, { + bsie.extractor.generic.path.Path(): bsie.reader.path.Path()}) + + # fail to build extractor + ebuild_err = ExtractorBuilder([ + {'bsie.extractor.generic.path.Path': {'foo': 123}}, + {'bsie.extractor.generic.path.Path': {}}, + ]) + with self.assertLogs(logging.getLogger('bsie.tools.builder'), logging.ERROR): + pipeline = PipelineBuilder(prefix, rbuild, ebuild_err).build() + self.assertDictEqual(pipeline._ext2rdr, { + bsie.extractor.generic.path.Path(): bsie.reader.path.Path()}) + + # fail to load reader + with self.assertLogs(logging.getLogger('bsie.tools.builder'), logging.ERROR): + # switch reader of an extractor + old_reader = bsie.extractor.generic.path.Path.CONTENT_READER + bsie.extractor.generic.path.Path.CONTENT_READER = 'bsie.reader.foo.Foo' + # build pipeline with invalid reader reference + pipeline = PipelineBuilder(prefix, rbuild, ebuild).build() + self.assertDictEqual(pipeline._ext2rdr, { + bsie.extractor.generic.stat.Stat(): bsie.reader.stat.Stat(), + bsie.extractor.generic.constant.Constant(c_schema, c_tuples): None, + }) + # switch back + bsie.extractor.generic.path.Path.CONTENT_READER = old_reader + + # fail to build reader + rbuild_err = ReaderBuilder({'bsie.reader.stat.Stat': dict(foo=123)}) + with self.assertLogs(logging.getLogger('bsie.tools.builder'), logging.ERROR): + pipeline = PipelineBuilder(prefix, rbuild_err, ebuild).build() + self.assertDictEqual(pipeline._ext2rdr, { + bsie.extractor.generic.path.Path(): bsie.reader.path.Path(), + bsie.extractor.generic.constant.Constant(c_schema, c_tuples): None, + }) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/tools/test_pipeline.py b/test/tools/test_pipeline.py new file mode 100644 index 0000000..a116a30 --- /dev/null +++ b/test/tools/test_pipeline.py @@ -0,0 +1,176 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import logging +import os +import unittest + +# bsie imports +from bsie.base import errors +from bsie.utils import bsfs, node, ns +import bsie.extractor.generic.constant +import bsie.extractor.generic.path +import bsie.extractor.generic.stat +import bsie.reader.path +import bsie.reader.stat + +# objects to test +from bsie.tools.pipeline import Pipeline + + +## code ## + +class TestPipeline(unittest.TestCase): + def setUp(self): + # constant A + csA = ''' + bse:author rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:string ; + bsfs:unique "true"^^xsd:boolean . + ''' + tupA = [('http://bsfs.ai/schema/Entity#author', 'Me, myself, and I')] + # constant B + csB = ''' + bse:rating rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:File ; + rdfs:range xsd:integer ; + bsfs:unique "true"^^xsd:boolean . + ''' + tupB = [('http://bsfs.ai/schema/Entity#rating', 123)] + # extractors/readers + self.ext2rdr = { + bsie.extractor.generic.path.Path(): bsie.reader.path.Path(), + bsie.extractor.generic.stat.Stat(): bsie.reader.stat.Stat(), + bsie.extractor.generic.constant.Constant(csA, tupA): None, + bsie.extractor.generic.constant.Constant(csB, tupB): None, + } + self.prefix = bsfs.Namespace('http://example.com/local/') + + def test_essentials(self): + pipeline = Pipeline(self.prefix, self.ext2rdr) + self.assertEqual(str(pipeline), 'Pipeline') + self.assertEqual(repr(pipeline), 'Pipeline(...)') + + def test_equality(self): + pipeline = Pipeline(self.prefix, self.ext2rdr) + # a pipeline is equivalent to itself + self.assertEqual(pipeline, pipeline) + self.assertEqual(hash(pipeline), hash(pipeline)) + # identical builds are equivalent + self.assertEqual(pipeline, Pipeline(self.prefix, self.ext2rdr)) + self.assertEqual(hash(pipeline), hash(Pipeline(self.prefix, self.ext2rdr))) + + # equivalence respects prefix + self.assertNotEqual(pipeline, Pipeline(bsfs.URI('http://example.com/global/ent#'), self.ext2rdr)) + self.assertNotEqual(hash(pipeline), hash(Pipeline(bsfs.URI('http://example.com/global/ent#'), self.ext2rdr))) + # equivalence respects extractors/readers + ext2rdr = {ext: rdr for idx, (ext, rdr) in enumerate(self.ext2rdr.items()) if idx % 2 == 0} + self.assertNotEqual(pipeline, Pipeline(self.prefix, ext2rdr)) + self.assertNotEqual(hash(pipeline), hash(Pipeline(self.prefix, ext2rdr))) + + # equivalence respects schema + p2 = Pipeline(self.prefix, self.ext2rdr) + p2._schema = pipeline.schema.Empty() + self.assertNotEqual(pipeline, p2) + self.assertNotEqual(hash(pipeline), hash(p2)) + + # not equal to other types + class Foo(): pass + self.assertNotEqual(pipeline, Foo()) + self.assertNotEqual(hash(pipeline), hash(Foo())) + self.assertNotEqual(pipeline, 123) + self.assertNotEqual(hash(pipeline), hash(123)) + self.assertNotEqual(pipeline, None) + self.assertNotEqual(hash(pipeline), hash(None)) + + + def test_call(self): + # build pipeline + pipeline = Pipeline(self.prefix, self.ext2rdr) + # build objects for tests + content_hash = 'a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447' + subject = node.Node(ns.bsfs.File, (self.prefix + 'file#')[content_hash]) + testfile = os.path.join(os.path.dirname(__file__), 'testfile.t') + p_filename = pipeline.schema.predicate(ns.bse.filename) + p_filesize = pipeline.schema.predicate(ns.bse.filesize) + p_author = pipeline.schema.predicate(ns.bse.author) + p_rating = pipeline.schema.predicate(ns.bse.rating) + entity = pipeline.schema.node(ns.bsfs.File) + p_invalid = pipeline.schema.predicate(ns.bsfs.Predicate).get_child(ns.bse.foo, range=entity) + + # extract given predicates + self.assertSetEqual(set(pipeline(testfile, {p_filename, p_filesize})), { + (subject, p_filename, 'testfile.t'), + (subject, p_filesize, 12), + }) + self.assertSetEqual(set(pipeline(testfile, {p_author})), { + (subject, p_author, 'Me, myself, and I'), + }) + self.assertSetEqual(set(pipeline(testfile, {p_filename})), { + (subject, p_filename, 'testfile.t'), + }) + self.assertSetEqual(set(pipeline(testfile, {p_filesize})), { + (subject, p_filesize, 12), + }) + # extract all predicates + self.assertSetEqual(set(pipeline(testfile)), { + (subject, p_filename, 'testfile.t'), + (subject, p_filesize, 12), + (subject, p_author, 'Me, myself, and I'), + (subject, p_rating, 123), + }) + # invalid predicate + self.assertSetEqual(set(pipeline(testfile, {p_invalid})), set()) + # valid/invalid predicates mixed + self.assertSetEqual(set(pipeline(testfile, {p_filename, p_invalid})), { + (subject, p_filename, 'testfile.t'), + }) + # invalid path + self.assertRaises(FileNotFoundError, list, pipeline('inexistent_file')) + # FIXME: unreadable file (e.g. permissions error) + + def test_call_reader_err(self): + class FaultyReader(bsie.reader.path.Path): + def __call__(self, path): + raise errors.ReaderError('reader error') + + pipeline = Pipeline(self.prefix, {bsie.extractor.generic.path.Path(): FaultyReader()}) + with self.assertLogs(logging.getLogger('bsie.tools.pipeline'), logging.ERROR): + testfile = os.path.join(os.path.dirname(__file__), 'testfile.t') + p_filename = pipeline.schema.predicate(ns.bse.filename) + self.assertSetEqual(set(pipeline(testfile, {p_filename})), set()) + + def test_call_extractor_err(self): + class FaultyExtractor(bsie.extractor.generic.path.Path): + def extract(self, subject, content, predicates): + raise errors.ExtractorError('extractor error') + + pipeline = Pipeline(self.prefix, {FaultyExtractor(): bsie.reader.path.Path()}) + with self.assertLogs(logging.getLogger('bsie.tools.pipeline'), logging.ERROR): + testfile = os.path.join(os.path.dirname(__file__), 'testfile.t') + p_filename = pipeline.schema.predicate(ns.bse.filename) + self.assertSetEqual(set(pipeline(testfile, {p_filename})), set()) + + def test_predicates(self): + # build pipeline + pipeline = Pipeline(self.prefix, self.ext2rdr) + # + self.assertSetEqual(set(pipeline.principals), { + pipeline.schema.predicate(ns.bse.filename), + pipeline.schema.predicate(ns.bse.filesize), + pipeline.schema.predicate(ns.bse.author), + pipeline.schema.predicate(ns.bse.rating), + }) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/tools/testfile.t b/test/tools/testfile.t new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/test/tools/testfile.t @@ -0,0 +1 @@ +hello world diff --git a/test/utils/__init__.py b/test/utils/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/utils/__init__.py diff --git a/test/utils/test_node.py b/test/utils/test_node.py new file mode 100644 index 0000000..c70f0b8 --- /dev/null +++ b/test/utils/test_node.py @@ -0,0 +1,65 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsie.utils import bsfs, ns + +# objects to test +from bsie.utils.node import Node + + +## code ## + +class TestNode(unittest.TestCase): + def test_equality(self): + uri = bsfs.URI('http://example.com/me/entity#1234') + node = Node(ns.bsfs.Entity, uri) + # basic equivalence + self.assertEqual(node, Node(ns.bsfs.Entity, bsfs.URI('http://example.com/me/entity#1234'))) + self.assertEqual(hash(node), hash(Node(ns.bsfs.Entity, bsfs.URI('http://example.com/me/entity#1234')))) + # equality respects uri + self.assertNotEqual(node, Node(ns.bsfs.Entity, bsfs.URI('http://example.com/me/entity#4321'))) + self.assertNotEqual(hash(node), hash(Node(ns.bsfs.Entity, bsfs.URI('http://example.com/me/entity#4321')))) + # equality respects node_type + self.assertNotEqual(node, Node(ns.bsfs.Foo, uri)) + self.assertNotEqual(hash(node), hash(Node(ns.bsfs.Foo, uri))) + # not equal to other types + self.assertNotEqual(node, 1234) + self.assertNotEqual(hash(node), hash(1234)) + self.assertNotEqual(node, uri) + self.assertNotEqual(hash(node), hash(uri)) + self.assertNotEqual(node, ns.bsfs.Entity) + self.assertNotEqual(hash(node), hash(ns.bsfs.Entity)) + class Foo(): pass + self.assertNotEqual(node, Foo()) + self.assertNotEqual(hash(node), hash(Foo())) + + def test_str(self): + uri = bsfs.URI('http://example.com/me/entity#1234') + # basic string conversion + node = Node(ns.bsfs.Entity, uri) + self.assertEqual(str(node), 'Node(http://bsfs.ai/schema/Entity, http://example.com/me/entity#1234)') + self.assertEqual(repr(node), 'Node(http://bsfs.ai/schema/Entity, http://example.com/me/entity#1234)') + # string conversion respects node_type + node = Node(ns.bsfs.Foo, uri) + self.assertEqual(str(node), 'Node(http://bsfs.ai/schema/Foo, http://example.com/me/entity#1234)') + self.assertEqual(repr(node), 'Node(http://bsfs.ai/schema/Foo, http://example.com/me/entity#1234)') + # string conversion respects uri + node = Node(ns.bsfs.Entity, bsfs.URI('http://example.com/me/entity#4321')) + self.assertEqual(str(node), 'Node(http://bsfs.ai/schema/Entity, http://example.com/me/entity#4321)') + self.assertEqual(repr(node), 'Node(http://bsfs.ai/schema/Entity, http://example.com/me/entity#4321)') + + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## |