diff --git a/test/test_integration_pending.rb b/test/test_integration_pending.rb index ca963dea..8d83e958 100644 --- a/test/test_integration_pending.rb +++ b/test/test_integration_pending.rb @@ -115,62 +115,74 @@ def test_busy_timeout t.join end - def test_busy_handler_timeout_releases_gvl - @db.busy_handler_timeout = 100 - - t1sync = ThreadSynchronizer.new - t2sync = ThreadSynchronizer.new - - busy = Mutex.new - busy.lock - - count = 0 - active_thread = Thread.new(t1sync) do |sync| - sync.send_to_main :ready - sync.wait_for_main :start - - loop do - sleep 0.01 - count += 1 - begin - sync.wait_for_main :end, true - break - rescue ThreadError - end + [ + # 10 is the theoretical max if timeout is 100ms and active thread sleeps 10ms + # in practice this number is almost always 9, but let's leave a bit of room for randomness + {name: "test_busy_handler_timeout_releases_gvl", busy_handler_timeout: 100, expected_count: [:>=, 8]}, + + # in practive this number is almost always 0, but it might squeak in 1 if the timing is juuuust right + {name: "test_busy_timeout_does_not_release_gvl", busy_timeout: 100, expected_count: [:<=, 1]} + ].each do |test_case| + define_method test_case[:name] do + if test_case[:busy_handler_timeout] + @db.busy_handler_timeout = 100 + end + if test_case[:busy_timeout] + @db.busy_timeout = test_case[:busy_timeout] end - sync.send_to_main :done - end - blocking_thread = Thread.new(t2sync) do |sync| - db2 = SQLite3::Database.open("test.db") - db2.transaction(:exclusive) do + t1sync = ThreadSynchronizer.new + t2sync = ThreadSynchronizer.new + + busy = Mutex.new + busy.lock + + count = 0 + active_thread = Thread.new(t1sync) do |sync| sync.send_to_main :ready - busy.lock + sync.wait_for_main :start + + loop do + sleep 0.01 + count += 1 + begin + sync.wait_for_main :end, true + break + rescue ThreadError + end + end + sync.send_to_main :done end - ensure - db2&.close - end - t1sync.wait_for_thread :ready - t2sync.wait_for_thread :ready + 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 + ensure + db2&.close + end - 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 + t1sync.wait_for_thread :ready + t2sync.wait_for_thread :ready - # 10 is the theoretical max if timeout is 100ms and active thread sleeps 10ms - # in practice this number is almost always 9, but let's leave a bit of room for randomness - assert_operator(count, :>=, 8) + 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 - ensure - active_thread&.kill - blocking_thread&.kill + assert_operator(count, *test_case[:expected_count]) - t1sync&.close - t2sync&.close + busy.unlock + ensure + active_thread&.join + blocking_thread&.join + + t1sync&.close + t2sync&.close + end end def test_busy_handler_outwait