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
|
describe :kernel_raise, shared: true do
before :each do
ScratchPad.clear
end
it "aborts execution" do
-> do
@object.raise Exception, "abort"
ScratchPad.record :no_abort
end.should raise_error(Exception, "abort")
ScratchPad.recorded.should be_nil
end
it "accepts an exception that implements to_hash" do
custom_error = Class.new(StandardError) do
def to_hash
{}
end
end
error = custom_error.new
-> { @object.raise(error) }.should raise_error(custom_error)
end
it "allows the message parameter to be a hash" do
data_error = Class.new(StandardError) do
attr_reader :data
def initialize(data)
@data = data
end
end
-> { @object.raise(data_error, {data: 42}) }.should raise_error(data_error) do |ex|
ex.data.should == {data: 42}
end
end
# https://bugs.ruby-lang.org/issues/8257#note-36
it "allows extra keyword arguments for compatibility" do
data_error = Class.new(StandardError) do
attr_reader :data
def initialize(data)
@data = data
end
end
-> { @object.raise(data_error, data: 42) }.should raise_error(data_error) do |ex|
ex.data.should == {data: 42}
end
end
it "does not allow message and extra keyword arguments" do
data_error = Class.new(StandardError) do
attr_reader :data
def initialize(data)
@data = data
end
end
-> { @object.raise(data_error, {a: 1}, b: 2) }.should raise_error(StandardError) do |e|
[TypeError, ArgumentError].should.include?(e.class)
end
-> { @object.raise(data_error, {a: 1}, [], b: 2) }.should raise_error(ArgumentError)
end
it "raises RuntimeError if no exception class is given" do
-> { @object.raise }.should raise_error(RuntimeError, "")
end
it "raises a given Exception instance" do
error = RuntimeError.new
-> { @object.raise(error) }.should raise_error(error)
end
it "raises a RuntimeError if string given" do
-> { @object.raise("a bad thing") }.should raise_error(RuntimeError)
end
it "passes no arguments to the constructor when given only an exception class" do
klass = Class.new(Exception) do
def initialize
end
end
-> { @object.raise(klass) }.should raise_error(klass) { |e| e.message.should == klass.to_s }
end
it "raises a TypeError when passed a non-Exception object" do
-> { @object.raise(Object.new) }.should raise_error(TypeError)
end
it "raises a TypeError when passed true" do
-> { @object.raise(true) }.should raise_error(TypeError)
end
it "raises a TypeError when passed false" do
-> { @object.raise(false) }.should raise_error(TypeError)
end
it "raises a TypeError when passed nil" do
-> { @object.raise(nil) }.should raise_error(TypeError)
end
it "re-raises a previously rescued exception without overwriting the backtrace" do
# This spec is written using #backtrace and matching the line number
# from the string, as backtrace_locations is a more advanced
# method that is not always supported by implementations.
#
initial_raise_line = nil
raise_again_line = nil
raised_again = nil
if defined?(FiberSpecs::NewFiberToRaise) and @object == FiberSpecs::NewFiberToRaise
fiber = Fiber.new do
begin
initial_raise_line = __LINE__; Fiber.yield
rescue => raised
begin
raise_again_line = __LINE__; Fiber.yield raised
rescue => raised_again
raised_again
end
end
end
fiber.resume
raised = fiber.raise 'raised'
raised_again = fiber.raise raised
else
begin
initial_raise_line = __LINE__; @object.raise 'raised'
rescue => raised
begin
raise_again_line = __LINE__; @object.raise raised
rescue => raised_again
raised_again
end
end
end
raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
end
it "allows Exception, message, and backtrace parameters" do
-> do
@object.raise(ArgumentError, "message", caller)
end.should raise_error(ArgumentError, "message")
end
end
|