empathy 0.0.1.RC0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|