require "./spec_helper" private class FooException < Exception end describe DB::Transaction do it "begin/commit transaction from connection" do with_dummy_connection do |cnn| tx = cnn.begin_transaction tx.commit end end it "begin/rollback transaction from connection" do with_dummy_connection do |cnn| tx = cnn.begin_transaction tx.rollback end end it "raise if begin over existing transaction" do with_dummy_connection do |cnn| cnn.begin_transaction expect_raises(DB::Error, "There is an existing transaction in this connection") do cnn.begin_transaction end end end it "allow sequential transactions" do with_dummy_connection do |cnn| tx = cnn.begin_transaction tx.rollback tx = cnn.begin_transaction tx.commit end end it "transaction with block from connection should be committed" do t = uninitialized DummyDriver::DummyTransaction with_witness do |w| with_dummy_connection do |cnn| cnn.transaction do |tx| if tx.is_a?(DummyDriver::DummyTransaction) t = tx w.check end end end end t.committed.should be_true t.rolledback.should be_false end it "transaction with block from connection should be rolledback if raise DB::Rollback" do t = uninitialized DummyDriver::DummyTransaction with_witness do |w| with_dummy_connection do |cnn| cnn.transaction do |tx| if tx.is_a?(DummyDriver::DummyTransaction) t = tx w.check end raise DB::Rollback.new end end end t.rolledback.should be_true t.committed.should be_false end it "transaction with block from connection should be rolledback if raise" do t = uninitialized DummyDriver::DummyTransaction with_witness do |w| with_dummy_connection do |cnn| expect_raises(FooException) do cnn.transaction do |tx| if tx.is_a?(DummyDriver::DummyTransaction) t = tx w.check end raise FooException.new end end end end t.rolledback.should be_true t.committed.should be_false end it "transaction with block from connection should be committed if `return` is called" do t = uninitialized DummyDriver::DummyTransaction with_witness do |w| with_dummy_connection do |cnn| t = return_from_txn(cnn).as(DummyDriver::DummyTransaction) w.check end end t.rolledback.should be_false t.committed.should be_true end it "transaction can be committed within block" do with_dummy_connection do |cnn| cnn.transaction do |tx| tx.commit end end end it "transaction can be rolledback within block" do with_dummy_connection do |cnn| cnn.transaction do |tx| tx.rollback end end end it "transaction can be rolledback within block and later raise" do with_dummy_connection do |cnn| expect_raises(FooException) do cnn.transaction do |tx| tx.rollback raise FooException.new end end end end it "transaction can be rolledback within block and later raise DB::Rollback without forwarding it" do with_dummy_connection do |cnn| cnn.transaction do |tx| tx.rollback raise DB::Rollback.new end end end it "transaction can't be committed twice" do with_dummy_connection do |cnn| cnn.transaction do |tx| tx.commit expect_raises(DB::Error, "Transaction already closed") do tx.commit end end end end it "transaction can't be rolledback twice" do with_dummy_connection do |cnn| cnn.transaction do |tx| tx.rollback expect_raises(DB::Error, "Transaction already closed") do tx.rollback end end end end it "return connection to pool after transaction block in db" do DummyDriver::DummyConnection.clear_connections with_dummy do |db| db.transaction do |tx| db.pool.is_available?(DummyDriver::DummyConnection.connections.first).should be_false end db.pool.is_available?(DummyDriver::DummyConnection.connections.first).should be_true end end it "releasing result_set from within transaction should not return connection to pool" do cnn = uninitialized DB::Connection with_dummy do |db| db.transaction do |tx| cnn = tx.connection cnn.scalar "1" db.pool.is_available?(cnn).should be_false end db.pool.is_available?(cnn).should be_true end end it "returns block value when sucess" do with_dummy_connection do |cnn| res = cnn.transaction do |tx| 42 end res.should eq(42) typeof(res).should eq(Int32 | Nil) end end it "returns value on rollback via method" do with_dummy_connection do |cnn| res = cnn.transaction do |tx| tx.rollback 42 end res.should eq(42) typeof(res).should eq(Int32 | Nil) end end it "returns nil on rollback via exception" do with_dummy_connection do |cnn| res = cnn.transaction do |tx| raise DB::Rollback.new 42 end res.should be_nil typeof(res).should eq(Int32 | Nil) end end end private def return_from_txn(cnn) cnn.transaction do |tx| return tx end end