def test_transaction(): with dbkit.connect(sqlite3, ':memory:'): dbkit.execute(SCHEMA) # First, make sure the normal case behaves correctly. assert dbkit.context()._depth == 0 with dbkit.transaction(): assert dbkit.context()._depth == 1 dbkit.execute(TEST_DATA) assert dbkit.context()._depth == 0 assert dbkit.query_value(GET_COUNTER, ('foo',)) == 42 assert dbkit.query_value(GET_COUNTER, ('bar',)) is None # Now, ensure transactions are rolled back in case of exceptions. exception_caught = False try: with dbkit.transaction(): dbkit.execute(UPDATE_COUNTER, (13, 'foo')) raise dbkit.AbortTransaction() assert False, "Should've raised an exception." except dbkit.AbortTransaction: exception_caught = True assert exception_caught value = dbkit.query_value(GET_COUNTER, ('foo',)) assert value == 42
def test_real_connect(self): with self.pool.connect(): with dbkit.transaction(): self.assertEqual(self.pool._allocated, 1) self.assertEqual(len(self.pool._pool), 0) self.assertEqual(self.pool._allocated, 1) self.assertEqual(len(self.pool._pool), 1)
def test_unpooled_disconnect(self): # Test rollback of connection. try: self.assertEqual(self.ctx.mdr.depth, 0) with self.ctx: try: with dbkit.transaction(): self.assertEqual(self.ctx.mdr.depth, 1) self.assertTrue(self.ctx.mdr.conn is not None) self.assertEqual( dbkit.query_value(GET_COUNTER, ('foo',)), 42) raise self.ctx.OperationalError("Simulating disconnect") except self.ctx.OperationalError: self.assertEqual(self.ctx.mdr.depth, 0) self.assertTrue(self.ctx.mdr.conn is None) raise self.fail("Should've raised OperationalError") except self.ctx.OperationalError as exc: self.assertEqual(self.ctx.mdr.depth, 0) self.assertTrue(self.ctx.mdr.conn is None) self.assertEqual(str(exc), "Simulating disconnect") # Test reconnect. As we're running this all against an in-memory DB, # everything in it will have been throttled, thus the only query we can # do is query the list of tables, which will be empty. with self.ctx: self.assertEqual(len(list(dbkit.query_column(LIST_TABLES))), 0) self.assertTrue(self.ctx.mdr.conn is not None)
def setup(): """Creates a context fit for testing.""" with dbkit.connect(sqlite3, ':memory:') as ctx: dbkit.execute(SCHEMA) with dbkit.transaction(): dbkit.execute(TEST_DATA) return ctx
def test_real_connect(): with POOL.connect(): with dbkit.transaction(): assert POOL._allocated == 1 assert len(POOL._pool) == 0 assert POOL._allocated == 1 assert len(POOL._pool) == 1
def setUp(self): """Creates a context fit for testing.""" self.ctx = dbkit.connect(sqlite3, ':memory:') with self.ctx: dbkit.execute(SCHEMA) with dbkit.transaction(): dbkit.execute(TEST_DATA) self.assertEqual(self.ctx.last_row_count, 1)
def test_transaction(self): with dbkit.connect(sqlite3, ':memory:'): dbkit.execute(SCHEMA) # First, make sure the normal case behaves correctly. self.assertEqual(dbkit.context()._depth, 0) with dbkit.transaction(): self.assertEqual(dbkit.context()._depth, 1) dbkit.execute(TEST_DATA) self.assertEqual(dbkit.context()._depth, 0) self.assertEqual(dbkit.query_value(GET_COUNTER, ('foo',)), 42) self.assertTrue(dbkit.query_value(GET_COUNTER, ('bar',)) is None) # Now, ensure transactions are rolled back in case of exceptions. exception_caught = False try: with dbkit.transaction(): dbkit.execute(UPDATE_COUNTER, (13, 'foo')) raise dbkit.AbortTransaction() self.fail("Should've raised an exception.") except dbkit.AbortTransaction: exception_caught = True self.assertTrue(exception_caught) self.assertEqual(dbkit.query_value(GET_COUNTER, ('foo',)), 42)
def wait_on_connection(): with pool.connect(): spawn.wait() # Request the other thread to release the connection after a # short period, enough to ensure the conditional variable # managing the pool is waited on by this thread. Basically # nearly any pause should be long enough, though 1/100 of a # second seems like a reasonable balance. # # We do this because we want to deterministically introduce a # wait on the condition variable that signals when there's a # free connection. In normal operation, this happens in a # nondeterministic manner. This pause and the use of the # release and spawn events ensure that the threads proceed in # lockstep to produce the behaviour we need to set. threading.Timer(1.0 / 100, lambda: release.set()).start() with dbkit.transaction(): pass
def test_unpooled_disconnect(): ctx = setup() # Test rollback of connection. try: with ctx: try: with dbkit.transaction(): assert ctx._mdr.depth == 1 assert ctx._mdr.conn is not None assert dbkit.query_value(GET_COUNTER, ('foo',)) == 42 raise ctx.OperationalError("Simulating disconnect") except: assert ctx._mdr.depth == 0 assert ctx._mdr.conn is None raise assert False, "Should've raised OperationalError" except ctx.OperationalError, exc: assert ctx._mdr.depth == 0 assert ctx._mdr.conn is None assert exc.message == "Simulating disconnect"
def hog_connection(): with pool.connect(): with dbkit.transaction(): spawn.set() release.wait()