ruby-changes:51923
From: hsbt <ko1@a...>
Date: Tue, 31 Jul 2018 12:49:43 +0900 (JST)
Subject: [ruby-changes:51923] hsbt:r64137 (trunk): Move obsoleted test/thread/test_*.rb with the current implementation.
hsbt 2018-07-31 12:49:38 +0900 (Tue, 31 Jul 2018) New Revision: 64137 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64137 Log: Move obsoleted test/thread/test_*.rb with the current implementation. * test/ruby/test_thread_{cv,queue}.rb: Move under the test/ruby directory. and rename TestThread* from Test*. * test/test_sync.rb: Move toplevel of test diretory because sync is still standard library. Added files: trunk/test/ruby/test_thread_cv.rb trunk/test/ruby/test_thread_queue.rb trunk/test/test_sync.rb Removed directories: trunk/test/thread/ Index: test/thread/test_cv.rb =================================================================== --- test/thread/test_cv.rb (revision 64136) +++ test/thread/test_cv.rb (nonexistent) @@ -1,247 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/test/thread/test_cv.rb#L0 -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' - -class TestConditionVariable < Test::Unit::TestCase - ConditionVariable = Thread::ConditionVariable - Mutex = Thread::Mutex - - def test_initialized - assert_raise(TypeError) { - ConditionVariable.allocate.wait(nil) - } - end - - def test_condvar_signal_and_wait - mutex = Mutex.new - condvar = ConditionVariable.new - result = [] - mutex.synchronize do - t = Thread.new do - mutex.synchronize do - result << 1 - condvar.signal - end - end - - result << 0 - condvar.wait(mutex) - result << 2 - t.join - end - assert_equal([0, 1, 2], result) - end - - def test_condvar_wait_exception_handling - skip "MJIT thread is unexpected for this test, especially with --jit-wait" if RubyVM::MJIT.enabled? - - # Calling wait in the only thread running should raise a ThreadError of - # 'stopping only thread' - mutex = Mutex.new - condvar = ConditionVariable.new - - locked = false - thread = Thread.new do - Thread.current.abort_on_exception = false - mutex.synchronize do - assert_raise(Interrupt) { - condvar.wait(mutex) - } - locked = mutex.locked? - end - end - - until thread.stop? - sleep(0.1) - end - - thread.raise Interrupt, "interrupt a dead condition variable" - thread.join - assert(locked) - end - - def test_condvar_wait_and_broadcast - nr_threads = 3 - threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new - result = [] - - nr_threads.times do |i| - threads[i] = Thread.new do - mutex.synchronize do - result << "C1" - condvar.wait mutex - result << "C2" - end - end - end - sleep 0.1 - mutex.synchronize do - result << "P1" - condvar.broadcast - result << "P2" - end - Timeout.timeout(5) do - nr_threads.times do |i| - threads[i].join - end - end - - assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result - end - - def test_condvar_wait_deadlock - assert_in_out_err([], <<-INPUT, /\Afatal\nNo live threads left\. Deadlock/, []) - mutex = Mutex.new - cv = ConditionVariable.new - - klass = nil - mesg = nil - begin - mutex.lock - cv.wait mutex - mutex.unlock - rescue Exception => e - klass = e.class - mesg = e.message - end - puts klass - print mesg -INPUT - end - - def test_condvar_wait_deadlock_2 - nr_threads = 3 - threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new - - nr_threads.times do |i| - if (i != 0) - mutex.unlock - end - threads[i] = Thread.new do - mutex.synchronize do - condvar.wait mutex - end - end - mutex.lock - end - - assert_raise(Timeout::Error) do - Timeout.timeout(0.1) { condvar.wait mutex } - end - mutex.unlock - threads.each(&:kill) - threads.each(&:join) - end - - def test_condvar_timed_wait - mutex = Mutex.new - condvar = ConditionVariable.new - timeout = 0.3 - locked = false - - t0 = Time.now - mutex.synchronize do - begin - condvar.wait(mutex, timeout) - ensure - locked = mutex.locked? - end - end - t1 = Time.now - t = t1-t0 - - assert_operator(timeout*0.9, :<, t) - assert(locked) - end - - def test_condvar_nolock - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_raise(ThreadError) {condvar.wait(mutex)} - end - - def test_condvar_nolock_2 - mutex = Mutex.new - condvar = ConditionVariable.new - - Thread.new do - assert_raise(ThreadError) {condvar.wait(mutex)} - end.join - end - - def test_condvar_nolock_3 - mutex = Mutex.new - condvar = ConditionVariable.new - - Thread.new do - assert_raise(ThreadError) {condvar.wait(mutex, 0.1)} - end.join - end - - def test_condvar_empty_signal - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_nothing_raised(Exception) { mutex.synchronize {condvar.signal} } - end - - def test_condvar_empty_broadcast - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_nothing_raised(Exception) { mutex.synchronize {condvar.broadcast} } - end - - def test_dup - bug9440 = '[ruby-core:59961] [Bug #9440]' - condvar = ConditionVariable.new - assert_raise(NoMethodError, bug9440) do - condvar.dup - end - end - - (DumpableCV = ConditionVariable.dup).class_eval {remove_method :marshal_dump} - - def test_dump - bug9674 = '[ruby-core:61677] [Bug #9674]' - condvar = ConditionVariable.new - assert_raise_with_message(TypeError, /#{ConditionVariable}/, bug9674) do - Marshal.dump(condvar) - end - - condvar = DumpableCV.new - assert_raise(TypeError, bug9674) do - Marshal.dump(condvar) - end - end - - def test_condvar_fork - mutex = Mutex.new - condvar = ConditionVariable.new - thrs = (1..10).map do - Thread.new { mutex.synchronize { condvar.wait(mutex) } } - end - thrs.each { 3.times { Thread.pass } } - pid = fork do - th = Thread.new do - mutex.synchronize { condvar.wait(mutex) } - :ok - end - until th.join(0.01) - mutex.synchronize { condvar.broadcast } - end - exit!(th.value == :ok ? 0 : 1) - end - _, s = Process.waitpid2(pid) - assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' - until thrs.empty? - mutex.synchronize { condvar.broadcast } - thrs.delete_if { |t| t.join(0.01) } - end - end if Process.respond_to?(:fork) -end Property changes on: test/thread/test_cv.rb ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -LF \ No newline at end of property Index: test/thread/test_sync.rb =================================================================== --- test/thread/test_sync.rb (revision 64136) +++ test/thread/test_sync.rb (nonexistent) @@ -1,69 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/test/thread/test_sync.rb#L0 -# frozen_string_literal: false -require 'test/unit' -require 'sync' -require 'timeout' - -class SyncTest < Test::Unit::TestCase - class Tester - include Sync_m - end - - def test_sync_lock_and_wakeup - tester = Tester.new - - tester.sync_lock(:EX) - - t = Thread.new { tester.sync_lock(:EX) } - - sleep 0.1 until t.stop? - t.wakeup - sleep 0.1 until t.stop? - - assert_equal(tester.sync_waiting.uniq, tester.sync_waiting) - ensure - t.kill - t.join - end - - def test_sync_upgrade_and_wakeup - tester = Tester.new - tester.sync_lock(:SH) - - t = Thread.new do - tester.sync_lock(:SH) - tester.sync_lock(:EX) - end - - sleep 0.1 until t.stop? - t.wakeup - sleep 0.1 until t.stop? - - tester.sync_upgrade_waiting.each { |ary| - assert(!tester.sync_waiting.include?(ary[0])) - } - assert_equal(tester.sync_waiting.uniq, tester.sync_waiting) - assert_equal(tester.sync_waiting, []) - ensure - t.kill - t.join - end - - def test_sync_lock_and_raise - tester= Tester.new - tester.sync_lock(:EX) - - t = Thread.new { - assert_raise(RuntimeError) { - tester.sync_lock(:EX) - } - } - - sleep 0.1 until t.stop? - sleep 1 if RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait - t.raise - t.join - - assert_equal(tester.sync_waiting.uniq, tester.sync_waiting) - assert_equal(tester.sync_waiting, []) - end -end Property changes on: test/thread/test_sync.rb ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -LF \ No newline at end of property Index: test/thread/test_queue.rb =================================================================== --- test/thread/test_queue.rb (revision 64136) +++ test/thread/test_queue.rb (nonexistent) @@ -1,616 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/test/thread/test_queue.rb#L0 -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' -require 'timeout' - -class TestQueue < Test::Unit::TestCase - Queue = Thread::Queue - SizedQueue = Thread::SizedQueue - - def test_queue_initialized - assert_raise(TypeError) { - Queue.allocate.push(nil) - } - end - - def test_sized_queue_initialized - assert_raise(TypeError) { - SizedQueue.allocate.push(nil) - } - end - - def test_queue - grind(5, 1000, 15, Queue) - end - - def test_sized_queue - grind(5, 1000, 15, SizedQueue, 1000) - end - - def grind(num_threads, num_objects, num_iterations, klass, *args) - from_workers = klass.new(*args) - to_workers = klass.new(*args) - - workers = (1..num_threads).map { - Thread.new { - while object = to_workers.pop - from_workers.push object - end - } - } - - Thread.new { - num_iterations.times { - num_objects.times { to_workers.push 99 } - num_objects.times { from_workers.pop } - } - }.join - - # close the queue the old way to test for backwards-compatibility - num_threads.times { to_workers.push nil } - workers.each { |t| t.join } - - assert_equal 0, from_workers.size - assert_equal 0, to_workers.size - end - - def test_sized_queue_initialize - q = SizedQueue.new(1) - assert_equal 1, q.max - assert_raise(ArgumentError) { SizedQueue.new(0) } - assert_raise(ArgumentError) { SizedQueue.new(-1) } - end - - def test_sized_queue_assign_max - q = SizedQueue.new(2) - assert_equal(2, q.max) - q.max = 1 - assert_equal(1, q.max) - assert_raise(ArgumentError) { q.max = 0 } - assert_equal(1, q.max) - assert_raise(ArgumentError) { q.max = -1 } - assert_equal(1, q.max) - - before = q.max - q.max.times { q << 1 } - t1 = Thread.new { q << 1 } - sleep 0.01 until t1.stop? - q.max = q.max + 1 - assert_equal before + 1, q.max - ensure - t1.join if t1 - end - - def test_queue_pop_interrupt - q = Queue.new - t1 = Thread.new { q.pop } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_queue_pop_non_block - q = Queue.new - assert_raise_with_message(ThreadError, /empty/) do - q.pop(true) - end - end - - def test_sized_queue_pop_interrupt - q = SizedQueue.new(1) - t1 = Thread.new { q.pop } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_sized_queue_pop_non_block - q = SizedQueue.new(1) - assert_raise_with_message(ThreadError, /empty/) do - q.pop(true) - end - end - - def test_sized_queue_push_interrupt - q = SizedQueue.new(1) - q.push(1) - assert_raise_with_message(ThreadError, /full/) do - q.push(2, true) - end - end - - def test_sized_queue_push_non_block - q = SizedQueue.new(1) - q.push(1) - t1 = Thread.new { q.push(2) } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_thr_kill - bug5343 = '[ruby-core:39634]' - Dir.mktmpdir {|d| - timeout = 60 - total_count = 250 - begin - assert_normal_exit(<<-"_eom", bug5343, {:timeout => timeout, :chdir=>d}) - #{total_count}.times do |i| - open("test_thr_kill_count", "w") {|f| f.puts i } - queue = Queue.new - r, w = IO.pipe - th = Thread.start { - queue.push(nil) - r.read 1 - } - queue.pop - th.kill - th.join - end - _eom - rescue Timeout::Error - count = File.read("#{d}/test_thr_kill_count").to_i - flunk "only #{count}/#{total_count} done in #{timeout} seconds." - end - } - end - - def test_queue_push_return_value - q = Queue.new - retval = q.push(1) - assert_same q, retval - end - - def test_queue_clear_return_value - q = Queue.new - retval = q.clear - assert_same q, retval - end - - def test_sized_queue_clear - # Fill queue, then test that SizedQueue#clear wakes up all waiting threads - sq = SizedQueue.new(2) - 2.times { sq << 1 } - - t1 = Thread.new do - sq << 1 - end - - t2 = Thread.new do - sq << 1 - end - - t3 = Thread.new do - Thread.pass - sq.clear - end - - [t3, t2, t1].each(&:join) - assert_equal sq.length, 2 - end - - def test_sized_queue_push_return_value - q = SizedQueue.new(1) - retval = q.push(1) - assert_same q, retval - end - - def test_sized_queue_clear_return_value - q = SizedQueue.new(1) - retval = q.clear - assert_same q, retval - end - - def test_sized_queue_throttle - q = SizedQueue.new(1) - i = 0 - consumer = Thread.new do - while q.pop - i += 1 - Thread.pass - end - end - nprod = 4 - npush = 100 - - producer = nprod.times.map do - Thread.new do - npush.times { q.push(true) } - end - end - producer.each(&:join) - q.push(nil) - consumer.join - assert_equal(nprod * npush, i) - end - - def test_queue_thread_raise - q = Queue.new - th1 = Thread.new do - begin - q.pop - rescue RuntimeError - sleep - end - end - th2 = Thread.new do - sleep 0.1 - q.pop - end - sleep 0.1 - th1.raise - sleep 0.1 - q << :s - assert_nothing_raised(Timeout::Error) do - Timeout.timeout(1) { th2.join } - end - ensure - [th1, th2].each do |th| - if th and th.alive? - th.wakeup - th.join - end - end - end - - def test_dup - bug9440 = '[ruby-core:59961] [Bug #9440]' - q = Queue.new - assert_raise(NoMethodError, bug9440) do - q.dup - end - end - - (DumpableQueue = Queue.dup).class_eval {remove_method :marshal_dump} - - def test_dump - bug9674 = '[ruby-core:61677] [Bug #9674]' - q = Queue.new - assert_raise_with_message(TypeError, /#{Queue}/, bug9674) do - Marshal.dump(q) - end - - sq = SizedQueue.new(1) - assert_raise_with_message(TypeError, /#{SizedQueue}/, bug9674) do - Marshal.dump(sq) - end - - q = DumpableQueue.new - assert_raise(TypeError, bug9674) do - Marshal.dump(q) - end - end - - def test_close - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| - q = qcreate.call - assert_equal false, q.closed? - q << :something - assert_equal q, q.close - assert q.closed? - assert_raise_with_message(ClosedQueueError, /closed/){q << :nothing} - assert_equal q.pop, :something - assert_nil q.pop - assert_nil q.pop - # non-blocking - assert_raise_with_message(ThreadError, /queue empty/){q.pop(non_block=true)} - end - end - - # test that waiting producers are woken up on close - def close_wakeup( num_items, num_threads, &qcreate ) - raise "This test won't work with num_items(#{num_items}) >= num_threads(#{num_threads})" if num_items >= num_threads - - # create the Queue - q = yield - threads = num_threads.times.map{Thread.new{q.pop}} - num_items.times{|i| q << i} - - # wait until queue empty - (Thread.pass; sleep 0.01) until q.size == 0 - - # close the queue so remaining threads will wake up - q.close - - # wait for them to go away - Thread.pass until threads.all?{|thr| thr.status == false} - - # check that they've gone away. Convert nil to -1 so we can sort and do the comparison - expected_values = [-1] * (num_threads - num_items) + num_items.times.to_a - assert_equal expected_values, threads.map{|thr| thr.value || -1 }.sort - end - - def test_queue_close_wakeup - close_wakeup(15, 18){Queue.new} - end - - def test_size_queue_close_wakeup - close_wakeup(5, 8){SizedQueue.new 9} - end - - def test_sized_queue_one_closed_interrupt - q = SizedQueue.new 1 - q << :one - t1 = Thread.new { q << :two } - sleep 0.01 until t1.stop? - q.close - - t1.kill.join - assert_equal 1, q.size - assert_equal :one, q.pop - assert q.empty?, "queue not empty" - end - - # make sure that shutdown state is handled properly by empty? for the non-blocking case - def test_empty_non_blocking - return - q = SizedQueue.new 3 - 3.times{|i| q << i} - - # these all block cos the queue is full - prod_threads = 4.times.map{|i| Thread.new{q << 3+i}} - sleep 0.01 until prod_threads.all?{|thr| thr.status == 'sleep'} - q.close - - items = [] - # sometimes empty? is false but pop will raise ThreadError('empty'), - # meaning a value is not immediately available but will be soon. - until q.empty? - items << q.pop(non_block=true) rescue nil - end - items.compact! - - assert_equal 7.times.to_a, items.sort - assert q.empty? - end - - def test_sized_queue_closed_push_non_blocking - q = SizedQueue.new 7 - q.close - assert_raise_with_message(ClosedQueueError, /queue closed/){q.push(non_block=true)} - end - - def test_blocked_pushers - q = SizedQueue.new 3 - prod_threads = 6.times.map do |i| - thr = Thread.new{ - Thread.current.report_on_exception = false - q << i - } - thr[:pc] = i - thr - end - - # wait until some producer threads have finished, and the other 3 are blocked - sleep 0.01 while prod_threads.reject{|t| t.status}.count < 3 - # this would ensure that all producer threads call push before close - # sleep 0.01 while prod_threads.select{|t| t.status == 'sleep'}.count < 3 - q.close - - # more than prod_threads - cons_threads = 10.times.map do |i| - thr = Thread.new{q.pop}; thr[:pc] = i; thr - end - - # values that came from the queue - popped_values = cons_threads.map &:value - - # wait untl all threads have finished - sleep 0.01 until prod_threads.find_all{|t| t.status}.count == 0 - - # pick only the producer threads that got in before close - successful_prod_threads = prod_threads.reject{|thr| thr.status == nil} - assert_nothing_raised{ successful_prod_threads.map(&:value) } - - # the producer threads that tried to push after q.close should all fail - unsuccessful_prod_threads = prod_threads - successful_prod_threads - unsuccessful_prod_threads.each do |thr| - assert_raise(ClosedQueueError){ thr.value } - end - - assert_equal cons_threads.size, popped_values.size - assert_equal 0, q.size - - # check that consumer threads with values match producers that called push before close - assert_equal successful_prod_threads.map{|thr| thr[:pc]}, popped_values.compact.sort - assert_nil q.pop - end - - def test_deny_pushers - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| - q = qcreate[] - synq = Queue.new - prod_threads = 20.times.map do |i| - Thread.new { - synq.pop - assert_raise(ClosedQueueError) { - q << i - } - } - end - q.close - synq.close # start producer threads - - prod_threads.each(&:join) - end - end - - # size should account for waiting pushers during shutdown - def sized_queue_size_close - q = SizedQueue.new 4 - 4.times{|i| q << i} - Thread.new{ q << 5 } - Thread.new{ q << 6 } - assert_equal 4, q.size - assert_equal 4, q.items - q.close - assert_equal 6, q.size - assert_equal 4, q.items - end - - def test_blocked_pushers_empty - q = SizedQueue.new 3 - prod_threads = 6.times.map do |i| - Thread.new{ - Thread.current (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/