diff options
Diffstat (limited to 'bootstraptest/test_thread.rb')
| -rw-r--r-- | bootstraptest/test_thread.rb | 234 |
1 files changed, 179 insertions, 55 deletions
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb index 54544df45e..7ff5bb4a38 100644 --- a/bootstraptest/test_thread.rb +++ b/bootstraptest/test_thread.rb @@ -1,4 +1,14 @@ -# Thread and Fiber +show_limit %q{ + threads = [] + begin + threads << Thread.new{sleep} + + raise Exception, "skipping" if threads.count >= 10_000 + rescue Exception => error + puts "Thread count: #{threads.count} (#{error})" + break + end while true +} if false # disable to pass CI assert_equal %q{ok}, %q{ Thread.new{ @@ -10,7 +20,8 @@ assert_equal %q{ok}, %q{ :ok }.value } -assert_equal %q{20100}, %q{ +assert_equal %q{ok}, %q{ +begin v = 0 (1..200).map{|i| Thread.new{ @@ -19,10 +30,14 @@ assert_equal %q{20100}, %q{ }.each{|t| v += t.value } - v + v == 20100 ? :ok : v +rescue ThreadError => e + :ok if /can't create Thread/ =~ e.message +end } -assert_equal %q{5000}, %q{ - 5000.times{|e| +assert_equal %q{ok}, %q{ +begin + :ok if 5000 == 5000.times{|e| (1..2).map{ Thread.new{ } @@ -30,9 +45,13 @@ assert_equal %q{5000}, %q{ e.join() } } +rescue ThreadError => e + /can't create Thread/ =~ e.message ? :ok : e.message +end } -assert_equal %q{5000}, %q{ - 5000.times{|e| +assert_equal %q{ok}, %q{ +begin + :ok if 5000 == 5000.times{|e| (1..2).map{ Thread.new{ } @@ -40,14 +59,21 @@ assert_equal %q{5000}, %q{ e.join(1000000000) } } +rescue ThreadError => e + /can't create Thread/ =~ e.message ? :ok : e.message +end } -assert_equal %q{5000}, %q{ - 5000.times{ +assert_equal %q{ok}, %q{ +begin + :ok if 5000 == 5000.times{ t = Thread.new{} while t.alive? Thread.pass end } +rescue NoMemoryError + :ok +end } assert_equal %q{100}, %q{ 100.times{ @@ -77,7 +103,7 @@ assert_equal %q{ok}, %q{ ans = :ok end } - Thread.pass + Thread.pass until t.stop? t.kill t.join ans @@ -174,9 +200,9 @@ assert_equal %q{[true, nil, true]}, %q{ $a = $~ Thread.new{ $b = $~ - /a/ =~ 'a' + /b/ =~ 'b' $c = $~ - } + }.join $d = $~ [$a == $d, $b, $c != $d] } @@ -188,19 +214,19 @@ assert_equal %q{11}, %q{ Thread.current[:a] }.value + Thread.current[:a] } -assert_equal %q{100}, %q{ -begin - 100.times do |i| - begin - Thread.start(Thread.current) {|u| u.raise } - raise - rescue - ensure +assert_normal_exit %q{ + begin + 100.times do |i| + begin + th = Thread.start(Thread.current) {|u| u.raise } + raise + rescue + ensure + th.join + end end + rescue end -rescue - 100 -end }, '[ruby-dev:31371]' assert_equal 'true', %{ @@ -216,9 +242,22 @@ assert_equal 'true', %{ end } +assert_equal 'true', %{ + Thread.new{}.join + begin + Process.waitpid2 fork{ + Thread.new{ + sleep 0.1 + }.join + } + true + rescue NotImplementedError + true + end +} + assert_equal 'ok', %{ - open("zzz.rb", "w") do |f| - f.puts <<-END + File.write("zzz_t1.rb", <<-END) begin Thread.new { fork { GC.start } }.join pid, status = Process.wait2 @@ -227,22 +266,21 @@ assert_equal 'ok', %{ $result = :ok end END - end - require "zzz.rb" + require "./zzz_t1.rb" $result } assert_finish 3, %{ - th = Thread.new {sleep 2} - th.join(1) + th = Thread.new {sleep 0.2} + th.join(0.1) th.join } assert_finish 3, %{ require 'timeout' - th = Thread.new {sleep 2} + th = Thread.new {sleep 0.2} begin - Timeout.timeout(1) {th.join} + Timeout.timeout(0.1) {th.join} rescue Timeout::Error end th.join @@ -267,8 +305,8 @@ assert_normal_exit %q{ assert_equal 'ok', %q{ def m - t = Thread.new { while true do // =~ "" end } - sleep 0.1 + t = Thread.new { while true; // =~ "" end } + sleep 0.01 10.times { if /((ab)*(ab)*)*(b)/ =~ "ab"*7 return :ng if !$4 @@ -283,10 +321,6 @@ assert_equal 'ok', %q{ }, '[ruby-dev:34492]' assert_normal_exit %q{ - at_exit { Fiber.new{}.resume } -} - -assert_normal_exit %q{ g = enum_for(:local_variables) loop { g.next } }, '[ruby-dev:34128]' @@ -312,10 +346,6 @@ assert_normal_exit %q{ }, '[ruby-dev:34128]' assert_normal_exit %q{ - Fiber.new(&Object.method(:class_eval)).resume("foo") -}, '[ruby-dev:34128]' - -assert_normal_exit %q{ Thread.new("foo", &Object.method(:class_eval)).join }, '[ruby-dev:34128]' @@ -331,9 +361,10 @@ assert_equal 'ok', %q{ assert_equal 'ok', %q{ begin - m1, m2 = Mutex.new, Mutex.new - Thread.new { m1.lock; sleep 1; m2.lock } - m2.lock; sleep 1; m1.lock + m1, m2 = Thread::Mutex.new, Thread::Mutex.new + f1 = f2 = false + Thread.new { m1.lock; f2 = true; sleep 0.001 until f1; m2.lock } + m2.lock; f1 = true; sleep 0.001 until f2; m1.lock :ng rescue Exception :ok @@ -341,34 +372,34 @@ assert_equal 'ok', %q{ } assert_equal 'ok', %q{ - m = Mutex.new - Thread.new { m.lock }; sleep 1; m.lock + m = Thread::Mutex.new + Thread.new { m.lock }; sleep 0.1; m.lock :ok } assert_equal 'ok', %q{ - m = Mutex.new + m = Thread::Mutex.new Thread.new { m.lock }; m.lock :ok } assert_equal 'ok', %q{ - m = Mutex.new + m = Thread::Mutex.new Thread.new { m.lock }.join; m.lock :ok } assert_equal 'ok', %q{ - m = Mutex.new - Thread.new { m.lock; sleep 2 } - sleep 1; m.lock + m = Thread::Mutex.new + Thread.new { m.lock; sleep 0.2 } + sleep 0.1; m.lock :ok } assert_equal 'ok', %q{ - m = Mutex.new - Thread.new { m.lock; sleep 2; m.unlock } - sleep 1; m.lock + m = Thread::Mutex.new + Thread.new { m.lock; sleep 0.2; m.unlock } + sleep 0.1; m.lock :ok } @@ -380,8 +411,101 @@ assert_equal 'ok', %q{ assert_equal 'ok', %q{ begin - 10000.times { Thread.new(true) {|x| x == false } } + 100.times{ + (1..100).map{ Thread.new(true) {|x| x == false } }.each{|th| th.join} + } rescue NoMemoryError, StandardError end :ok } + +assert_equal 'ok', %{ + File.write("zzz_t2.rb", <<-'end;') # do + begin + m = Thread::Mutex.new + parent = Thread.current + th1 = Thread.new { m.lock; sleep } + sleep 0.01 until th1.stop? + Thread.new do + sleep 0.01 until parent.stop? + begin + fork { GC.start } + rescue Exception + parent.raise $! + end + th1.run + end + m.lock + pid, status = Process.wait2 + $result = status.success? ? :ok : :ng + rescue NotImplementedError + $result = :ok + end + end; + require "./zzz_t2.rb" + $result +} + +assert_finish 3, %q{ + require 'thread' + + lock = Thread::Mutex.new + cond = Thread::ConditionVariable.new + t = Thread.new do + lock.synchronize do + cond.wait(lock) + end + end + + begin + pid = fork do + # Child + STDOUT.write "This is the child process.\n" + STDOUT.write "Child process exiting.\n" + end + Process.waitpid(pid) + rescue NotImplementedError + end +}, '[ruby-core:23572]' + +assert_equal 'ok', %q{ + begin + Process.waitpid2(fork {})[1].success? ? 'ok' : 'ng' + rescue NotImplementedError + 'ok' + end +} + +assert_equal 'foo', %q{ + i = 0 + Thread.start {sleep 1; exit!} + f = proc {|s, c| /#{c.call; s}/o } + th2 = Thread.new { + sleep 0.01 until i == 1 + i = 2 + f.call("bar", proc {sleep 2}); + nil + } + th1 = Thread.new { + f.call("foo", proc {i = 1; sleep 0.01 until i == 2; sleep 0.01}) + nil + } + [th1, th2].each {|t| t.join } + GC.start + f.call.source +} + +assert_normal_exit %q{ + class C + def inspect + sleep 0.5 + 'C!!' + end + end + Thread.new{ + loop{ + p C.new + } + } + sleep 0.1 +}, timeout: 5 |
