1 # frozen_string_literal: false
5 class TestThreadConditionVariable < Test::Unit::TestCase
6 ConditionVariable = Thread::ConditionVariable
10 assert_raise(TypeError) {
11 ConditionVariable.allocate.wait(nil)
15 def test_condvar_signal_and_wait
16 mutex = Thread::Mutex.new
17 condvar = Thread::ConditionVariable.new
29 woken = condvar.wait(mutex)
33 assert_equal([0, 1, 2], result)
37 def test_condvar_wait_exception_handling
38 # Calling wait in the only thread running should raise a ThreadError of
39 # 'stopping only thread'
40 mutex = Thread::Mutex.new
41 condvar = Thread::ConditionVariable.new
44 thread = Thread.new do
45 Thread.current.abort_on_exception = false
47 assert_raise(Interrupt) {
50 locked = mutex.locked?
58 thread.raise Interrupt, "interrupt a dead condition variable"
63 def test_condvar_wait_and_broadcast
66 mutex = Thread::Mutex.new
67 condvar = Thread::ConditionVariable.new
70 nr_threads.times do |i|
71 threads[i] = Thread.new do
86 nr_threads.times do |i|
91 assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result
97 def test_condvar_wait_deadlock
98 assert_in_out_err([], <<-INPUT, /\Afatal\nNo live threads left\. Deadlock/, [])
99 mutex = Thread::Mutex.new
100 cv = Thread::ConditionVariable.new
108 rescue Exception => e
117 def test_condvar_wait_deadlock_2
120 mutex = Thread::Mutex.new
121 condvar = Thread::ConditionVariable.new
123 nr_threads.times do |i|
127 threads[i] = Thread.new do
135 assert_raise(Timeout::Error) do
136 Timeout.timeout(0.1) { condvar.wait mutex }
143 def test_condvar_timed_wait
144 mutex = Thread::Mutex.new
145 condvar = Thread::ConditionVariable.new
153 woken = condvar.wait(mutex, timeout)
155 locked = mutex.locked?
161 assert_operator(timeout*0.9, :<, t)
166 def test_condvar_nolock
167 mutex = Thread::Mutex.new
168 condvar = Thread::ConditionVariable.new
170 assert_raise(ThreadError) {condvar.wait(mutex)}
173 def test_condvar_nolock_2
174 mutex = Thread::Mutex.new
175 condvar = Thread::ConditionVariable.new
178 assert_raise(ThreadError) {condvar.wait(mutex)}
182 def test_condvar_nolock_3
183 mutex = Thread::Mutex.new
184 condvar = Thread::ConditionVariable.new
187 assert_raise(ThreadError) {condvar.wait(mutex, 0.1)}
191 def test_condvar_empty_signal
192 mutex = Thread::Mutex.new
193 condvar = Thread::ConditionVariable.new
195 assert_nothing_raised(Exception) { mutex.synchronize {condvar.signal} }
198 def test_condvar_empty_broadcast
199 mutex = Thread::Mutex.new
200 condvar = Thread::ConditionVariable.new
202 assert_nothing_raised(Exception) { mutex.synchronize {condvar.broadcast} }
206 bug9440 = '[ruby-core:59961] [Bug #9440]'
207 condvar = Thread::ConditionVariable.new
208 assert_raise(NoMethodError, bug9440) do
213 (DumpableCV = ConditionVariable.dup).class_eval {remove_method :marshal_dump}
216 bug9674 = '[ruby-core:61677] [Bug #9674]'
217 condvar = Thread::ConditionVariable.new
218 assert_raise_with_message(TypeError, /#{ConditionVariable}/, bug9674) do
219 Marshal.dump(condvar)
222 condvar = DumpableCV.new
223 assert_raise(TypeError, bug9674) do
224 Marshal.dump(condvar)
228 def test_condvar_fork
229 mutex = Thread::Mutex.new
230 condvar = Thread::ConditionVariable.new
231 thrs = (1..10).map do
232 Thread.new { mutex.synchronize { condvar.wait(mutex) } }
234 thrs.each { 3.times { Thread.pass } }
237 mutex.synchronize { condvar.wait(mutex) }
241 mutex.synchronize { condvar.broadcast }
243 exit!(th.value == :ok ? 0 : 1)
245 _, s = Process.waitpid2(pid)
246 assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]'
248 mutex.synchronize { condvar.broadcast }
249 thrs.delete_if { |t| t.join(0.01) }
251 end if Process.respond_to?(:fork)