ruby--ruby/test/fiber/test_mutex.rb

221 lines
3.8 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require 'test/unit'
require_relative 'scheduler'
class TestFiberMutex < Test::Unit::TestCase
def test_mutex_synchronize
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
Fiber.schedule do
2020-10-16 01:25:58 +00:00
assert_not_predicate Fiber, :blocking?
mutex.synchronize do
2020-10-16 01:25:58 +00:00
assert_not_predicate Fiber, :blocking?
end
end
end
thread.join
end
def test_mutex_interleaved_locking
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
Fiber.schedule do
mutex.lock
sleep 0.1
mutex.unlock
end
Fiber.schedule do
mutex.lock
sleep 0.1
mutex.unlock
end
scheduler.run
end
thread.join
end
def test_mutex_thread
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
mutex.lock
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
Fiber.schedule do
mutex.lock
sleep 0.1
mutex.unlock
end
scheduler.run
end
sleep 0.1
mutex.unlock
thread.join
end
def test_mutex_fiber_raise
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
ran = false
main = Thread.new do
mutex.lock
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
f = Fiber.schedule do
assert_raise_with_message(RuntimeError, "bye") do
mutex.lock
end
ran = true
end
Fiber.schedule do
f.raise "bye"
end
end
thread.join
end
main.join # causes mutex to be released
assert_equal false, mutex.locked?
assert_equal true, ran
end
2020-09-11 08:47:25 +00:00
def test_condition_variable
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
condition = Thread::ConditionVariable.new
2020-09-11 08:47:25 +00:00
signalled = 0
Thread.new do
2020-09-11 08:47:25 +00:00
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
2020-09-11 08:47:25 +00:00
Fiber.schedule do
mutex.synchronize do
3.times do
condition.wait(mutex)
signalled += 1
end
end
end
Fiber.schedule do
3.times do
mutex.synchronize do
condition.signal
end
sleep 0.1
end
end
scheduler.run
end.join
2020-09-11 08:47:25 +00:00
assert_equal 3, signalled
2020-09-11 08:47:25 +00:00
end
2020-09-13 23:10:02 +00:00
def test_queue
2021-06-28 14:01:53 +00:00
queue = Thread::Queue.new
2020-09-13 23:10:02 +00:00
processed = 0
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
2020-09-13 23:10:02 +00:00
Fiber.schedule do
3.times do |i|
queue << i
sleep 0.1
end
queue.close
end
Fiber.schedule do
while item = queue.pop
processed += 1
end
end
scheduler.run
end
thread.join
assert_equal 3, processed
2020-09-13 23:10:02 +00:00
end
def test_queue_pop_waits
2021-06-28 14:01:53 +00:00
queue = Thread::Queue.new
running = false
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
result = nil
Fiber.schedule do
result = queue.pop
end
running = true
scheduler.run
result
end
Thread.pass until running
sleep 0.1
queue << :done
assert_equal :done, thread.value
end
def test_mutex_deadlock
error_pattern = /No live threads left. Deadlock\?/
assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], error_pattern, success: false
require 'scheduler'
2021-06-28 14:01:53 +00:00
mutex = Thread::Mutex.new
thread = Thread.new do
scheduler = Scheduler.new
2020-10-16 01:25:58 +00:00
Fiber.set_scheduler scheduler
Fiber.schedule do
mutex.synchronize do
puts 'in synchronize'
Fiber.yield
end
end
2020-05-14 10:57:39 +00:00
mutex.lock
end
thread.join
RUBY
end
end