From fdba4126468badfb8cf9987b768bd9632c508c6c Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 25 Apr 2024 13:31:36 -0400 Subject: [PATCH] test: rewrite the bundler_handler_timout GVL test It's now 10x faster --- test/test_integration_pending.rb | 72 ++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/test/test_integration_pending.rb b/test/test_integration_pending.rb index 69f1fd7f..b8933bcb 100644 --- a/test/test_integration_pending.rb +++ b/test/test_integration_pending.rb @@ -80,12 +80,11 @@ def test_busy_handler_impatient assert_raise(SQLite3::BusyException) do @db.execute "insert into foo (b) values ( 'from 2' )" end + assert_equal 1, handler_call_count synchronizer.send_to_thread :end_1 synchronizer.close_main t.join - - assert_equal 1, handler_call_count end def test_busy_timeout @@ -102,55 +101,83 @@ def test_busy_timeout db2&.close sync.close_thread end - synchronizer.wait_for_thread :ready_0 + time = Benchmark.measure do assert_raise(SQLite3::BusyException) do @db.execute "insert into foo (b) values ( 'from 2' )" end end + assert_operator time.real * 1000, :>=, 1000 synchronizer.send_to_thread :end_1 synchronizer.close_main t.join - - assert_operator time.real * 1000, :>=, 1000 end def test_busy_handler_timeout_releases_gvl - work = [] + @db.busy_handler_timeout = 100 - Thread.new do - loop do - sleep 0.1 - work << "." - end - end - sleep 1 + t1sync = ThreadSynchronizer.new + t2sync = ThreadSynchronizer.new - @db.busy_handler_timeout = 1000 busy = Mutex.new busy.lock - t = Thread.new do + count = 0 + active_thread = Thread.new(t1sync) do |sync| + sync.send_to_main :ready + sync.wait_for_main :start + + loop do + sleep 0.005 + count += 1 + begin + sync.wait_for_main :end, true + break + rescue ThreadError + end + end + sync.send_to_main :done + end + + blocking_thread = Thread.new(t2sync) do |sync| db2 = SQLite3::Database.open("test.db") db2.transaction(:exclusive) do + sync.send_to_main :ready busy.lock end + sync.send_to_main :done ensure db2&.close end - sleep 1 - work << "|" + t1sync.wait_for_thread :ready + t2sync.wait_for_thread :ready + + t1sync.send_to_thread :start assert_raises(SQLite3::BusyException) do @db.execute "insert into foo (b) values ( 'from 2' )" end + t1sync.send_to_thread :end busy.unlock - t.join - - assert_operator work.size - work.find_index("|"), :>, 3 + t2sync.wait_for_thread :done + + expected = if RUBY_PLATFORM.include?("linux") + # 20 is the theoretical max if timeout is 100ms and active thread sleeps 5ms + 15 + else + # in CI, macos and windows systems seem to really not thread very well, so let's set a lower bar. + 2 + end + assert_operator(count, :>=, expected) + ensure + active_thread&.join + blocking_thread&.join + + t1sync&.close + t2sync&.close end def test_busy_handler_outwait @@ -168,6 +195,7 @@ def test_busy_handler_outwait db2&.close sync.close_thread end + synchronizer.wait_for_thread :ready_0 @db.busy_handler do |count| handler_call_count += 1 @@ -176,14 +204,12 @@ def test_busy_handler_outwait true end - synchronizer.wait_for_thread :ready_0 assert_nothing_raised do @db.execute "insert into foo (b) values ( 'from 2' )" end + assert_equal 1, handler_call_count synchronizer.close_main t.join - - assert_equal 1, handler_call_count end end