def setUp(self): NeoUnitTestBase.setUp(self) self.app = Mock() # no history self.app.dm = Mock({'getObjectHistory': []}) self.app.pt = Mock({'isAssigned': True, 'getPartitions': 2}) self.app.em = Mock({'setTimeout': None}) self.manager = TransactionManager(self.app)
def setUp(self): NeoUnitTestBase.setUp(self) self.app = Mock() # no history self.app.dm = Mock({'getObjectHistory': []}) self.app.pt = Mock({'isAssigned': True}) self.app.em = Mock({'setTimeout': None}) self.manager = TransactionManager(self.app) self.ltid = None
class TransactionManagerTests(NeoUnitTestBase): def setUp(self): NeoUnitTestBase.setUp(self) self.app = Mock() # no history self.app.dm = Mock({'getObjectHistory': []}) self.app.pt = Mock({'isAssigned': True, 'getPartitions': 2}) self.app.em = Mock({'setTimeout': None}) self.manager = TransactionManager(self.app) def register(self, uuid, ttid): self.manager.register(Mock({'getUUID': uuid}), ttid) def test_updateObjectDataForPack(self): ram_serial = self.getNextTID() oid = p64(1) orig_serial = self.getNextTID() uuid = self.getClientUUID() locking_serial = self.getNextTID() other_serial = self.getNextTID() new_serial = self.getNextTID() checksum = "2" * 20 self.register(uuid, locking_serial) # Object not known, nothing happens self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), None) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), None) self.manager.abort(locking_serial, even_if_locked=True) # Object known, but doesn't point at orig_serial, it is not updated self.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, 0, "3" * 20, 'bar', None) holdData = self.app.dm.mockGetNamedCalls('holdData') self.assertEqual(holdData.pop(0).params, ("3" * 20, oid, 'bar', 0)) orig_object = self.manager.getObjectFromTransaction( locking_serial, oid) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), orig_object) self.manager.abort(locking_serial, even_if_locked=True) self.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, other_serial) orig_object = self.manager.getObjectFromTransaction( locking_serial, oid) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), orig_object) self.manager.abort(locking_serial, even_if_locked=True) # Object known and points at undone data it gets updated self.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, orig_serial) self.manager.updateObjectDataForPack(oid, orig_serial, new_serial, checksum) self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), (oid, None, new_serial)) self.manager.abort(locking_serial, even_if_locked=True) self.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, orig_serial) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual(holdData.pop(0).params, (checksum, )) self.assertEqual( self.manager.getObjectFromTransaction(locking_serial, oid), (oid, checksum, None)) self.manager.abort(locking_serial, even_if_locked=True) self.assertFalse(holdData)
class TransactionManagerTests(NeoUnitTestBase): def setUp(self): NeoUnitTestBase.setUp(self) self.app = Mock() # no history self.app.dm = Mock({'getObjectHistory': []}) self.app.pt = Mock({'isAssigned': True}) self.app.em = Mock({'setTimeout': None}) self.manager = TransactionManager(self.app) self.ltid = None def _getTransaction(self): tid = self.getNextTID(self.ltid) oid_list = [self.getOID(1), self.getOID(2)] return (tid, ('USER', 'DESC', 'EXT', oid_list)) def _storeTransactionObjects(self, tid, txn): for i, oid in enumerate(txn[3]): self.manager.storeObject(tid, None, oid, 1, '%020d' % i, '0' + str(i), None) def _getObject(self, value): oid = self.getOID(value) serial = self.getNextTID() return (serial, (oid, 1, '%020d' % value, 'O' + str(value), None)) def _checkTransactionStored(self, *args): calls = self.app.dm.mockGetNamedCalls('storeTransaction') self.assertEqual(len(calls), 1) calls[0].checkArgs(*args) def _checkTransactionFinished(self, *args): calls = self.app.dm.mockGetNamedCalls('unlockTransaction') self.assertEqual(len(calls), 1) calls[0].checkArgs(*args) def _checkQueuedEventExecuted(self, number=1): calls = self.app.mockGetNamedCalls('executeQueuedEvents') self.assertEqual(len(calls), number) def assertRegistered(self, ttid): self.assertIn(ttid, self.manager._transaction_dict) def assertNotRegistered(self, ttid): self.assertNotIn(ttid, self.manager._transaction_dict) def testSimpleCase(self): """ One node, one transaction, not abort """ data_id_list = random.random(), random.random() self.app.dm.mockAddReturnValues(holdData=ReturnValues(*data_id_list)) uuid = self.getClientUUID() ttid = self.getNextTID() tid, txn = self._getTransaction() serial1, object1 = self._getObject(1) serial2, object2 = self._getObject(2) self.manager.register(uuid, ttid) self.manager.storeObject(ttid, serial1, *object1) self.manager.storeObject(ttid, serial2, *object2) self.assertRegistered(ttid) self.manager.vote(ttid, txn) user, desc, ext, oid_list = txn call, = self.app.dm.mockGetNamedCalls('storeTransaction') call.checkArgs(ttid, [ (object1[0], data_id_list[0], object1[4]), (object2[0], data_id_list[1], object2[4]), ], (oid_list, user, desc, ext, False, ttid)) self.manager.lock(ttid, tid) call, = self.app.dm.mockGetNamedCalls('lockTransaction') call.checkArgs(tid, ttid) self.manager.unlock(ttid) self.assertNotRegistered(ttid) call, = self.app.dm.mockGetNamedCalls('unlockTransaction') call.checkArgs(tid, ttid) def testDelayed(self): """ Two transactions, the first cause the second to be delayed """ uuid = self.getClientUUID() ttid1 = self.getNextTID() ttid2 = self.getNextTID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() serial, obj = self._getObject(1) # first transaction lock the object self.manager.register(uuid, ttid1) self.assertRegistered(ttid1) self._storeTransactionObjects(ttid1, txn1) self.manager.vote(ttid1, txn1) self.manager.lock(ttid1, tid1) # the second is delayed self.manager.register(uuid, ttid2) self.assertRegistered(ttid2) self.assertRaises(DelayedError, self.manager.storeObject, ttid2, serial, *obj) def testUnresolvableConflict(self): """ A newer transaction has already modified an object """ uuid = self.getClientUUID() ttid1 = self.getNextTID() ttid2 = self.getNextTID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() serial, obj = self._getObject(1) # the (later) transaction lock (change) the object self.manager.register(uuid, ttid2) self.assertRegistered(ttid2) self._storeTransactionObjects(ttid2, txn2) self.manager.vote(ttid2, txn2) self.manager.lock(ttid2, tid2) # the previous it's not using the latest version self.manager.register(uuid, ttid1) self.assertRegistered(ttid1) self.assertRaises(ConflictError, self.manager.storeObject, ttid1, serial, *obj) def testResolvableConflict(self): """ Try to store an object with the lastest revision """ uuid = self.getClientUUID() tid, txn = self._getTransaction() serial, obj = self._getObject(1) next_serial = self.getNextTID(serial) # try to store without the last revision self.app.dm = Mock({'getLastObjectTID': next_serial}) self.manager.register(uuid, tid) self.assertRaises(ConflictError, self.manager.storeObject, tid, serial, *obj) def testLockDelayed(self): """ Check lock delay """ uuid1 = self.getClientUUID() uuid2 = self.getClientUUID() self.assertNotEqual(uuid1, uuid2) ttid1 = self.getNextTID() ttid2 = self.getNextTID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() serial1, obj1 = self._getObject(1) serial2, obj2 = self._getObject(2) # first transaction lock objects self.manager.register(uuid1, ttid1) self.assertRegistered(ttid1) self.manager.storeObject(ttid1, serial1, *obj1) self.manager.storeObject(ttid1, serial1, *obj2) self.manager.vote(ttid1, txn1) self.manager.lock(ttid1, tid1) # second transaction is delayed self.manager.register(uuid2, ttid2) self.assertRegistered(ttid2) self.assertRaises(DelayedError, self.manager.storeObject, ttid2, serial1, *obj1) self.assertRaises(DelayedError, self.manager.storeObject, ttid2, serial2, *obj2) def testLockConflict(self): """ Check lock conflict """ uuid1 = self.getClientUUID() uuid2 = self.getClientUUID() self.assertNotEqual(uuid1, uuid2) ttid1 = self.getNextTID() ttid2 = self.getNextTID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() serial1, obj1 = self._getObject(1) serial2, obj2 = self._getObject(2) # the second transaction lock objects self.manager.register(uuid2, ttid2) self.manager.storeObject(ttid2, serial1, *obj1) self.manager.storeObject(ttid2, serial2, *obj2) self.assertRegistered(ttid2) self.manager.vote(ttid2, txn2) self.manager.lock(ttid2, tid2) # the first get a conflict self.manager.register(uuid1, ttid1) self.assertRegistered(ttid1) self.assertRaises(ConflictError, self.manager.storeObject, ttid1, serial1, *obj1) self.assertRaises(ConflictError, self.manager.storeObject, ttid1, serial2, *obj2) def testAbortUnlocked(self): """ Abort a non-locked transaction """ uuid = self.getClientUUID() tid, txn = self._getTransaction() serial, obj = self._getObject(1) self.manager.register(uuid, tid) self.manager.storeObject(tid, serial, *obj) self.assertRegistered(tid) self.manager.vote(tid, txn) # transaction is not locked self.manager.abort(tid) self.assertNotRegistered(tid) self.assertFalse(self.manager.loadLocked(obj[0])) self._checkQueuedEventExecuted() def testAbortLockedDoNothing(self): """ Try to abort a locked transaction """ uuid = self.getClientUUID() ttid = self.getNextTID() tid, txn = self._getTransaction() self.manager.register(uuid, ttid) self._storeTransactionObjects(ttid, txn) self.manager.vote(ttid, txn) # lock transaction self.manager.lock(ttid, tid) self.assertRegistered(ttid) self.manager.abort(ttid) self.assertRegistered(ttid) for oid in txn[-1]: self.assertTrue(self.manager.loadLocked(oid)) self._checkQueuedEventExecuted(number=0) def testAbortForNode(self): """ Abort transaction for a node """ uuid1 = self.getClientUUID() uuid2 = self.getClientUUID() self.assertNotEqual(uuid1, uuid2) ttid1 = self.getNextTID() ttid2 = self.getNextTID() ttid3 = self.getNextTID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() tid3, txn3 = self._getTransaction() self.manager.register(uuid1, ttid1) self.manager.register(uuid2, ttid2) self.manager.register(uuid2, ttid3) self.manager.vote(ttid1, txn1) # node 2 owns tid2 & tid3 and lock tid2 only self._storeTransactionObjects(ttid2, txn2) self.manager.vote(ttid2, txn2) self.manager.vote(ttid3, txn3) self.manager.lock(ttid2, tid2) self.assertRegistered(ttid1) self.assertRegistered(ttid2) self.assertRegistered(ttid3) self.manager.abortFor(uuid2) # only tid3 is aborted self.assertRegistered(ttid1) self.assertRegistered(ttid2) self.assertNotRegistered(ttid3) self._checkQueuedEventExecuted(number=1) def testReset(self): """ Reset the manager """ uuid = self.getClientUUID() tid, txn = self._getTransaction() ttid = self.getNextTID() self.manager.register(uuid, ttid) self._storeTransactionObjects(ttid, txn) self.manager.vote(ttid, txn) self.manager.lock(ttid, tid) self.assertRegistered(ttid) self.manager.reset() self.assertNotRegistered(ttid) for oid in txn[0]: self.assertFalse(self.manager.loadLocked(oid)) def test_getObjectFromTransaction(self): data_id = random.random() self.app.dm.mockAddReturnValues(holdData=ReturnValues(data_id)) uuid = self.getClientUUID() tid1, txn1 = self._getTransaction() tid2, txn2 = self._getTransaction() serial1, obj1 = self._getObject(1) serial2, obj2 = self._getObject(2) self.manager.register(uuid, tid1) self.manager.storeObject(tid1, serial1, *obj1) self.assertEqual(self.manager.getObjectFromTransaction(tid2, obj1[0]), None) self.assertEqual(self.manager.getObjectFromTransaction(tid1, obj2[0]), None) self.assertEqual(self.manager.getObjectFromTransaction(tid1, obj1[0]), (obj1[0], data_id, obj1[4])) def test_getLockingTID(self): uuid = self.getClientUUID() serial1, obj1 = self._getObject(1) oid1 = obj1[0] tid1, txn1 = self._getTransaction() self.assertEqual(self.manager.getLockingTID(oid1), None) self.manager.register(uuid, tid1) self.manager.storeObject(tid1, serial1, *obj1) self.assertEqual(self.manager.getLockingTID(oid1), tid1) def test_updateObjectDataForPack(self): ram_serial = self.getNextTID() oid = self.getOID(1) orig_serial = self.getNextTID() uuid = self.getClientUUID() locking_serial = self.getNextTID() other_serial = self.getNextTID() new_serial = self.getNextTID() checksum = "2" * 20 self.manager.register(uuid, locking_serial) # Object not known, nothing happens self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), None) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), None) self.manager.abort(locking_serial, even_if_locked=True) # Object known, but doesn't point at orig_serial, it is not updated self.manager.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, 0, "3" * 20, 'bar', None) holdData = self.app.dm.mockGetNamedCalls('holdData') self.assertEqual(holdData.pop(0).params, ("3" * 20, 'bar', 0)) orig_object = self.manager.getObjectFromTransaction(locking_serial, oid) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), orig_object) self.manager.abort(locking_serial, even_if_locked=True) self.manager.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, other_serial) orig_object = self.manager.getObjectFromTransaction(locking_serial, oid) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), orig_object) self.manager.abort(locking_serial, even_if_locked=True) # Object known and points at undone data it gets updated self.manager.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, orig_serial) self.manager.updateObjectDataForPack(oid, orig_serial, new_serial, checksum) self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), (oid, None, new_serial)) self.manager.abort(locking_serial, even_if_locked=True) self.manager.register(uuid, locking_serial) self.manager.storeObject(locking_serial, ram_serial, oid, None, None, None, orig_serial) self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum) self.assertEqual(holdData.pop(0).params, (checksum,)) self.assertEqual(self.manager.getObjectFromTransaction(locking_serial, oid), (oid, checksum, None)) self.manager.abort(locking_serial, even_if_locked=True) self.assertFalse(holdData)