Skip to content

Commit

Permalink
Merge pull request #459 from masamitsu-murase/improve_test_for_multit…
Browse files Browse the repository at this point in the history
…hread

Revive test_busy_handler_outwait and synchronize threads to remove "sleep 1".
  • Loading branch information
flavorjones committed Apr 25, 2024
2 parents 659d01c + 6899ba3 commit 2388793
Showing 1 changed file with 83 additions and 12 deletions.
95 changes: 83 additions & 12 deletions test/test_integration_pending.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,39 @@
require "benchmark"

class IntegrationPendingTestCase < SQLite3::TestCase
class ThreadSynchronizer
def initialize
@main_to_thread = Queue.new
@thread_to_main = Queue.new
end

def send_to_thread state
@main_to_thread.push state
end

def send_to_main state
@thread_to_main.push state
end

def wait_for_thread expected_state
state = @thread_to_main.pop
raise "Invalid state #{state}. #{expected_state} is expected" if state != expected_state
end

def wait_for_main expected_state
state = @main_to_thread.pop
raise "Invalid state #{state}. #{expected_state} is expected" if state != expected_state
end

def close_thread
@thread_to_main.close
end

def close_main
@main_to_thread.close
end
end

def setup
@db = SQLite3::Database.new("test.db")
@db.transaction do
Expand All @@ -19,19 +52,20 @@ def teardown
end

def test_busy_handler_impatient
busy = Mutex.new
busy.lock
synchronizer = ThreadSynchronizer.new
handler_call_count = 0

t = Thread.new do
t = Thread.new(synchronizer) do |sync|
db2 = SQLite3::Database.open("test.db")
db2.transaction(:exclusive) do
busy.lock
sync.send_to_main :ready_0
sync.wait_for_main :end_1
end
ensure
db2&.close
sync.close_thread
end
sleep 1
synchronizer.wait_for_thread :ready_0

@db.busy_handler do
handler_call_count += 1
Expand All @@ -42,34 +76,37 @@ def test_busy_handler_impatient
@db.execute "insert into foo (b) values ( 'from 2' )"
end

busy.unlock
synchronizer.send_to_thread :end_1
synchronizer.close_main
t.join

assert_equal 1, handler_call_count
end

def test_busy_timeout
@db.busy_timeout 1000
busy = Mutex.new
busy.lock
synchronizer = ThreadSynchronizer.new

t = Thread.new do
t = Thread.new(synchronizer) do |sync|
db2 = SQLite3::Database.open("test.db")
db2.transaction(:exclusive) do
busy.lock
sync.send_to_main :ready_0
sync.wait_for_main :end_1
end
ensure
db2&.close
sync.close_thread
end

sleep 1
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

busy.unlock
synchronizer.send_to_thread :end_1
synchronizer.close_main
t.join

assert_operator time.real * 1000, :>=, 1000
Expand Down Expand Up @@ -110,4 +147,38 @@ def test_busy_handler_timeout_releases_gvl

assert_operator work.size - work.find_index("|"), :>, 3
end

def test_busy_handler_outwait
synchronizer = ThreadSynchronizer.new
handler_call_count = 0

t = Thread.new(synchronizer) do |sync|
db2 = SQLite3::Database.open("test.db")
db2.transaction(:exclusive) do
sync.send_to_main :ready_0
sync.wait_for_main :busy_handler_called_1
end
sync.send_to_main :end_of_transaction_2
ensure
db2&.close
sync.close_thread
end

@db.busy_handler do |count|
handler_call_count += 1
synchronizer.send_to_thread :busy_handler_called_1
synchronizer.wait_for_thread :end_of_transaction_2
true
end

synchronizer.wait_for_thread :ready_0
assert_nothing_raised do
@db.execute "insert into foo (b) values ( 'from 2' )"
end

synchronizer.close_main
t.join

assert_equal 1, handler_call_count
end
end

0 comments on commit 2388793

Please sign in to comment.