import gi from chrysacase import ChrysalideTestCase from gi.repository import GObject from pychrysalide.glibext import HashableObject class TestStringBuilder(ChrysalideTestCase): """Test cases for pychrysalide.glibext.HashableObject.""" def testHashableObjectCreation(self): """Create objects with HashableObject interface.""" with self.assertRaisesRegex(NotImplementedError, 'HashableObject can not be constructed'): ho = HashableObject() class NewHashableObjectImplem(gi._gi.GObject, HashableObject): pass nho = NewHashableObjectImplem() self.assertIsNotNone(nho) class NewHashableObjectImplem2(GObject.Object, HashableObject): pass nho2 = NewHashableObjectImplem() self.assertIsNotNone(nho2) def testHashableObjectMethods(self): """Test the HashableObject methods.""" class BasicHashableObjectImplem(gi._gi.GObject, HashableObject): def __init__(self, val): super().__init__() self._val = val def _hash(self): return self._val value = 1234 ho = BasicHashableObjectImplem(value) self.assertEqual(hash(ho), value) class BasicHashableObjectImplem2(GObject.Object, HashableObject): def __init__(self, val): super().__init__() self._val = val def _hash(self): return self._val value = 5678 ho2 = BasicHashableObjectImplem2(value) self.assertEqual(hash(ho2), value) def testCascadingHashableObjectImplementations(self): """Request the hash from the object parent for a full computing.""" class CascadingHashableObjectFullImplemA(GObject.Object, HashableObject): def _hash(self): return 1 class CascadingHashableObjectFullImplemB(CascadingHashableObjectFullImplemA, HashableObject): def _hash(self): return super()._hash() * 2 class CascadingHashableObjectFullImplemC(CascadingHashableObjectFullImplemB, HashableObject): def _hash(self): return super()._hash() * 3 obj_a = CascadingHashableObjectFullImplemA() obj_b = CascadingHashableObjectFullImplemB() obj_c = CascadingHashableObjectFullImplemC() self.assertEqual(hash(obj_a), 1) self.assertEqual(hash(obj_b), 2) self.assertEqual(hash(obj_c), 6) class CascadingHashableObjectPartialImplemA(GObject.Object, HashableObject): def _hash(self): return 1 class CascadingHashableObjectPartialImplemB(CascadingHashableObjectPartialImplemA): pass class CascadingHashableObjectPartialImplemC(CascadingHashableObjectPartialImplemB, HashableObject): def _hash(self): return super()._hash() * 3 obj_a = CascadingHashableObjectPartialImplemA() obj_b = CascadingHashableObjectPartialImplemB() obj_c = CascadingHashableObjectPartialImplemC() self.assertEqual(hash(obj_a), 1) self.assertEqual(hash(obj_b), 1) self.assertEqual(hash(obj_c), 3) def testHashableObjectExceptions(self): """Raise exceptions from the HashableObject interface as expected.""" class BadHashableObjectImplem(GObject.Object, HashableObject): pass obj = BadHashableObjectImplem() with self.assertRaisesRegex(NotImplementedError, "method implementation is missing for '_hash'"): h = hash(obj) with self.assertRaisesRegex(TypeError, 'object parent does not implement the HashableObject interface'): h = obj.parent_hash() class BadHashableObjectImplem2(GObject.Object, HashableObject): def _hash(self): return 'AAA' obj2 = BadHashableObjectImplem2() with self.assertRaisesRegex(TypeError, 'computed hash value has to be an unsigned integer'): h = hash(obj2) class BadHashableObjectImplem3a(GObject.Object, HashableObject): def _hash(self): return 123 class BadHashableObjectImplem3b(BadHashableObjectImplem3a, HashableObject): def _hash(self): return self.parent_hash() obj3 = BadHashableObjectImplem3b() with self.assertRaisesRegex(RuntimeError, 'object parent is not a native type'): h = hash(obj3) class BadHashableObjectImplem4(GObject.Object, HashableObject): def _hash(self): raise Exception('error') obj4 = BadHashableObjectImplem4() with self.assertRaisesRegex(Exception, 'error'): h = hash(obj4)