mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Move spec/rubyspec to spec/ruby for consistency
* Other ruby implementations use the spec/ruby directory. [Misc #13792] [ruby-core:82287] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
75bfc6440d
commit
1d15d5f080
4370 changed files with 0 additions and 0 deletions
176
spec/ruby/core/thread/shared/exit.rb
Normal file
176
spec/ruby/core/thread/shared/exit.rb
Normal file
|
@ -0,0 +1,176 @@
|
|||
describe :thread_exit, shared: true do
|
||||
before :each do
|
||||
ScratchPad.clear
|
||||
end
|
||||
|
||||
it "kills sleeping thread" do
|
||||
sleeping_thread = Thread.new do
|
||||
sleep
|
||||
ScratchPad.record :after_sleep
|
||||
end
|
||||
Thread.pass while sleeping_thread.status and sleeping_thread.status != "sleep"
|
||||
sleeping_thread.send(@method)
|
||||
sleeping_thread.join
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
|
||||
it "kills current thread" do
|
||||
thread = Thread.new do
|
||||
Thread.current.send(@method)
|
||||
ScratchPad.record :after_sleep
|
||||
end
|
||||
thread.join
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
|
||||
it "runs ensure clause" do
|
||||
thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record :in_ensure_clause }
|
||||
thread.join
|
||||
ScratchPad.recorded.should == :in_ensure_clause
|
||||
end
|
||||
|
||||
it "runs nested ensure clauses" do
|
||||
ScratchPad.record []
|
||||
@outer = Thread.new do
|
||||
begin
|
||||
@inner = Thread.new do
|
||||
begin
|
||||
sleep
|
||||
ensure
|
||||
ScratchPad << :inner_ensure_clause
|
||||
end
|
||||
end
|
||||
sleep
|
||||
ensure
|
||||
ScratchPad << :outer_ensure_clause
|
||||
@inner.send(@method)
|
||||
@inner.join
|
||||
end
|
||||
end
|
||||
Thread.pass while @outer.status and @outer.status != "sleep"
|
||||
Thread.pass until @inner
|
||||
Thread.pass while @inner.status and @inner.status != "sleep"
|
||||
@outer.send(@method)
|
||||
@outer.join
|
||||
ScratchPad.recorded.should include(:inner_ensure_clause)
|
||||
ScratchPad.recorded.should include(:outer_ensure_clause)
|
||||
end
|
||||
|
||||
it "does not set $!" do
|
||||
thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record $! }
|
||||
thread.join
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
|
||||
it "cannot be rescued" do
|
||||
thread = Thread.new do
|
||||
begin
|
||||
Thread.current.send(@method)
|
||||
rescue Exception
|
||||
ScratchPad.record :in_rescue
|
||||
end
|
||||
ScratchPad.record :end_of_thread_block
|
||||
end
|
||||
|
||||
thread.join
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
|
||||
with_feature :fiber do
|
||||
it "kills the entire thread when a fiber is active" do
|
||||
t = Thread.new do
|
||||
Fiber.new do
|
||||
sleep
|
||||
end.resume
|
||||
ScratchPad.record :fiber_resumed
|
||||
end
|
||||
Thread.pass while t.status and t.status != "sleep"
|
||||
t.send(@method)
|
||||
t.join
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
end
|
||||
|
||||
# This spec is a mess. It fails randomly, it hangs on MRI, it needs to be removed
|
||||
quarantine! do
|
||||
it "killing dying running does nothing" do
|
||||
in_ensure_clause = false
|
||||
exit_loop = true
|
||||
t = ThreadSpecs.dying_thread_ensures do
|
||||
in_ensure_clause = true
|
||||
loop { if exit_loop then break end }
|
||||
ScratchPad.record :after_stop
|
||||
end
|
||||
|
||||
Thread.pass until in_ensure_clause == true
|
||||
10.times { t.send(@method); Thread.pass }
|
||||
exit_loop = true
|
||||
t.join
|
||||
ScratchPad.recorded.should == :after_stop
|
||||
end
|
||||
end
|
||||
|
||||
quarantine! do
|
||||
|
||||
it "propogates inner exception to Thread.join if there is an outer ensure clause" do
|
||||
thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { }
|
||||
lambda { thread.join }.should raise_error(RuntimeError, "In dying thread")
|
||||
end
|
||||
|
||||
it "runs all outer ensure clauses even if inner ensure clause raises exception" do
|
||||
ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record :in_outer_ensure_clause }
|
||||
ScratchPad.recorded.should == :in_outer_ensure_clause
|
||||
end
|
||||
|
||||
it "sets $! in outer ensure clause if inner ensure clause raises exception" do
|
||||
ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record $! }
|
||||
ScratchPad.recorded.to_s.should == "In dying thread"
|
||||
end
|
||||
end
|
||||
|
||||
it "can be rescued by outer rescue clause when inner ensure clause raises exception" do
|
||||
thread = Thread.new do
|
||||
begin
|
||||
begin
|
||||
Thread.current.send(@method)
|
||||
ensure
|
||||
raise "In dying thread"
|
||||
end
|
||||
rescue Exception
|
||||
ScratchPad.record $!
|
||||
end
|
||||
:end_of_thread_block
|
||||
end
|
||||
|
||||
thread.value.should == :end_of_thread_block
|
||||
ScratchPad.recorded.to_s.should == "In dying thread"
|
||||
end
|
||||
|
||||
it "is deferred if ensure clause does Thread.stop" do
|
||||
ThreadSpecs.wakeup_dying_sleeping_thread(@method) { Thread.stop; ScratchPad.record :after_sleep }
|
||||
ScratchPad.recorded.should == :after_sleep
|
||||
end
|
||||
|
||||
# Hangs on 1.8.6.114 OS X, possibly also on Linux
|
||||
quarantine! do
|
||||
it "is deferred if ensure clause sleeps" do
|
||||
ThreadSpecs.wakeup_dying_sleeping_thread(@method) { sleep; ScratchPad.record :after_sleep }
|
||||
ScratchPad.recorded.should == :after_sleep
|
||||
end
|
||||
end
|
||||
|
||||
# This case occurred in JRuby where native threads are used to provide
|
||||
# the same behavior as MRI green threads. Key to this issue was the fact
|
||||
# that the thread which called #exit in its block was also being explicitly
|
||||
# sent #join from outside the thread. The 100.times provides a certain
|
||||
# probability that the deadlock will occur. It was sufficient to reliably
|
||||
# reproduce the deadlock in JRuby.
|
||||
it "does not deadlock when called from within the thread while being joined from without" do
|
||||
100.times do
|
||||
t = Thread.new { Thread.stop; Thread.current.send(@method) }
|
||||
Thread.pass while t.status and t.status != "sleep"
|
||||
t.wakeup.should == t
|
||||
t.join.should == t
|
||||
end
|
||||
end
|
||||
end
|
41
spec/ruby/core/thread/shared/start.rb
Normal file
41
spec/ruby/core/thread/shared/start.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
describe :thread_start, shared: true do
|
||||
before :each do
|
||||
ScratchPad.clear
|
||||
end
|
||||
|
||||
it "raises an ArgumentError if not passed a block" do
|
||||
lambda {
|
||||
Thread.send(@method)
|
||||
}.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "spawns a new Thread running the block" do
|
||||
run = false
|
||||
t = Thread.send(@method) { run = true }
|
||||
t.should be_kind_of(Thread)
|
||||
t.join
|
||||
|
||||
run.should be_true
|
||||
end
|
||||
|
||||
it "respects Thread subclasses" do
|
||||
c = Class.new(Thread)
|
||||
t = c.send(@method) { }
|
||||
t.should be_kind_of(c)
|
||||
|
||||
t.join
|
||||
end
|
||||
|
||||
it "does not call #initialize" do
|
||||
c = Class.new(Thread) do
|
||||
def initialize
|
||||
ScratchPad.record :bad
|
||||
end
|
||||
end
|
||||
|
||||
t = c.send(@method) { }
|
||||
t.join
|
||||
|
||||
ScratchPad.recorded.should == nil
|
||||
end
|
||||
end
|
61
spec/ruby/core/thread/shared/wakeup.rb
Normal file
61
spec/ruby/core/thread/shared/wakeup.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
describe :thread_wakeup, shared: true do
|
||||
it "can interrupt Kernel#sleep" do
|
||||
exit_loop = false
|
||||
after_sleep1 = false
|
||||
after_sleep2 = false
|
||||
|
||||
t = Thread.new do
|
||||
while true
|
||||
break if exit_loop == true
|
||||
Thread.pass
|
||||
end
|
||||
|
||||
sleep
|
||||
after_sleep1 = true
|
||||
|
||||
sleep
|
||||
after_sleep2 = true
|
||||
end
|
||||
|
||||
10.times { t.send(@method); Thread.pass }
|
||||
t.status.should_not == "sleep"
|
||||
|
||||
exit_loop = true
|
||||
|
||||
10.times { sleep 0.1 if t.status and t.status != "sleep" }
|
||||
after_sleep1.should == false # t should be blocked on the first sleep
|
||||
t.send(@method)
|
||||
|
||||
10.times { sleep 0.1 if after_sleep1 != true }
|
||||
10.times { sleep 0.1 if t.status and t.status != "sleep" }
|
||||
after_sleep2.should == false # t should be blocked on the second sleep
|
||||
t.send(@method)
|
||||
|
||||
t.join
|
||||
end
|
||||
|
||||
it "does not result in a deadlock" do
|
||||
t = Thread.new do
|
||||
100.times { Thread.stop }
|
||||
end
|
||||
|
||||
while t.status
|
||||
begin
|
||||
t.send(@method)
|
||||
rescue ThreadError
|
||||
# The thread might die right after.
|
||||
t.status.should == false
|
||||
end
|
||||
Thread.pass
|
||||
end
|
||||
|
||||
t.status.should == false
|
||||
t.join
|
||||
end
|
||||
|
||||
it "raises a ThreadError when trying to wake up a dead thread" do
|
||||
t = Thread.new { 1 }
|
||||
t.join
|
||||
lambda { t.send @method }.should raise_error(ThreadError)
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue