aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/connection_management_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/connection_management_test.rb')
-rw-r--r--activerecord/test/cases/connection_management_test.rb114
1 files changed, 114 insertions, 0 deletions
diff --git a/activerecord/test/cases/connection_management_test.rb b/activerecord/test/cases/connection_management_test.rb
new file mode 100644
index 0000000000..0941ee3309
--- /dev/null
+++ b/activerecord/test/cases/connection_management_test.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "rack"
+
+module ActiveRecord
+ module ConnectionAdapters
+ class ConnectionManagementTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
+
+ class App
+ attr_reader :calls
+ def initialize
+ @calls = []
+ end
+
+ def call(env)
+ @calls << env
+ [200, {}, ["hi mom"]]
+ end
+ end
+
+ def setup
+ @env = {}
+ @app = App.new
+ @management = middleware(@app)
+
+ # make sure we have an active connection
+ assert ActiveRecord::Base.connection
+ assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+
+ def test_app_delegation
+ manager = middleware(@app)
+
+ manager.call @env
+ assert_equal [@env], @app.calls
+ end
+
+ def test_body_responds_to_each
+ _, _, body = @management.call(@env)
+ bits = []
+ body.each { |bit| bits << bit }
+ assert_equal ["hi mom"], bits
+ end
+
+ def test_connections_are_cleared_after_body_close
+ _, _, body = @management.call(@env)
+ body.close
+ assert_not_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+
+ def test_active_connections_are_not_cleared_on_body_close_during_transaction
+ ActiveRecord::Base.transaction do
+ _, _, body = @management.call(@env)
+ body.close
+ assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+ end
+
+ def test_connections_closed_if_exception
+ app = Class.new(App) { def call(env); raise NotImplementedError; end }.new
+ explosive = middleware(app)
+ assert_raises(NotImplementedError) { explosive.call(@env) }
+ assert_not_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+
+ def test_connections_not_closed_if_exception_inside_transaction
+ ActiveRecord::Base.transaction do
+ app = Class.new(App) { def call(env); raise RuntimeError; end }.new
+ explosive = middleware(app)
+ assert_raises(RuntimeError) { explosive.call(@env) }
+ assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+ end
+
+ test "doesn't clear active connections when running in a test case" do
+ executor.wrap do
+ @management.call(@env)
+ assert_predicate ActiveRecord::Base.connection_handler, :active_connections?
+ end
+ end
+
+ test "proxy is polite to its body and responds to it" do
+ body = Class.new(String) { def to_path; "/path"; end }.new
+ app = lambda { |_| [200, {}, body] }
+ response_body = middleware(app).call(@env)[2]
+ assert_respond_to response_body, :to_path
+ assert_equal "/path", response_body.to_path
+ end
+
+ test "doesn't mutate the original response" do
+ original_response = [200, {}, "hi"]
+ app = lambda { |_| original_response }
+ middleware(app).call(@env)[2]
+ assert_equal "hi", original_response.last
+ end
+
+ private
+ def executor
+ @executor ||= Class.new(ActiveSupport::Executor).tap do |exe|
+ ActiveRecord::QueryCache.install_executor_hooks(exe)
+ end
+ end
+
+ def middleware(app)
+ lambda do |env|
+ a, b, c = executor.wrap { app.call(env) }
+ [a, b, Rack::BodyProxy.new(c) {}]
+ end
+ end
+ end
+ end
+end