aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2017-02-20 13:35:19 -0500
committereileencodes <eileencodes@gmail.com>2017-02-20 16:31:24 -0500
commitd6466beb9fff9f2ba4f73673e65f087dd6bba488 (patch)
tree72e63e704e18a4bc37594e5b5d482bcc59754545 /activerecord/test/cases
parent71da39097b67114329be6d8db7fe6911124531af (diff)
downloadrails-d6466beb9fff9f2ba4f73673e65f087dd6bba488.tar.gz
rails-d6466beb9fff9f2ba4f73673e65f087dd6bba488.tar.bz2
rails-d6466beb9fff9f2ba4f73673e65f087dd6bba488.zip
Ensure test threads share a DB connection
This ensures multiple threads inside a transactional test to see consistent database state. When a system test starts Puma spins up one thread and Capybara spins up another thread. Because of this when tests are run the database cannot see what was inserted into the database on teardown. This is because there are two threads using two different connections. This change uses the statement cache to lock the threads to using a single connection ID instead of each not being able to see each other. This code only runs in the fixture setup and teardown so it does not affect real production databases. When a transaction is opened we set `lock_thread` to `Thread.current` so we can keep track of which connection the thread is using. When we rollback the transaction we unlock the thread and then there will be no left-over data in the database because the transaction will roll back the correct connections. [ Eileen M. Uchitelle, Matthew Draper ]
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r--activerecord/test/cases/fixtures_test.rb6
-rw-r--r--activerecord/test/cases/query_cache_test.rb12
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb2
3 files changed, 20 insertions, 0 deletions
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 61e596e208..afe761cb55 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -640,6 +640,8 @@ class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase
def test_transaction_created_on_connection_notification
connection = stub(transaction_open?: false)
connection.expects(:begin_transaction).with(joinable: false)
+ pool = connection.stubs(:pool).returns(ActiveRecord::ConnectionAdapters::ConnectionPool.new(ActiveRecord::Base.connection_pool.spec))
+ pool.stubs(:lock_thread=).with(false)
fire_connection_notification(connection)
end
@@ -647,12 +649,16 @@ class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase
# Mocha is not thread-safe so define our own stub to test
connection = Class.new do
attr_accessor :rollback_transaction_called
+ attr_accessor :pool
def transaction_open?; true; end
def begin_transaction(*args); end
def rollback_transaction(*args)
@rollback_transaction_called = true
end
end.new
+ connection.pool = Class.new do
+ def lock_thread=(lock_thread); false; end
+ end.new
fire_connection_notification(connection)
teardown_fixtures
assert(connection.rollback_transaction_called, "Expected <mock connection>#rollback_transaction to be called but was not")
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index d8cf235000..494663eb04 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -532,4 +532,16 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
end
end
end
+
+ test "threads use the same connection" do
+ @connection_1 = ActiveRecord::Base.connection.object_id
+
+ thread_a = Thread.new do
+ @connection_2 = ActiveRecord::Base.connection.object_id
+ end
+
+ thread_a.join
+
+ assert_equal @connection_1, @connection_2
+ end
end
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 3a04f4bf7d..14fb2fbbfa 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -10,6 +10,8 @@ require "concurrent/atomic/cyclic_barrier"
class DefaultScopingTest < ActiveRecord::TestCase
fixtures :developers, :posts, :comments
+ self.use_transactional_tests = false
+
def test_default_scope
expected = Developer.all.merge!(order: "salary DESC").to_a.collect(&:salary)
received = DeveloperOrderedBySalary.all.collect(&:salary)