empathy 0.0.1.RC0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +135 -0
- data/Rakefile +33 -0
- data/TESTING.rdoc +11 -0
- data/empathy.gemspec +23 -0
- data/empathy.mspec +34 -0
- data/lib/empathy.rb +162 -0
- data/lib/empathy/em/condition_variable.rb +57 -0
- data/lib/empathy/em/mutex.rb +70 -0
- data/lib/empathy/em/queue.rb +84 -0
- data/lib/empathy/em/thread.rb +363 -0
- data/lib/empathy/object.rb +19 -0
- data/lib/empathy/thread.rb +8 -0
- data/lib/empathy/version.rb +3 -0
- data/mspec/lib/mspec/empathy.rb +19 -0
- data/mspec/lib/mspec/guards/empathy.rb +10 -0
- data/rubyspec/core/kernel/fixtures/__method__.rb +25 -0
- data/rubyspec/core/kernel/fixtures/autoload_b.rb +5 -0
- data/rubyspec/core/kernel/fixtures/autoload_c.rb +5 -0
- data/rubyspec/core/kernel/fixtures/autoload_d.rb +5 -0
- data/rubyspec/core/kernel/fixtures/caller_fixture1.rb +42 -0
- data/rubyspec/core/kernel/fixtures/caller_fixture2.rb +26 -0
- data/rubyspec/core/kernel/fixtures/chomp.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chomp_f.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chop.rb +4 -0
- data/rubyspec/core/kernel/fixtures/chop_f.rb +4 -0
- data/rubyspec/core/kernel/fixtures/classes.rb +410 -0
- data/rubyspec/core/kernel/fixtures/eval_locals.rb +6 -0
- data/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb +12 -0
- data/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb +14 -0
- data/rubyspec/core/kernel/fixtures/test.rb +362 -0
- data/rubyspec/core/kernel/sleep_spec.rb +43 -0
- data/rubyspec/core/mutex/lock_spec.rb +8 -0
- data/rubyspec/core/mutex/locked_spec.rb +8 -0
- data/rubyspec/core/mutex/sleep_spec.rb +56 -0
- data/rubyspec/core/mutex/synchronize_spec.rb +8 -0
- data/rubyspec/core/mutex/try_lock_spec.rb +8 -0
- data/rubyspec/core/mutex/unlock_spec.rb +8 -0
- data/rubyspec/core/thread/abort_on_exception_spec.rb +126 -0
- data/rubyspec/core/thread/add_trace_func_spec.rb +7 -0
- data/rubyspec/core/thread/alive_spec.rb +60 -0
- data/rubyspec/core/thread/allocate_spec.rb +9 -0
- data/rubyspec/core/thread/backtrace_spec.rb +7 -0
- data/rubyspec/core/thread/critical_spec.rb +96 -0
- data/rubyspec/core/thread/current_spec.rb +15 -0
- data/rubyspec/core/thread/element_reference_spec.rb +53 -0
- data/rubyspec/core/thread/element_set_spec.rb +46 -0
- data/rubyspec/core/thread/exclusive_spec.rb +20 -0
- data/rubyspec/core/thread/exit_spec.rb +21 -0
- data/rubyspec/core/thread/fixtures/classes.rb +291 -0
- data/rubyspec/core/thread/fork_spec.rb +9 -0
- data/rubyspec/core/thread/group_spec.rb +5 -0
- data/rubyspec/core/thread/initialize_spec.rb +26 -0
- data/rubyspec/core/thread/inspect_spec.rb +48 -0
- data/rubyspec/core/thread/join_spec.rb +63 -0
- data/rubyspec/core/thread/key_spec.rb +64 -0
- data/rubyspec/core/thread/keys_spec.rb +47 -0
- data/rubyspec/core/thread/kill_spec.rb +21 -0
- data/rubyspec/core/thread/list_spec.rb +38 -0
- data/rubyspec/core/thread/main_spec.rb +10 -0
- data/rubyspec/core/thread/new_spec.rb +56 -0
- data/rubyspec/core/thread/pass_spec.rb +8 -0
- data/rubyspec/core/thread/priority_spec.rb +9 -0
- data/rubyspec/core/thread/raise_spec.rb +225 -0
- data/rubyspec/core/thread/run_spec.rb +9 -0
- data/rubyspec/core/thread/safe_level_spec.rb +6 -0
- data/rubyspec/core/thread/set_trace_func_spec.rb +7 -0
- data/rubyspec/core/thread/shared/exit.rb +173 -0
- data/rubyspec/core/thread/shared/start.rb +51 -0
- data/rubyspec/core/thread/shared/wakeup.rb +59 -0
- data/rubyspec/core/thread/start_spec.rb +9 -0
- data/rubyspec/core/thread/status_spec.rb +48 -0
- data/rubyspec/core/thread/stop_spec.rb +66 -0
- data/rubyspec/core/thread/terminate_spec.rb +11 -0
- data/rubyspec/core/thread/value_spec.rb +36 -0
- data/rubyspec/core/thread/wakeup_spec.rb +7 -0
- data/rubyspec/empathy_spec.rb +26 -0
- data/rubyspec/library/conditionvariable/broadcast_spec.rb +62 -0
- data/rubyspec/library/conditionvariable/signal_spec.rb +64 -0
- data/rubyspec/library/conditionvariable/wait_spec.rb +21 -0
- data/rubyspec/library/mutex/lock_spec.rb +10 -0
- data/rubyspec/library/mutex/locked_spec.rb +10 -0
- data/rubyspec/library/mutex/synchronize_spec.rb +10 -0
- data/rubyspec/library/mutex/try_lock_spec.rb +10 -0
- data/rubyspec/library/mutex/unlock_spec.rb +10 -0
- data/rubyspec/library/queue/append_spec.rb +7 -0
- data/rubyspec/library/queue/clear_spec.rb +15 -0
- data/rubyspec/library/queue/deq_spec.rb +7 -0
- data/rubyspec/library/queue/empty_spec.rb +15 -0
- data/rubyspec/library/queue/enq_spec.rb +7 -0
- data/rubyspec/library/queue/length_spec.rb +7 -0
- data/rubyspec/library/queue/num_waiting_spec.rb +19 -0
- data/rubyspec/library/queue/pop_spec.rb +7 -0
- data/rubyspec/library/queue/push_spec.rb +7 -0
- data/rubyspec/library/queue/shared/deque.rb +37 -0
- data/rubyspec/library/queue/shared/enque.rb +10 -0
- data/rubyspec/library/queue/shared/length.rb +9 -0
- data/rubyspec/library/queue/shift_spec.rb +7 -0
- data/rubyspec/library/queue/size_spec.rb +7 -0
- data/rubyspec/shared/kernel/raise.rb +68 -0
- data/rubyspec/shared/mutex/lock.rb +52 -0
- data/rubyspec/shared/mutex/locked.rb +31 -0
- data/rubyspec/shared/mutex/synchronize.rb +23 -0
- data/rubyspec/shared/mutex/try_lock.rb +30 -0
- data/rubyspec/shared/mutex/unlock.rb +35 -0
- data/rubyspec/spec_helper.rb +48 -0
- data/spec/empathy_spec.rb +129 -0
- data/spec/library_spec.rb +79 -0
- data/spec/spec_helper.rb +6 -0
- metadata +222 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread#join" do
|
5
|
+
it "returns the thread when it is finished" do
|
6
|
+
t = Thread.new {}
|
7
|
+
t.join.should equal(t)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns the thread when it is finished when given a timeout" do
|
11
|
+
t = Thread.new {}
|
12
|
+
t.join
|
13
|
+
t.join(0).should equal(t)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns nil if it is not finished when given a timeout" do
|
17
|
+
c = Channel.new
|
18
|
+
t = Thread.new { c.receive }
|
19
|
+
begin
|
20
|
+
t.join(0).should == nil
|
21
|
+
ensure
|
22
|
+
c << true
|
23
|
+
end
|
24
|
+
t.join.should == t
|
25
|
+
end
|
26
|
+
|
27
|
+
it "accepts a floating point timeout length" do
|
28
|
+
c = Channel.new
|
29
|
+
t = Thread.new { c.receive }
|
30
|
+
begin
|
31
|
+
t.join(0.01).should == nil
|
32
|
+
ensure
|
33
|
+
c << true
|
34
|
+
end
|
35
|
+
t.join.should == t
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises any exceptions encountered in the thread body" do
|
39
|
+
t = Thread.new { raise NotImplementedError.new("Just kidding") }
|
40
|
+
lambda { t.join }.should raise_error(NotImplementedError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns the dead thread" do
|
44
|
+
t = Thread.new { Thread.current.kill }
|
45
|
+
t.join.should equal(t)
|
46
|
+
end
|
47
|
+
|
48
|
+
ruby_version_is "" ... "1.9" do
|
49
|
+
not_compliant_on :rubinius do
|
50
|
+
it "returns the dead thread even if an uncaught exception is thrown from ensure block" do
|
51
|
+
t = ThreadSpecs.dying_thread_ensures { raise "In dying thread" }
|
52
|
+
t.join.should equal(t)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
ruby_version_is "1.9" do
|
58
|
+
it "raises any uncaught exception encountered in ensure block" do
|
59
|
+
t = ThreadSpecs.dying_thread_ensures { raise NotImplementedError.new("Just kidding") }
|
60
|
+
lambda { t.join }.should raise_error(NotImplementedError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread#key?" do
|
5
|
+
before :each do
|
6
|
+
@th = Thread.new do
|
7
|
+
Thread.current[:oliver] = "a"
|
8
|
+
end
|
9
|
+
@th.join
|
10
|
+
end
|
11
|
+
|
12
|
+
it "tests for existance of thread local variables using symbols or strings" do
|
13
|
+
@th.key?(:oliver).should == true
|
14
|
+
@th.key?("oliver").should == true
|
15
|
+
@th.key?(:stanley).should == false
|
16
|
+
@th.key?(:stanley.to_s).should == false
|
17
|
+
end
|
18
|
+
|
19
|
+
quarantine! do
|
20
|
+
ruby_version_is ""..."1.9" do
|
21
|
+
it "raises exceptions on the wrong type of keys" do
|
22
|
+
lambda { Thread.current.key? nil }.should raise_error(TypeError)
|
23
|
+
lambda { Thread.current.key? 5 }.should raise_error(ArgumentError)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ruby_version_is "1.9" do
|
29
|
+
it "raises exceptions on the wrong type of keys" do
|
30
|
+
lambda { Thread.current.key? nil }.should raise_error(TypeError)
|
31
|
+
lambda { Thread.current.key? 5 }.should raise_error(TypeError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is not shared across fibers" do
|
35
|
+
fib = Fiber.new do
|
36
|
+
Thread.current[:val1] = 1
|
37
|
+
Fiber.yield
|
38
|
+
Thread.current.key?(:val1).should be_true
|
39
|
+
Thread.current.key?(:val2).should be_false
|
40
|
+
end
|
41
|
+
Thread.current.key?(:val1).should_not be_true
|
42
|
+
fib.resume
|
43
|
+
Thread.current[:val2] = 2
|
44
|
+
fib.resume
|
45
|
+
Thread.current.key?(:val1).should be_false
|
46
|
+
Thread.current.key?(:val2).should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "stores a local in another thread when in a fiber" do
|
50
|
+
fib = Fiber.new do
|
51
|
+
t = Thread.new do
|
52
|
+
sleep
|
53
|
+
Thread.current.key?(:value).should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
Thread.pass while t.status and t.status != "sleep"
|
57
|
+
t[:value] = 1
|
58
|
+
t.wakeup
|
59
|
+
t.join
|
60
|
+
end
|
61
|
+
fib.resume
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread#keys" do
|
5
|
+
it "returns an array of the names of the thread-local variables as symbols" do
|
6
|
+
th = Thread.new do
|
7
|
+
Thread.current["cat"] = 'woof'
|
8
|
+
Thread.current[:cat] = 'meow'
|
9
|
+
Thread.current[:dog] = 'woof'
|
10
|
+
end
|
11
|
+
th.join
|
12
|
+
th.keys.sort_by {|x| x.to_s}.should == [:cat,:dog]
|
13
|
+
end
|
14
|
+
|
15
|
+
ruby_version_is "1.9" do
|
16
|
+
it "is not shared across fibers" do
|
17
|
+
fib = Fiber.new do
|
18
|
+
Thread.current[:val1] = 1
|
19
|
+
Fiber.yield
|
20
|
+
Thread.current.keys.should include(:val1)
|
21
|
+
Thread.current.keys.should_not include(:val2)
|
22
|
+
end
|
23
|
+
Thread.current.keys.should_not include(:val1)
|
24
|
+
fib.resume
|
25
|
+
Thread.current[:val2] = 2
|
26
|
+
fib.resume
|
27
|
+
Thread.current.keys.should include(:val2)
|
28
|
+
Thread.current.keys.should_not include(:val1)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "stores a local in another thread when in a fiber" do
|
32
|
+
fib = Fiber.new do
|
33
|
+
t = Thread.new do
|
34
|
+
sleep
|
35
|
+
Thread.current.keys.should include(:value)
|
36
|
+
end
|
37
|
+
|
38
|
+
Thread.pass while t.status and t.status != "sleep"
|
39
|
+
t[:value] = 1
|
40
|
+
t.wakeup
|
41
|
+
t.join
|
42
|
+
end
|
43
|
+
fib.resume
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
require File.expand_path('../shared/exit', __FILE__)
|
4
|
+
|
5
|
+
describe "Thread#kill" do
|
6
|
+
it_behaves_like :thread_exit, :kill
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Thread#kill!" do
|
10
|
+
it "needs to be reviewed for spec completeness"
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Thread.kill" do
|
14
|
+
it "causes the given thread to exit" do
|
15
|
+
thread = Thread.new { sleep }
|
16
|
+
Thread.pass while thread.status and thread.status != "sleep"
|
17
|
+
Thread.kill(thread)
|
18
|
+
thread.join
|
19
|
+
thread.status.should be_false
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread::list" do
|
5
|
+
it "includes the current and main thread" do
|
6
|
+
Thread.list.should include(Thread.current)
|
7
|
+
Thread.list.should include(Thread.main)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "includes threads of non-default thread groups" do
|
11
|
+
t = Thread.new { sleep }
|
12
|
+
ThreadGroup.new.add(t)
|
13
|
+
Thread.list.should include(t)
|
14
|
+
t.kill
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does not include deceased threads" do
|
18
|
+
t = Thread.new { 1; }
|
19
|
+
t.join
|
20
|
+
Thread.list.should_not include(t)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "includes waiting threads" do
|
24
|
+
c = Channel.new
|
25
|
+
t = Thread.new { c.receive }
|
26
|
+
begin
|
27
|
+
Thread.pass while t.status and t.status != 'sleep'
|
28
|
+
Thread.list.should include(t)
|
29
|
+
ensure
|
30
|
+
c << nil
|
31
|
+
t.join
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "Thread.list" do
|
37
|
+
it "needs to be reviewed for spec completeness"
|
38
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread.main" do
|
5
|
+
it "returns the main thread" do
|
6
|
+
Thread.new { @main = Thread.main ; @current = Thread.current}.join
|
7
|
+
@main.should_not == @current
|
8
|
+
@main.should == Thread.current
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
|
4
|
+
describe "Thread.new" do
|
5
|
+
it "creates a thread executing the given block" do
|
6
|
+
c = Channel.new
|
7
|
+
Thread.new { c << true }.join
|
8
|
+
c << false
|
9
|
+
c.receive.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "can pass arguments to the thread block" do
|
13
|
+
arr = []
|
14
|
+
a, b, c = 1, 2, 3
|
15
|
+
t = Thread.new(a,b,c) {|d,e,f| arr << d << e << f }
|
16
|
+
t.join
|
17
|
+
arr.should == [a,b,c]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises an exception when not given a block" do
|
21
|
+
lambda { Thread.new }.should raise_error(ThreadError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "creates a subclass of thread calls super with a block in initialize" do
|
25
|
+
arr = []
|
26
|
+
t = ThreadSpecs::SubThread.new(arr)
|
27
|
+
t.join
|
28
|
+
arr.should == [1]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "calls #initialize and raises an error if super not used" do
|
32
|
+
c = Class.new(Thread) do
|
33
|
+
def initialize
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
lambda {
|
38
|
+
c.new
|
39
|
+
}.should raise_error(ThreadError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "calls and respects #initialize for the block to use" do
|
43
|
+
c = Class.new(Thread) do
|
44
|
+
def initialize
|
45
|
+
ScratchPad.record [:good]
|
46
|
+
super { ScratchPad << :in_thread }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
t = c.new
|
51
|
+
t.join
|
52
|
+
|
53
|
+
ScratchPad.recorded.should == [:good, :in_thread]
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
describe "Thread#priority" do
|
4
|
+
it "needs to be reviewed for spec completeness"
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "Thread#priority=" do
|
8
|
+
it "needs to be reviewed for spec completeness"
|
9
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
3
|
+
require File.expand_path('../../../shared/kernel/raise', __FILE__)
|
4
|
+
|
5
|
+
describe "Thread#raise" do
|
6
|
+
it "ignores dead threads" do
|
7
|
+
t = Thread.new { :dead }
|
8
|
+
Thread.pass while t.alive?
|
9
|
+
lambda {t.raise("Kill the thread")}.should_not raise_error
|
10
|
+
lambda {t.value}.should_not raise_error
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Thread#raise on a sleeping thread" do
|
15
|
+
before :each do
|
16
|
+
ScratchPad.clear
|
17
|
+
@thr = ThreadSpecs.sleeping_thread
|
18
|
+
Thread.pass while @thr.status and @thr.status != "sleep"
|
19
|
+
end
|
20
|
+
|
21
|
+
after :each do
|
22
|
+
@thr.kill
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises a RuntimeError if no exception class is given" do
|
26
|
+
@thr.raise
|
27
|
+
Thread.pass while @thr.status
|
28
|
+
ScratchPad.recorded.should be_kind_of(RuntimeError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "raises the given exception" do
|
32
|
+
@thr.raise Exception
|
33
|
+
Thread.pass while @thr.status
|
34
|
+
ScratchPad.recorded.should be_kind_of(Exception)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises the given exception with the given message" do
|
38
|
+
@thr.raise Exception, "get to work"
|
39
|
+
Thread.pass while @thr.status
|
40
|
+
ScratchPad.recorded.should be_kind_of(Exception)
|
41
|
+
ScratchPad.recorded.message.should == "get to work"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "is captured and raised by Thread#value" do
|
45
|
+
t = Thread.new do
|
46
|
+
sleep
|
47
|
+
end
|
48
|
+
|
49
|
+
ThreadSpecs.spin_until_sleeping(t)
|
50
|
+
|
51
|
+
t.raise
|
52
|
+
lambda { t.value }.should raise_error(RuntimeError)
|
53
|
+
end
|
54
|
+
|
55
|
+
ruby_version_is "" ... "1.9" do
|
56
|
+
it "raises a ZeroDivisionError when called with no arguments inside rescue" do
|
57
|
+
t = Thread.new do
|
58
|
+
begin
|
59
|
+
1/0
|
60
|
+
rescue ZeroDivisionError
|
61
|
+
sleep
|
62
|
+
end
|
63
|
+
end
|
64
|
+
begin
|
65
|
+
raise RangeError
|
66
|
+
rescue
|
67
|
+
ThreadSpecs.spin_until_sleeping(t)
|
68
|
+
t.raise
|
69
|
+
end
|
70
|
+
lambda {t.value}.should raise_error(ZeroDivisionError)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
ruby_version_is "1.9" do
|
75
|
+
it "raises a RuntimeError when called with no arguments inside rescue" do
|
76
|
+
t = Thread.new do
|
77
|
+
begin
|
78
|
+
1/0
|
79
|
+
rescue ZeroDivisionError
|
80
|
+
sleep
|
81
|
+
end
|
82
|
+
end
|
83
|
+
begin
|
84
|
+
raise RangeError
|
85
|
+
rescue
|
86
|
+
ThreadSpecs.spin_until_sleeping(t)
|
87
|
+
t.raise
|
88
|
+
end
|
89
|
+
lambda {t.value}.should raise_error(RuntimeError)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "Thread#raise on a running thread" do
|
95
|
+
before :each do
|
96
|
+
ScratchPad.clear
|
97
|
+
ThreadSpecs.clear_state
|
98
|
+
|
99
|
+
@thr = ThreadSpecs.running_thread
|
100
|
+
Thread.pass until ThreadSpecs.state == :running
|
101
|
+
end
|
102
|
+
|
103
|
+
after :each do
|
104
|
+
@thr.kill
|
105
|
+
end
|
106
|
+
|
107
|
+
it "raises a RuntimeError if no exception class is given" do
|
108
|
+
@thr.raise
|
109
|
+
Thread.pass while @thr.status
|
110
|
+
ScratchPad.recorded.should be_kind_of(RuntimeError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "raises the given exception" do
|
114
|
+
@thr.raise Exception
|
115
|
+
Thread.pass while @thr.status
|
116
|
+
ScratchPad.recorded.should be_kind_of(Exception)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "raises the given exception with the given message" do
|
120
|
+
@thr.raise Exception, "get to work"
|
121
|
+
Thread.pass while @thr.status
|
122
|
+
ScratchPad.recorded.should be_kind_of(Exception)
|
123
|
+
ScratchPad.recorded.message.should == "get to work"
|
124
|
+
end
|
125
|
+
|
126
|
+
it "can go unhandled" do
|
127
|
+
t = Thread.new do
|
128
|
+
loop {}
|
129
|
+
end
|
130
|
+
|
131
|
+
t.raise
|
132
|
+
lambda {t.value}.should raise_error(RuntimeError)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "raise the given argument even when there is an active exception" do
|
136
|
+
raised = false
|
137
|
+
t = Thread.new do
|
138
|
+
begin
|
139
|
+
1/0
|
140
|
+
rescue ZeroDivisionError
|
141
|
+
raised = true
|
142
|
+
loop { }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
begin
|
146
|
+
raise "Create an active exception for the current thread too"
|
147
|
+
rescue
|
148
|
+
Thread.pass until raised
|
149
|
+
t.raise RangeError
|
150
|
+
lambda {t.value}.should raise_error(RangeError)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
ruby_version_is "" ... "1.9" do
|
155
|
+
it "raises a ZeroDivisionError when called with no arguments inside rescue" do
|
156
|
+
raised = false
|
157
|
+
t = Thread.new do
|
158
|
+
begin
|
159
|
+
1/0
|
160
|
+
rescue ZeroDivisionError
|
161
|
+
raised = true
|
162
|
+
loop { }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
begin
|
166
|
+
raise RangeError
|
167
|
+
rescue
|
168
|
+
Thread.pass until raised
|
169
|
+
t.raise
|
170
|
+
end
|
171
|
+
lambda {t.value}.should raise_error(ZeroDivisionError)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
ruby_version_is "1.9" do
|
176
|
+
it "raises a RuntimeError when called with no arguments inside rescue" do
|
177
|
+
raised = false
|
178
|
+
t = Thread.new do
|
179
|
+
begin
|
180
|
+
1/0
|
181
|
+
rescue ZeroDivisionError
|
182
|
+
raised = true
|
183
|
+
loop { }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
begin
|
187
|
+
raise RangeError
|
188
|
+
rescue
|
189
|
+
Thread.pass until raised
|
190
|
+
t.raise
|
191
|
+
end
|
192
|
+
lambda {t.value}.should raise_error(RuntimeError)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "Thread#raise on same thread" do
|
198
|
+
it_behaves_like :kernel_raise, :raise, Thread.current
|
199
|
+
|
200
|
+
ruby_version_is "" ... "1.9" do
|
201
|
+
it "raises a ZeroDivisionError when called with no arguments inside rescue" do
|
202
|
+
t = Thread.new do
|
203
|
+
begin
|
204
|
+
1/0
|
205
|
+
rescue ZeroDivisionError
|
206
|
+
Thread.current.raise
|
207
|
+
end
|
208
|
+
end
|
209
|
+
lambda {t.value}.should raise_error(ZeroDivisionError)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
ruby_version_is "1.9" do
|
214
|
+
it "raises a RuntimeError when called with no arguments inside rescue" do
|
215
|
+
t = Thread.new do
|
216
|
+
begin
|
217
|
+
1/0
|
218
|
+
rescue ZeroDivisionError
|
219
|
+
Thread.current.raise
|
220
|
+
end
|
221
|
+
end
|
222
|
+
lambda {t.value}.should raise_error(RuntimeError)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|