diff options
Diffstat (limited to 'test/schema/test_types.py')
-rw-r--r-- | test/schema/test_types.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/test/schema/test_types.py b/test/schema/test_types.py new file mode 100644 index 0000000..4a49e6e --- /dev/null +++ b/test/schema/test_types.py @@ -0,0 +1,225 @@ +""" + +Part of the tagit test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import operator +import unittest + +# bsfs imports +from bsfs.namespace import ns +from bsfs.utils import errors + +# objects to test +from bsfs.schema.types import _Type, _Vertex, Node, Literal, Predicate + + +## code ## + +class TestType(unittest.TestCase): + def test_parents(self): + # create some types + fst = _Type('First') + snd = _Type('Second', fst) + trd = _Type('Third', snd) + frd = _Type('Fourth', trd) + # check parents + self.assertListEqual(list(fst.parents()), []) + self.assertListEqual(list(snd.parents()), [fst]) + self.assertListEqual(list(trd.parents()), [snd, fst]) + self.assertListEqual(list(frd.parents()), [trd, snd, fst]) + + def test_essentials(self): + # type w/o parent + self.assertEqual(str(_Type('Foo')), '_Type(Foo)') + self.assertEqual(repr(_Type('Foo')), '_Type(Foo, None)') + # type w/ parent + self.assertEqual(str(_Type('Foo', _Type('Bar'))), '_Type(Foo)') + self.assertEqual(repr(_Type('Foo', _Type('Bar'))), '_Type(Foo, _Type(Bar, None))') + # subtype w/o parent + class SubType(_Type): pass + self.assertEqual(str(SubType('Foo')), 'SubType(Foo)') + self.assertEqual(repr(SubType('Foo')), 'SubType(Foo, None)') + # subtype w/ parent + self.assertEqual(str(SubType('Foo', SubType('Bar'))), 'SubType(Foo)') + self.assertEqual(repr(SubType('Foo', SubType('Bar'))), 'SubType(Foo, SubType(Bar, None))') + # subtype and type mixed + self.assertEqual(str(SubType('Foo', _Type('Bar'))), 'SubType(Foo)') + self.assertEqual(repr(SubType('Foo', _Type('Bar'))), 'SubType(Foo, _Type(Bar, None))') + self.assertEqual(str(_Type('Foo', SubType('Bar'))), '_Type(Foo)') + self.assertEqual(repr(_Type('Foo', SubType('Bar'))), '_Type(Foo, SubType(Bar, None))') + + def test_get_child(self): + # callee is used as parent + self.assertEqual(_Type('First').get_child('Second'), _Type('Second', _Type('First'))) + # works with multiple parents + self.assertEqual(_Type('First').get_child('Second').get_child('Third'), _Type('Third', _Type('Second', _Type('First')))) + # type persists + class Foo(_Type): pass + self.assertEqual(Foo('First').get_child('Second'), Foo('Second', Foo('First'))) + + def test_equality(self): + # equality depends on uri + self.assertEqual(_Type('Foo'), _Type('Foo')) + self.assertEqual(hash(_Type('Foo')), hash(_Type('Foo'))) + self.assertNotEqual(_Type('Foo'), _Type('Bar')) + self.assertNotEqual(hash(_Type('Foo')), hash(_Type('Bar'))) + # comparison is case-sensitive + self.assertNotEqual(_Type('FOO'), _Type('foo')) + self.assertNotEqual(hash(_Type('FOO')), hash(_Type('foo'))) + # comparison respects type + class Foo(_Type): pass + self.assertNotEqual(_Type('Foo'), Foo('Foo')) + self.assertNotEqual(hash(_Type('Foo')), hash(Foo('Foo'))) + # comparison respects parent + self.assertNotEqual(_Type('Foo', _Type('Bar')), _Type('Foo')) + self.assertNotEqual(hash(_Type('Foo', _Type('Bar'))), hash(_Type('Foo'))) + + def test_order(self): + # create some types. + vehicle = _Type('Vehicle') + twowheel = _Type('Two-wheel', vehicle) + bike = _Type('Bike', twowheel) + bicycle = _Type('Bicycle', twowheel) + # two-wheel is equivalent to itself + self.assertFalse(twowheel == vehicle) + self.assertTrue(twowheel == twowheel) + self.assertFalse(twowheel == bicycle) + # two-wheel is a true subclass of Vehicle + self.assertTrue(twowheel < vehicle) + self.assertFalse(twowheel < twowheel) + self.assertFalse(twowheel < bicycle) + # two-wheel is a subclass of itself and Vehicle + self.assertTrue(twowheel <= vehicle) + self.assertTrue(twowheel <= twowheel) + self.assertFalse(twowheel <= bicycle) + # two-wheel is a true superclass of Bicycle + self.assertFalse(twowheel > vehicle) + self.assertFalse(twowheel > twowheel) + self.assertTrue(twowheel > bicycle) + # two-wheel is a superclass of itself and Bicycle + self.assertFalse(twowheel >= vehicle) + self.assertTrue(twowheel >= twowheel) + self.assertTrue(twowheel >= bicycle) + # analoguous to sets, this is not a total order + self.assertFalse(bike <= bicycle) + self.assertFalse(bike < bicycle) + self.assertFalse(bike > bicycle) + self.assertFalse(bike >= bicycle) + self.assertFalse(bike == bicycle) + class Foo(_Type): pass + foo = Foo(bike.uri, bike.parent) + # cannot compare different types + self.assertRaises(TypeError, operator.lt, foo, bike) + self.assertRaises(TypeError, operator.le, foo, bike) + self.assertRaises(TypeError, operator.gt, foo, bike) + self.assertRaises(TypeError, operator.ge, foo, bike) + # goes both ways + self.assertRaises(TypeError, operator.lt, bike, foo) + self.assertRaises(TypeError, operator.le, bike, foo) + self.assertRaises(TypeError, operator.gt, bike, foo) + self.assertRaises(TypeError, operator.ge, bike, foo) + +class TestPredicate(unittest.TestCase): + def test_construction(self): + # domain must be a node + self.assertRaises(TypeError, Predicate, ns.bse.foo, 1234, None, True) + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Literal(ns.bsfs.Foo, None), None, True) + # range must be None, a Literal, or a Node + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), 1234, True) + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Vertex(ns.bsfs.Foo, None), True) + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Type(ns.bsfs.Foo, None), True) + class Foo(): pass + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), Foo(), True) + + def test_equality(self): + n_root = Node(ns.bsfs.Node, None) + n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) + n_tag = Node(ns.bsfs.Tag, Node(ns.bsfs.Tag, None)) + root = Predicate( + uri=ns.bsfs.Predicate, + parent=None, + domain=n_root, + range=None, + unique=False, + ) + # instance is equal to itself + self.assertEqual(root, root) + self.assertEqual(hash(root), hash(root)) + # instance is equal to a clone + self.assertEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, None, False)) + self.assertEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, None, False))) + # equality respects uri + self.assertNotEqual(root, Predicate(ns.bsfs.Alternative, None, n_root, None, False)) + self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Alternative, None, n_root, None, False))) + # equality respects parent + self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, n_root, n_root, None, False)) + self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, n_root, n_root, None, False))) + # equality respects domain + self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_ent, None, False)) + self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_ent, None, False))) + # equality respects range + self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, n_root, False)) + self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, n_root, False))) + # equality respects unique + self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, None, True)) + self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, None, True))) + + def test_get_child(self): + n_root = Node(ns.bsfs.Node, None) + n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) + n_tag = Node(ns.bsfs.Tag, Node(ns.bsfs.Tag, None)) + root = Predicate( + uri=ns.bsfs.Predicate, + parent=None, + domain=n_root, + range=None, + unique=False, + ) + tag = Predicate( + uri=ns.bsfs.Entity, + parent=root, + domain=n_ent, + range=n_tag, + unique=False, + ) + + # uri is respected + self.assertEqual(ns.bse.foo, tag.get_child(ns.bse.foo).uri) + # domain is respected + dom = Node(ns.bsfs.Image, n_ent) + self.assertEqual(dom, tag.get_child(ns.bse.foo, domain=dom).domain) + # range is respected + rng = Node(ns.bsfs.Group, n_tag) + self.assertEqual(rng, tag.get_child(ns.bse.foo, range=rng).range) + # cannot set range to None + self.assertEqual(n_tag, tag.get_child(ns.bse.foo, range=None).range) + # unique is respected + self.assertTrue(tag.get_child(ns.bse.foo, unique=True).unique) + + # domain is inherited from parent + self.assertEqual(n_ent, tag.get_child(ns.bse.foo).domain) + # range is inherited from parent + self.assertEqual(n_tag, tag.get_child(ns.bse.foo).range) + # uniqueness is inherited from parent + self.assertFalse(tag.get_child(ns.bse.foo).unique) + + # domain must be subtype of parent's domain + self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=n_root) + self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) + # range cannot be None + self.assertRaises(ValueError, root.get_child, ns.bse.foo) + # range must be subtype of parent's range + self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=n_root) + self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=Node(ns.bsfs.Image, n_root)) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## + |