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,173 @@
|
|
|
1
|
+
describe :thread_exit, :shared => true do
|
|
2
|
+
before(:each) do
|
|
3
|
+
ScratchPad.clear
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
it "kills sleeping thread" do
|
|
7
|
+
sleeping_thread = Thread.new do
|
|
8
|
+
sleep
|
|
9
|
+
ScratchPad.record :after_sleep
|
|
10
|
+
end
|
|
11
|
+
Thread.pass while sleeping_thread.status and sleeping_thread.status != "sleep"
|
|
12
|
+
sleeping_thread.send(@method)
|
|
13
|
+
sleeping_thread.join
|
|
14
|
+
ScratchPad.recorded.should == nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "kills current thread" do
|
|
18
|
+
thread = Thread.new do
|
|
19
|
+
Thread.current.send(@method)
|
|
20
|
+
ScratchPad.record :after_sleep
|
|
21
|
+
end
|
|
22
|
+
thread.join
|
|
23
|
+
ScratchPad.recorded.should == nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "runs ensure clause" do
|
|
27
|
+
thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record :in_ensure_clause }
|
|
28
|
+
thread.join
|
|
29
|
+
ScratchPad.recorded.should == :in_ensure_clause
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "runs nested ensure clauses" do
|
|
33
|
+
ScratchPad.record []
|
|
34
|
+
outer = Thread.new do
|
|
35
|
+
begin
|
|
36
|
+
inner = Thread.new do
|
|
37
|
+
begin
|
|
38
|
+
sleep
|
|
39
|
+
ensure
|
|
40
|
+
ScratchPad << :inner_ensure_clause
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
sleep
|
|
44
|
+
ensure
|
|
45
|
+
ScratchPad << :outer_ensure_clause
|
|
46
|
+
Thread.pass while inner.status and inner.status != "sleep"
|
|
47
|
+
inner.send(@method)
|
|
48
|
+
inner.join
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
Thread.pass while outer.status and outer.status != "sleep"
|
|
52
|
+
outer.send(@method)
|
|
53
|
+
outer.join
|
|
54
|
+
ScratchPad.recorded.should include(:inner_ensure_clause)
|
|
55
|
+
ScratchPad.recorded.should include(:outer_ensure_clause)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "does not set $!" do
|
|
59
|
+
thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record $! }
|
|
60
|
+
thread.join
|
|
61
|
+
ScratchPad.recorded.should == nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "cannot be rescued" do
|
|
65
|
+
thread = Thread.new do
|
|
66
|
+
begin
|
|
67
|
+
Thread.current.send(@method)
|
|
68
|
+
rescue Exception
|
|
69
|
+
ScratchPad.record :in_rescue
|
|
70
|
+
end
|
|
71
|
+
ScratchPad.record :end_of_thread_block
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
thread.join
|
|
75
|
+
ScratchPad.recorded.should == nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
ruby_version_is "" ... "1.9" do
|
|
79
|
+
it "killing dying sleeping thread wakes up thread" do
|
|
80
|
+
t = ThreadSpecs.dying_thread_ensures { Thread.stop; ScratchPad.record :after_stop }
|
|
81
|
+
Thread.pass while t.status and t.status != "sleep"
|
|
82
|
+
t.send(@method)
|
|
83
|
+
t.join
|
|
84
|
+
ScratchPad.recorded.should == :after_stop
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# This spec is a mess. It fails randomly, it hangs on MRI, it needs to be removed
|
|
89
|
+
quarantine! do
|
|
90
|
+
it "killing dying running does nothing" do
|
|
91
|
+
in_ensure_clause = false
|
|
92
|
+
exit_loop = true
|
|
93
|
+
t = ThreadSpecs.dying_thread_ensures do
|
|
94
|
+
in_ensure_clause = true
|
|
95
|
+
loop { if exit_loop then break end }
|
|
96
|
+
ScratchPad.record :after_stop
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
Thread.pass until in_ensure_clause == true
|
|
100
|
+
10.times { t.send(@method); Thread.pass }
|
|
101
|
+
exit_loop = true
|
|
102
|
+
t.join
|
|
103
|
+
ScratchPad.recorded.should == :after_stop
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
quarantine! do
|
|
108
|
+
|
|
109
|
+
it "propogates inner exception to Thread.join if there is an outer ensure clause" do
|
|
110
|
+
thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { }
|
|
111
|
+
lambda { thread.join }.should raise_error(RuntimeError, "In dying thread")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "runs all outer ensure clauses even if inner ensure clause raises exception" do
|
|
115
|
+
thread = ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record :in_outer_ensure_clause }
|
|
116
|
+
ScratchPad.recorded.should == :in_outer_ensure_clause
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "sets $! in outer ensure clause if inner ensure clause raises exception" do
|
|
120
|
+
thread = ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record $! }
|
|
121
|
+
ScratchPad.recorded.to_s.should == "In dying thread"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "can be rescued by outer rescue clause when inner ensure clause raises exception" do
|
|
126
|
+
thread = Thread.new do
|
|
127
|
+
begin
|
|
128
|
+
begin
|
|
129
|
+
Thread.current.send(@method)
|
|
130
|
+
ensure
|
|
131
|
+
raise "In dying thread"
|
|
132
|
+
end
|
|
133
|
+
rescue Exception
|
|
134
|
+
ScratchPad.record $!
|
|
135
|
+
end
|
|
136
|
+
:end_of_thread_block
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
thread.value.should == :end_of_thread_block
|
|
140
|
+
ScratchPad.recorded.to_s.should == "In dying thread"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "is deferred if ensure clause does Thread.stop" do
|
|
144
|
+
ThreadSpecs.wakeup_dying_sleeping_thread(@method) { Thread.stop; ScratchPad.record :after_sleep }
|
|
145
|
+
ScratchPad.recorded.should == :after_sleep
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Hangs on 1.8.6.114 OS X, possibly also on Linux
|
|
149
|
+
# FIX: There is no such thing as not_compliant_on(:ruby)!!!
|
|
150
|
+
quarantine! do
|
|
151
|
+
not_compliant_on(:ruby) do # Doing a sleep in the ensure block hangs the process
|
|
152
|
+
it "is deferred if ensure clause sleeps" do
|
|
153
|
+
ThreadSpecs.wakeup_dying_sleeping_thread(@method) { sleep; ScratchPad.record :after_sleep }
|
|
154
|
+
ScratchPad.recorded.should == :after_sleep
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# This case occurred in JRuby where native threads are used to provide
|
|
160
|
+
# the same behavior as MRI green threads. Key to this issue was the fact
|
|
161
|
+
# that the thread which called #exit in its block was also being explicitly
|
|
162
|
+
# sent #join from outside the thread. The 100.times provides a certain
|
|
163
|
+
# probability that the deadlock will occur. It was sufficient to reliably
|
|
164
|
+
# reproduce the deadlock in JRuby.
|
|
165
|
+
it "does not deadlock when called from within the thread while being joined from without" do
|
|
166
|
+
100.times do
|
|
167
|
+
t = Thread.new { Thread.stop; Thread.current.send(@method) }
|
|
168
|
+
Thread.pass while t.status and t.status != "sleep"
|
|
169
|
+
t.wakeup.should == t
|
|
170
|
+
t.join.should == t
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
describe :thread_start, :shared => true do
|
|
2
|
+
before(:each) do
|
|
3
|
+
ScratchPad.clear
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
ruby_version_is '' ... '1.9' do
|
|
7
|
+
it "raises a ThreadError if not passed a block" do
|
|
8
|
+
lambda {
|
|
9
|
+
Thread.send(@method)
|
|
10
|
+
}.should raise_error(ThreadError)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
ruby_version_is '1.9' do
|
|
15
|
+
it "raises a ArgumentError if not passed a block" do
|
|
16
|
+
lambda {
|
|
17
|
+
Thread.send(@method)
|
|
18
|
+
}.should raise_error(ArgumentError)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "spawns a new Thread running the block" do
|
|
23
|
+
run = false
|
|
24
|
+
t = Thread.send(@method) { run = true }
|
|
25
|
+
t.should be_kind_of(Thread)
|
|
26
|
+
t.join
|
|
27
|
+
|
|
28
|
+
run.should be_true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "respects Thread subclasses" do
|
|
32
|
+
c = Class.new(Thread)
|
|
33
|
+
t = c.send(@method) { }
|
|
34
|
+
t.should be_kind_of(c)
|
|
35
|
+
|
|
36
|
+
t.join
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "does not call #initialize" do
|
|
40
|
+
c = Class.new(Thread) do
|
|
41
|
+
def initialize
|
|
42
|
+
ScratchPad.record :bad
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
t = c.send(@method) { }
|
|
47
|
+
t.join
|
|
48
|
+
|
|
49
|
+
ScratchPad.recorded.should == nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
describe :thread_wakeup, :shared => true do
|
|
2
|
+
it "can interrupt Kernel#sleep" do
|
|
3
|
+
exit_loop = false
|
|
4
|
+
after_sleep1 = false
|
|
5
|
+
after_sleep2 = false
|
|
6
|
+
|
|
7
|
+
t = Thread.new do
|
|
8
|
+
while true
|
|
9
|
+
break if exit_loop == true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
sleep
|
|
13
|
+
after_sleep1 = true
|
|
14
|
+
|
|
15
|
+
sleep
|
|
16
|
+
after_sleep2 = true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
10.times { t.send(@method); Thread.pass }
|
|
20
|
+
t.status.should_not == "sleep"
|
|
21
|
+
|
|
22
|
+
exit_loop = true
|
|
23
|
+
|
|
24
|
+
10.times { sleep 0.1 if t.status and t.status != "sleep" }
|
|
25
|
+
after_sleep1.should == false # t should be blocked on the first sleep
|
|
26
|
+
t.send(@method)
|
|
27
|
+
|
|
28
|
+
10.times { sleep 0.1 if after_sleep1 != true }
|
|
29
|
+
10.times { sleep 0.1 if t.status and t.status != "sleep" }
|
|
30
|
+
after_sleep2.should == false # t should be blocked on the second sleep
|
|
31
|
+
t.send(@method)
|
|
32
|
+
|
|
33
|
+
t.join
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "does not result in a deadlock" do
|
|
37
|
+
t = Thread.new do
|
|
38
|
+
1000.times {Thread.stop }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
while(t.status != false) do
|
|
42
|
+
begin
|
|
43
|
+
t.send(@method)
|
|
44
|
+
rescue ThreadError
|
|
45
|
+
# The thread might die right after.
|
|
46
|
+
t.status.should == false
|
|
47
|
+
end
|
|
48
|
+
Thread.pass
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
1.should == 1 # test succeeds if we reach here
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "raises a ThreadError when trying to wake up a dead thread" do
|
|
55
|
+
t = Thread.new { 1 }
|
|
56
|
+
t.join
|
|
57
|
+
lambda { t.wakeup }.should raise_error(ThreadError)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
require File.expand_path('../shared/start', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe "Thread.start" do
|
|
6
|
+
describe "Thread.start" do
|
|
7
|
+
it_behaves_like :thread_start, :start
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe "Thread#status" do
|
|
5
|
+
it "can check it's own status" do
|
|
6
|
+
ThreadSpecs.status_of_current_thread.status.should == 'run'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "describes a running thread" do
|
|
10
|
+
ThreadSpecs.status_of_running_thread.status.should == 'run'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "describes a sleeping thread" do
|
|
14
|
+
ThreadSpecs.status_of_sleeping_thread.status.should == 'sleep'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "describes a blocked thread" do
|
|
18
|
+
ThreadSpecs.status_of_blocked_thread.status.should == 'sleep'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "describes a completed thread" do
|
|
22
|
+
ThreadSpecs.status_of_completed_thread.status.should == false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "describes a killed thread" do
|
|
26
|
+
ThreadSpecs.status_of_killed_thread.status.should == false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "describes a thread with an uncaught exception" do
|
|
30
|
+
ThreadSpecs.status_of_thread_with_uncaught_exception.status.should == nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
ruby_version_is ""..."1.9" do
|
|
34
|
+
it "describes a dying running thread" do
|
|
35
|
+
ThreadSpecs.status_of_dying_running_thread.status.should == 'aborting'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "describes a dying sleeping thread" do
|
|
40
|
+
ThreadSpecs.status_of_dying_sleeping_thread.status.should == 'sleep'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
quarantine! do
|
|
44
|
+
it "reports aborting on a killed thread" do
|
|
45
|
+
ThreadSpecs.status_of_aborting_thread.status.should == 'aborting'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
require File.expand_path('../fixtures/classes', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe "Thread.stop" do
|
|
5
|
+
it "causes the current thread to sleep indefinitely" do
|
|
6
|
+
t = Thread.new { Thread.stop; 5 }
|
|
7
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
8
|
+
t.status.should == 'sleep'
|
|
9
|
+
t.run
|
|
10
|
+
t.value.should == 5
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
ruby_version_is ""..."1.9" do
|
|
14
|
+
it "resets Thread.critical to false" do
|
|
15
|
+
t = Thread.new { Thread.critical = true; Thread.stop }
|
|
16
|
+
Thread.pass while t.status and t.status != 'sleep'
|
|
17
|
+
Thread.critical.should == false
|
|
18
|
+
t.run
|
|
19
|
+
t.join
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "Thread#stop?" do
|
|
25
|
+
it "can check it's own status" do
|
|
26
|
+
ThreadSpecs.status_of_current_thread.stop?.should == false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "describes a running thread" do
|
|
30
|
+
ThreadSpecs.status_of_running_thread.stop?.should == false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "describes a sleeping thread" do
|
|
34
|
+
ThreadSpecs.status_of_sleeping_thread.stop?.should == true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "describes a blocked thread" do
|
|
38
|
+
ThreadSpecs.status_of_blocked_thread.stop?.should == true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "describes a completed thread" do
|
|
42
|
+
ThreadSpecs.status_of_completed_thread.stop?.should == true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "describes a killed thread" do
|
|
46
|
+
ThreadSpecs.status_of_killed_thread.stop?.should == true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "describes a thread with an uncaught exception" do
|
|
50
|
+
ThreadSpecs.status_of_thread_with_uncaught_exception.stop?.should == true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "describes a dying running thread" do
|
|
54
|
+
ThreadSpecs.status_of_dying_running_thread.stop?.should == false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "describes a dying sleeping thread" do
|
|
58
|
+
ThreadSpecs.status_of_dying_sleeping_thread.stop?.should == true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
quarantine! do
|
|
62
|
+
it "reports aborting on a killed thread" do
|
|
63
|
+
ThreadSpecs.status_of_aborting_thread.stop?.should == false
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
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#terminate" do
|
|
6
|
+
it_behaves_like :thread_exit, :terminate
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe "Thread#terminate!" do
|
|
10
|
+
it "needs to be reviewed for spec completeness"
|
|
11
|
+
end
|