diff options
Diffstat (limited to 'activerecord/test/cases/transactions_test.rb')
-rw-r--r-- | activerecord/test/cases/transactions_test.rb | 144 |
1 files changed, 107 insertions, 37 deletions
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index bb4f2c8064..980981903a 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -14,6 +14,21 @@ class TransactionTest < ActiveRecord::TestCase @first, @second = Topic.find(1, 2).sort_by { |t| t.id } end + def test_raise_after_destroy + assert_not @first.frozen? + + assert_raises(RuntimeError) { + Topic.transaction do + @first.destroy + assert @first.frozen? + raise + end + } + + assert @first.reload + assert_not @first.frozen? + end + def test_successful Topic.transaction do @first.approved = true @@ -102,21 +117,35 @@ class TransactionTest < ActiveRecord::TestCase assert !Topic.find(1).approved? end - def test_update_attributes_should_rollback_on_failure + def test_raising_exception_in_nested_transaction_restore_state_in_save + topic = Topic.new + + def topic.after_save_for_transaction + raise 'Make the transaction rollback' + end + + assert_raises(RuntimeError) do + Topic.transaction { topic.save } + end + + assert topic.new_record?, "#{topic.inspect} should be new record" + end + + def test_update_should_rollback_on_failure author = Author.find(1) posts_count = author.posts.size assert posts_count > 0 - status = author.update_attributes(:name => nil, :post_ids => []) + status = author.update(name: nil, post_ids: []) assert !status assert_equal posts_count, author.posts(true).size end - def test_update_attributes_should_rollback_on_failure! + def test_update_should_rollback_on_failure! author = Author.find(1) posts_count = author.posts.size assert posts_count > 0 assert_raise(ActiveRecord::RecordInvalid) do - author.update_attributes!(:name => nil, :post_ids => []) + author.update!(name: nil, post_ids: []) end assert_equal posts_count, author.posts(true).size end @@ -346,6 +375,36 @@ class TransactionTest < ActiveRecord::TestCase assert_equal "Three", @three end if Topic.connection.supports_savepoints? + def test_using_named_savepoints + Topic.transaction do + @first.approved = true + @first.save! + Topic.connection.create_savepoint("first") + + @first.approved = false + @first.save! + Topic.connection.rollback_to_savepoint("first") + assert @first.reload.approved? + + @first.approved = false + @first.save! + Topic.connection.release_savepoint("first") + assert_not @first.reload.approved? + end + end if Topic.connection.supports_savepoints? + + def test_releasing_named_savepoints + Topic.transaction do + Topic.connection.create_savepoint("another") + Topic.connection.release_savepoint("another") + + # The savepoint is now gone and we can't remove it again. + assert_raises(ActiveRecord::StatementInvalid) do + Topic.connection.release_savepoint("another") + end + end + end + def test_rollback_when_commit_raises Topic.connection.expects(:begin_db_transaction) Topic.connection.expects(:commit_db_transaction).raises('OH NOES') @@ -362,7 +421,9 @@ class TransactionTest < ActiveRecord::TestCase topic = Topic.new(:title => 'test') topic.freeze e = assert_raise(RuntimeError) { topic.save } - assert_equal "can't modify frozen Hash", e.message + assert_match(/frozen/i, e.message) # Not good enough, but we can't do much + # about it since there is no specific error + # for frozen objects. assert !topic.persisted?, 'not persisted' assert_nil topic.id assert topic.frozen?, 'not frozen' @@ -395,16 +456,6 @@ class TransactionTest < ActiveRecord::TestCase assert !@second.destroyed?, 'not destroyed' end - if current_adapter?(:PostgreSQLAdapter) && defined?(PGconn::PQTRANS_IDLE) - def test_outside_transaction_works - assert assert_deprecated { Topic.connection.outside_transaction? } - Topic.connection.begin_db_transaction - assert assert_deprecated { !Topic.connection.outside_transaction? } - Topic.connection.rollback_db_transaction - assert assert_deprecated { Topic.connection.outside_transaction? } - end - end - def test_sqlite_add_column_in_transaction return true unless current_adapter?(:SQLite3Adapter) @@ -436,6 +487,34 @@ class TransactionTest < ActiveRecord::TestCase end end + def test_transactions_state_from_rollback + connection = Topic.connection + transaction = ActiveRecord::ConnectionAdapters::ClosedTransaction.new(connection).begin + + assert transaction.open? + assert !transaction.state.rolledback? + assert !transaction.state.committed? + + transaction.perform_rollback + + assert transaction.state.rolledback? + assert !transaction.state.committed? + end + + def test_transactions_state_from_commit + connection = Topic.connection + transaction = ActiveRecord::ConnectionAdapters::ClosedTransaction.new(connection).begin + + assert transaction.open? + assert !transaction.state.rolledback? + assert !transaction.state.committed? + + transaction.perform_commit + + assert !transaction.state.rolledback? + assert transaction.state.committed? + end + private %w(validation save destroy).each do |filter| @@ -493,22 +572,22 @@ if current_adapter?(:PostgreSQLAdapter) # This will cause transactions to overlap and fail unless they are performed on # separate database connections. def test_transaction_per_thread - assert_nothing_raised do - threads = (1..3).map do - Thread.new do - Topic.transaction do - topic = Topic.find(1) - topic.approved = !topic.approved? - topic.save! - topic.approved = !topic.approved? - topic.save! - end - Topic.connection.close + skip "in memory db can't share a db between threads" if in_memory_db? + + threads = 3.times.map do + Thread.new do + Topic.transaction do + topic = Topic.find(1) + topic.approved = !topic.approved? + assert topic.save! + topic.approved = !topic.approved? + assert topic.save! end + Topic.connection.close end - - threads.each { |t| t.join } end + + threads.each { |t| t.join } end # Test for dirty reads among simultaneous transactions. @@ -560,14 +639,5 @@ if current_adapter?(:PostgreSQLAdapter) assert_equal original_salary, Developer.find(1).salary end - - test "#transaction_joinable= is deprecated" do - Developer.transaction do - conn = Developer.connection - assert conn.current_transaction.joinable? - assert_deprecated { conn.transaction_joinable = false } - assert !conn.current_transaction.joinable? - end - end end end |