Skip to content

Commit

Permalink
test: rewrite the bundler_handler_timout GVL test
Browse files Browse the repository at this point in the history
It's now 10x faster
  • Loading branch information
flavorjones committed Apr 25, 2024
1 parent f02e23f commit 3100997
Showing 1 changed file with 41 additions and 22 deletions.
63 changes: 41 additions & 22 deletions test/test_integration_pending.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -102,55 +101,76 @@ 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.01
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
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

# 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)

busy.unlock
t.join
ensure
active_thread&.kill
blocking_thread&.kill

assert_operator work.size - work.find_index("|"), :>, 3
t1sync&.close
t2sync&.close
end

def test_busy_handler_outwait
Expand All @@ -168,6 +188,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
Expand All @@ -176,14 +197,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

0 comments on commit 3100997

Please sign in to comment.