1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
require_relative '../../spec_helper'
describe "Thread.report_on_exception" do
it "defaults to true" do
ruby_exe("p Thread.report_on_exception").should == "true\n"
end
end
describe "Thread.report_on_exception=" do
before :each do
@report_on_exception = Thread.report_on_exception
end
after :each do
Thread.report_on_exception = @report_on_exception
end
it "changes the default value for new threads" do
Thread.report_on_exception = true
Thread.report_on_exception.should == true
t = Thread.new {}
t.join
t.report_on_exception.should == true
end
end
describe "Thread#report_on_exception" do
it "returns true for the main Thread" do
Thread.current.report_on_exception.should == true
end
it "returns true for new Threads" do
Thread.new { Thread.current.report_on_exception }.value.should == true
end
it "returns whether the Thread will print a backtrace if it exits with an exception" do
t = Thread.new { Thread.current.report_on_exception = true }
t.join
t.report_on_exception.should == true
t = Thread.new { Thread.current.report_on_exception = false }
t.join
t.report_on_exception.should == false
end
end
describe "Thread#report_on_exception=" do
describe "when set to true" do
it "prints a backtrace on $stderr if it terminates with an exception" do
t = nil
-> {
t = Thread.new {
Thread.current.report_on_exception = true
raise RuntimeError, "Thread#report_on_exception specs"
}
Thread.pass while t.alive?
}.should output("", /Thread.+terminated with exception.+Thread#report_on_exception specs/m)
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
end
it "prints a backtrace on $stderr in the regular backtrace order" do
line_raise = __LINE__ + 2
def foo
raise RuntimeError, "Thread#report_on_exception specs backtrace order"
end
line_call_foo = __LINE__ + 5
go = false
t = Thread.new {
Thread.current.report_on_exception = true
Thread.pass until go
foo
}
-> {
go = true
Thread.pass while t.alive?
}.should output("", /\A
#{Regexp.quote(t.inspect)}\sterminated\swith\sexception\s\(report_on_exception\sis\strue\):\n
#{Regexp.quote(__FILE__)}:#{line_raise}:in\s[`']foo':\sThread\#report_on_exception\sspecs\sbacktrace\sorder\s\(RuntimeError\)\n
\tfrom\s#{Regexp.quote(__FILE__)}:#{line_call_foo}:in\s[`']block\s\(4\slevels\)\sin\s<top\s\(required\)>'\n
\z/x)
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs backtrace order")
end
it "prints the backtrace even if the thread was killed just after Thread#raise" do
t = nil
ready = false
-> {
t = Thread.new {
Thread.current.report_on_exception = true
ready = true
sleep
}
Thread.pass until ready and t.stop?
t.raise RuntimeError, "Thread#report_on_exception before kill spec"
t.kill
Thread.pass while t.alive?
}.should output("", /Thread.+terminated with exception.+Thread#report_on_exception before kill spec/m)
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception before kill spec")
end
end
describe "when set to false" do
it "lets the thread terminates silently with an exception" do
t = nil
-> {
t = Thread.new {
Thread.current.report_on_exception = false
raise RuntimeError, "Thread#report_on_exception specs"
}
Thread.pass while t.alive?
}.should output("", "")
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
end
end
describe "when used in conjunction with Thread#abort_on_exception" do
it "first reports then send the exception back to the main Thread" do
t = nil
mutex = Mutex.new
mutex.lock
-> {
t = Thread.new {
Thread.current.abort_on_exception = true
Thread.current.report_on_exception = true
mutex.lock
mutex.unlock
raise RuntimeError, "Thread#report_on_exception specs"
}
-> {
mutex.sleep(5)
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
}.should output("", /Thread.+terminated with exception.+Thread#report_on_exception specs/m)
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
end
end
end
|