blackstart 0.2.0 → 0.9.0
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/LICENSE +202 -0
- data/README +202 -0
- data/lib/blackstart.rb +46 -72
- data/sig/blackstart.rbs +17 -0
- data/test/blackstart_test.rb +355 -269
- metadata +9 -25
- data/LICENSE.txt +0 -19
- data/README.txt +0 -152
- data/blackstart.gemspec +0 -11
data/test/blackstart_test.rb
CHANGED
|
@@ -1,198 +1,42 @@
|
|
|
1
1
|
# Sections that create local variables are in class definitions so that later
|
|
2
2
|
# sections cannot accidentally reference those local variables.
|
|
3
3
|
|
|
4
|
+
# Kernel#fail is an alias of Kernel#raise, so they do the same thing. However,
|
|
5
|
+
# they are used differently in this file: Kernel#fail is used only for
|
|
6
|
+
# assertions and Kernel#raise is used otherwise. Assertions always pass a
|
|
7
|
+
# string argument so that a new RuntimeError is raised. Kernel#fail with no
|
|
8
|
+
# arguments re-raises the current exception ($!) or, if there is none, raises a
|
|
9
|
+
# new RuntimeError. This would be fine (that is, it would raise a new
|
|
10
|
+
# RuntimeError) sometimes, but not always (not in a rescue clause, for
|
|
11
|
+
# example). Always using Kernel#fail with a string argument makes assertions
|
|
12
|
+
# consistent and avoids this subtle error.
|
|
13
|
+
|
|
14
|
+
# Constant references in blocks are fully qualified because this program must
|
|
15
|
+
# run correctly on a wide range of Ruby versions, including those in the 1.9.1
|
|
16
|
+
# and 1.9.2 branches. Ruby 1.9.1 and 1.9.2 used constant-lookup rules in
|
|
17
|
+
# certain situations that differed from those of earlier and later branches of
|
|
18
|
+
# Ruby.
|
|
19
|
+
|
|
4
20
|
require "blackstart"
|
|
5
21
|
|
|
6
22
|
# Blackstart should be a module.
|
|
7
23
|
fail "" unless Module.equal? Blackstart.class
|
|
8
24
|
|
|
9
|
-
# Blackstart should say it responds to
|
|
10
|
-
fail "" unless Blackstart.respond_to? :vet
|
|
11
|
-
fail "" unless Blackstart.respond_to? :add
|
|
25
|
+
# Blackstart should say it responds to run.
|
|
12
26
|
fail "" unless Blackstart.respond_to? :run
|
|
13
27
|
|
|
14
|
-
# Test Blackstart
|
|
15
|
-
|
|
16
|
-
# Blackstart.vet should raise an exception if any non-block arguments are sent.
|
|
17
|
-
begin
|
|
18
|
-
Blackstart.vet nil
|
|
19
|
-
rescue ArgumentError
|
|
20
|
-
else
|
|
21
|
-
fail ""
|
|
22
|
-
end
|
|
23
|
-
begin
|
|
24
|
-
Blackstart.vet(nil) {}
|
|
25
|
-
rescue ArgumentError
|
|
26
|
-
else
|
|
27
|
-
fail ""
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# If sending call with no arguments to the block raises an error,
|
|
31
|
-
# Blackstart.vet should return a new descriptive string.
|
|
32
|
-
class ::Object
|
|
33
|
-
fail "" unless /\ANoMethodError: / =~ Blackstart.vet
|
|
34
|
-
|
|
35
|
-
e_class = Class.new StandardError
|
|
36
|
-
def e_class.to_s
|
|
37
|
-
"FakeError".freeze
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
e_nil = e_class.new "a".freeze
|
|
41
|
-
def e_nil.backtrace
|
|
42
|
-
nil
|
|
43
|
-
end
|
|
44
|
-
fail "" unless "FakeError: a" == Blackstart.vet { ::Kernel.raise e_nil }
|
|
45
|
-
|
|
46
|
-
e_empty = e_class.new "b".freeze
|
|
47
|
-
def e_empty.backtrace
|
|
48
|
-
[].freeze
|
|
49
|
-
end
|
|
50
|
-
fail "" unless "FakeError: b" == Blackstart.vet { ::Kernel.raise e_empty }
|
|
51
|
-
|
|
52
|
-
e_full = e_class.new "c".freeze
|
|
53
|
-
def e_full.backtrace
|
|
54
|
-
["d".freeze, "e".freeze].freeze
|
|
55
|
-
end
|
|
56
|
-
fail "" unless "FakeError: c\nd\ne" ==
|
|
57
|
-
Blackstart.vet { ::Kernel.raise e_full }
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# If sending call with no arguments to the block raises a non-StandardError
|
|
61
|
-
# exception, Blackstart.vet should not rescue it.
|
|
62
|
-
class ::Object
|
|
63
|
-
non_standard_error = Class.new Exception
|
|
64
|
-
begin
|
|
65
|
-
Blackstart.vet { ::Kernel.raise non_standard_error }
|
|
66
|
-
rescue non_standard_error
|
|
67
|
-
else
|
|
68
|
-
fail ""
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# If sending call with no arguments to the block does not raise an exception,
|
|
73
|
-
# Blackstart.vet should return nil.
|
|
74
|
-
fail "" unless nil.equal? Blackstart.vet { nil }
|
|
75
|
-
fail "" unless nil.equal? Blackstart.vet { true }
|
|
76
|
-
|
|
77
|
-
# Test Blackstart.add:
|
|
78
|
-
|
|
79
|
-
# When there is no block, Blackstart.add should raise an exception.
|
|
80
|
-
begin
|
|
81
|
-
Blackstart.add
|
|
82
|
-
rescue NoMethodError
|
|
83
|
-
else
|
|
84
|
-
fail ""
|
|
85
|
-
end
|
|
86
|
-
begin
|
|
87
|
-
Blackstart.add []
|
|
88
|
-
rescue NoMethodError
|
|
89
|
-
else
|
|
90
|
-
fail ""
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Blackstart.add should raise an exception if superfluous arguments are sent.
|
|
94
|
-
begin
|
|
95
|
-
Blackstart.add [], "invalid"
|
|
96
|
-
rescue ArgumentError
|
|
97
|
-
else
|
|
98
|
-
fail ""
|
|
99
|
-
end
|
|
100
|
-
begin
|
|
101
|
-
Blackstart.add([], "invalid") {}
|
|
102
|
-
rescue ArgumentError
|
|
103
|
-
else
|
|
104
|
-
fail ""
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# When no collection is specified and the block does nothing, Blackstart.add
|
|
108
|
-
# should return an empty array.
|
|
109
|
-
fail "" unless [] == Blackstart.add {}
|
|
28
|
+
# Test Blackstart::Scratchpad:
|
|
110
29
|
|
|
111
|
-
#
|
|
112
|
-
# Blackstart
|
|
113
|
-
#
|
|
114
|
-
|
|
115
|
-
sink = [42]
|
|
116
|
-
prc1 = proc {}
|
|
117
|
-
prc2 = proc {}
|
|
118
|
-
retval = Blackstart.add sink do |adder|
|
|
119
|
-
adder.call(&prc1)
|
|
120
|
-
adder.call(&prc2)
|
|
121
|
-
adder.call
|
|
122
|
-
end
|
|
123
|
-
fail "" unless sink.equal? retval
|
|
124
|
-
fail "" unless [42, prc1, prc2, nil] == sink
|
|
125
|
-
end
|
|
30
|
+
# Blackstart::Scratchpad.new should return an instance of
|
|
31
|
+
# Blackstart::Scratchpad, which implies that Blackstart::Scratchpad should be a
|
|
32
|
+
# class.
|
|
33
|
+
fail "" unless Blackstart::Scratchpad.equal? Blackstart::Scratchpad.new.class
|
|
126
34
|
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
class ::Object
|
|
130
|
-
sink = []
|
|
131
|
-
begin
|
|
132
|
-
Blackstart.add(sink) { |adder| adder.call("invalid") {} }
|
|
133
|
-
rescue ArgumentError
|
|
134
|
-
else
|
|
135
|
-
fail ""
|
|
136
|
-
end
|
|
137
|
-
begin
|
|
138
|
-
Blackstart.add(sink) { |adder| adder.call "invalid" }
|
|
139
|
-
rescue ArgumentError
|
|
140
|
-
else
|
|
141
|
-
fail ""
|
|
142
|
-
end
|
|
143
|
-
fail "" unless 0 == sink.length
|
|
144
|
-
end
|
|
35
|
+
# Blackstart::Scratchpad should not be frozen.
|
|
36
|
+
fail "" if Blackstart::Scratchpad.frozen?
|
|
145
37
|
|
|
146
|
-
#
|
|
147
|
-
|
|
148
|
-
class ::Object
|
|
149
|
-
retval_block = retval_no_block = true
|
|
150
|
-
Blackstart.add do |adder|
|
|
151
|
-
retval_block = adder.call {}
|
|
152
|
-
retval_no_block = adder.call
|
|
153
|
-
end
|
|
154
|
-
fail "" unless nil.equal? retval_block
|
|
155
|
-
fail "" unless nil.equal? retval_no_block
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# In general, when there is a block that raises an exception, Blackstart.add
|
|
159
|
-
# should not rescue it.
|
|
160
|
-
class ::Object
|
|
161
|
-
e = StandardError.new
|
|
162
|
-
begin
|
|
163
|
-
Blackstart.add { ::Kernel.raise e }
|
|
164
|
-
rescue
|
|
165
|
-
fail "" unless e.equal? $!
|
|
166
|
-
else
|
|
167
|
-
fail ""
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# When there is a block that tries to add to the collection and the collection
|
|
172
|
-
# responds to the << message by raising an exception, Blackstart.add should not
|
|
173
|
-
# rescue it.
|
|
174
|
-
begin
|
|
175
|
-
Blackstart.add(nil) { |adder| adder.call {} }
|
|
176
|
-
rescue NoMethodError
|
|
177
|
-
else
|
|
178
|
-
fail ""
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# When no collection is specified and the block tries to add to the collection,
|
|
182
|
-
# Blackstart.add should append to a new array that gets returned.
|
|
183
|
-
class ::Object
|
|
184
|
-
prc = proc {}
|
|
185
|
-
fail "" unless [prc] == Blackstart.add { |adder| adder.call(&prc) }
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# Test Blackstart::Context:
|
|
189
|
-
|
|
190
|
-
# Blackstart::Context.new should return an instance of Blackstart::Context,
|
|
191
|
-
# which implies that Blackstart::Context should be a class.
|
|
192
|
-
fail "" unless Blackstart::Context.equal? Blackstart::Context.new.class
|
|
193
|
-
|
|
194
|
-
# A new context should have no instance variables.
|
|
195
|
-
fail "" unless 0 == Blackstart::Context.new.instance_variables.length
|
|
38
|
+
# A new scratchpad should have no instance variables.
|
|
39
|
+
fail "" unless 0 == Blackstart::Scratchpad.new.instance_variables.length
|
|
196
40
|
|
|
197
41
|
# Test Blackstart.run:
|
|
198
42
|
|
|
@@ -200,7 +44,7 @@ fail "" unless 0 == Blackstart::Context.new.instance_variables.length
|
|
|
200
44
|
# return the appropriate object based on the behavior of the tests.
|
|
201
45
|
class ::Object
|
|
202
46
|
begin
|
|
203
|
-
# Set $stdout to a test spy and
|
|
47
|
+
# Set $stdout to a test spy and restore it in the ensure clause.
|
|
204
48
|
original_stdout = $stdout
|
|
205
49
|
spy_stdout = $stdout.clone
|
|
206
50
|
spy_stdout.instance_variable_set :@_test_calls, stdout_calls = []
|
|
@@ -210,155 +54,289 @@ class ::Object
|
|
|
210
54
|
end
|
|
211
55
|
$stdout = spy_stdout
|
|
212
56
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
57
|
+
invalid_ostream = Object.new
|
|
58
|
+
def invalid_ostream.puts(*)
|
|
59
|
+
::Kernel.raise ::NoMethodError
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# When there are no tests, Blackstart.run should not notify the output
|
|
63
|
+
# stream of any failures.
|
|
64
|
+
source = []
|
|
65
|
+
fail "" unless true.equal? Blackstart.run(source, invalid_ostream)
|
|
216
66
|
fail "" unless true.equal? Blackstart.run(source, spy_stdout)
|
|
217
67
|
fail "" unless true.equal? Blackstart.run(source)
|
|
218
68
|
fail "" unless 0 == stdout_calls.length
|
|
219
69
|
|
|
220
|
-
#
|
|
221
|
-
|
|
222
|
-
|
|
70
|
+
# When there are tests but none raise exceptions, Blackstart.run should not
|
|
71
|
+
# notify the output stream of any failures. The objects returned by the
|
|
72
|
+
# test procs shouldn't affect Blackstart.run's behavior.
|
|
73
|
+
source = [lambda {}, lambda { 42 }]
|
|
74
|
+
fail "" unless true.equal? Blackstart.run(source, invalid_ostream)
|
|
223
75
|
fail "" unless true.equal? Blackstart.run(source, spy_stdout)
|
|
224
76
|
fail "" unless true.equal? Blackstart.run(source)
|
|
225
77
|
fail "" unless 0 == stdout_calls.length
|
|
226
78
|
|
|
227
|
-
# Define some
|
|
228
|
-
|
|
79
|
+
# Define some test objects. Freeze them, the strings to which they convert,
|
|
80
|
+
# some exception details, and the strings to which the exception classes
|
|
81
|
+
# convert to check that they don't get modified.
|
|
82
|
+
e_class = Class.new StandardError do
|
|
83
|
+
def backtrace
|
|
84
|
+
["line1".freeze, "line2".freeze].freeze
|
|
85
|
+
end
|
|
86
|
+
end
|
|
229
87
|
def e_class.to_s
|
|
230
|
-
"FakeError"
|
|
88
|
+
"FakeError".freeze
|
|
231
89
|
end
|
|
232
|
-
fail_prc1 =
|
|
90
|
+
fail_prc1 = lambda { ::Kernel.raise e_class, "fake message 1".freeze }
|
|
233
91
|
def fail_prc1.to_s
|
|
234
|
-
"to_s 1"
|
|
92
|
+
"to_s 1".freeze
|
|
235
93
|
end
|
|
94
|
+
fail_prc1.freeze
|
|
95
|
+
pass_prc = lambda {}.freeze
|
|
236
96
|
fail_prc2 = Object.new # Not a Proc instance, but converts to one.
|
|
237
97
|
fail_prc2.instance_variable_set :@_test_e_class, e_class
|
|
238
98
|
def fail_prc2.to_proc
|
|
239
99
|
e_class = @_test_e_class
|
|
240
|
-
::
|
|
100
|
+
::Kernel.lambda do
|
|
101
|
+
::Kernel.raise e_class, "fake message 2".freeze
|
|
102
|
+
end.freeze
|
|
241
103
|
end
|
|
242
104
|
def fail_prc2.to_s
|
|
243
|
-
"to_s 2"
|
|
105
|
+
"to_s 2".freeze
|
|
244
106
|
end
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
# Output stream that does not conform to the expected interface. (And in
|
|
251
|
-
# general, the only exceptions Blackstart.run should rescue are
|
|
252
|
-
# StandardError exceptions raised by tests.)
|
|
253
|
-
begin
|
|
254
|
-
Blackstart.run source, Object.new
|
|
255
|
-
rescue NoMethodError
|
|
256
|
-
else
|
|
257
|
-
fail ""
|
|
107
|
+
fail_prc2.freeze
|
|
108
|
+
non_prc = Object.new # Does not convert to a proc.
|
|
109
|
+
def non_prc.to_proc
|
|
110
|
+
::Kernel.raise ::NoMethodError
|
|
258
111
|
end
|
|
259
|
-
|
|
112
|
+
def non_prc.to_s
|
|
113
|
+
"to_s 3".freeze
|
|
114
|
+
end
|
|
115
|
+
non_prc.freeze
|
|
116
|
+
bad_prc = Object.new # Pretends to convert to a proc but doesn't.
|
|
117
|
+
def bad_prc.to_proc
|
|
118
|
+
0
|
|
119
|
+
end
|
|
120
|
+
def bad_prc.to_s
|
|
121
|
+
"to_s 4".freeze
|
|
122
|
+
end
|
|
123
|
+
bad_prc.freeze
|
|
124
|
+
|
|
125
|
+
# A mix of tests that raise errors and tests that return. Freeze the array
|
|
126
|
+
# to check that it's not being modified.
|
|
127
|
+
source = [fail_prc1, pass_prc, fail_prc2, non_prc, bad_prc].freeze
|
|
260
128
|
|
|
261
|
-
#
|
|
129
|
+
# An output stream that conforms to the expected interface and does not
|
|
130
|
+
# raise an exception should receive all failure information.
|
|
262
131
|
spy_ostream = Object.new
|
|
263
132
|
spy_ostream.instance_variable_set :@_test_calls, calls = []
|
|
264
133
|
def spy_ostream.puts *args
|
|
265
134
|
@_test_calls << args
|
|
266
|
-
nil
|
|
135
|
+
# A real standard output stream would return nil here (and spy_stdout
|
|
136
|
+
# does that), but Blackstart.run's behavior should not be affected by the
|
|
137
|
+
# returned object. Returning this unusual object tests that.
|
|
138
|
+
::Object.new
|
|
267
139
|
end
|
|
140
|
+
# Freeze the output stream to check that it's not being modified.
|
|
141
|
+
spy_ostream.freeze
|
|
268
142
|
fail "" unless false.equal? Blackstart.run(source, spy_ostream)
|
|
269
143
|
fail "" unless 0 == stdout_calls.length
|
|
270
|
-
fail "" unless
|
|
271
|
-
fail "" unless
|
|
144
|
+
fail "" unless 4 == calls.length
|
|
145
|
+
fail "" unless 7 == calls[0].length
|
|
272
146
|
fail "" unless "FAILED TEST:" == calls[0][0]
|
|
273
147
|
fail "" unless "to_s 1" == calls[0][1]
|
|
274
148
|
fail "" unless "...ERROR:" == calls[0][2]
|
|
275
|
-
fail "" unless
|
|
276
|
-
fail "" unless "" == calls[0][4]
|
|
277
|
-
fail "" unless
|
|
149
|
+
fail "" unless "FakeError" == calls[0][3]
|
|
150
|
+
fail "" unless "fake message 1" == calls[0][4]
|
|
151
|
+
fail "" unless ["line1", "line2"] == calls[0][5]
|
|
152
|
+
fail "" unless "" == calls[0][6]
|
|
153
|
+
fail "" unless 7 == calls[1].length
|
|
278
154
|
fail "" unless "FAILED TEST:" == calls[1][0]
|
|
279
155
|
fail "" unless "to_s 2" == calls[1][1]
|
|
280
156
|
fail "" unless "...ERROR:" == calls[1][2]
|
|
281
|
-
fail "" unless
|
|
282
|
-
fail "" unless "" == calls[1][4]
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
157
|
+
fail "" unless "FakeError" == calls[1][3]
|
|
158
|
+
fail "" unless "fake message 2" == calls[1][4]
|
|
159
|
+
fail "" unless ["line1", "line2"] == calls[1][5]
|
|
160
|
+
fail "" unless "" == calls[1][6]
|
|
161
|
+
fail "" unless 7 == calls[2].length
|
|
162
|
+
fail "" unless "FAILED TEST:" == calls[2][0]
|
|
163
|
+
fail "" unless "to_s 3" == calls[2][1]
|
|
164
|
+
fail "" unless "...ERROR:" == calls[2][2]
|
|
165
|
+
# (No need to check the error details.)
|
|
166
|
+
fail "" unless "" == calls[2][6]
|
|
167
|
+
fail "" unless 7 == calls[3].length
|
|
168
|
+
fail "" unless "FAILED TEST:" == calls[3][0]
|
|
169
|
+
fail "" unless "to_s 4" == calls[3][1]
|
|
170
|
+
fail "" unless "...ERROR:" == calls[3][2]
|
|
171
|
+
# (No need to check the error details.)
|
|
172
|
+
fail "" unless "" == calls[3][6]
|
|
173
|
+
|
|
174
|
+
# The faked standard output stream.
|
|
286
175
|
stdout_calls.clear
|
|
287
176
|
fail "" unless false.equal? Blackstart.run(source)
|
|
288
|
-
fail "" unless
|
|
289
|
-
fail "" unless
|
|
177
|
+
fail "" unless 4 == stdout_calls.length
|
|
178
|
+
fail "" unless 7 == stdout_calls[0].length
|
|
290
179
|
fail "" unless "FAILED TEST:" == stdout_calls[0][0]
|
|
291
180
|
fail "" unless "to_s 1" == stdout_calls[0][1]
|
|
292
181
|
fail "" unless "...ERROR:" == stdout_calls[0][2]
|
|
293
|
-
fail "" unless
|
|
294
|
-
fail "" unless "" == stdout_calls[0][4]
|
|
295
|
-
fail "" unless
|
|
182
|
+
fail "" unless "FakeError" == stdout_calls[0][3]
|
|
183
|
+
fail "" unless "fake message 1" == stdout_calls[0][4]
|
|
184
|
+
fail "" unless ["line1", "line2"] == stdout_calls[0][5]
|
|
185
|
+
fail "" unless "" == stdout_calls[0][6]
|
|
186
|
+
fail "" unless 7 == stdout_calls[1].length
|
|
296
187
|
fail "" unless "FAILED TEST:" == stdout_calls[1][0]
|
|
297
188
|
fail "" unless "to_s 2" == stdout_calls[1][1]
|
|
298
189
|
fail "" unless "...ERROR:" == stdout_calls[1][2]
|
|
299
|
-
fail "" unless
|
|
300
|
-
fail "" unless "" == stdout_calls[1][4]
|
|
190
|
+
fail "" unless "FakeError" == stdout_calls[1][3]
|
|
191
|
+
fail "" unless "fake message 2" == stdout_calls[1][4]
|
|
192
|
+
fail "" unless ["line1", "line2"] == stdout_calls[1][5]
|
|
193
|
+
fail "" unless "" == stdout_calls[1][6]
|
|
194
|
+
fail "" unless 7 == stdout_calls[2].length
|
|
195
|
+
fail "" unless "FAILED TEST:" == stdout_calls[2][0]
|
|
196
|
+
fail "" unless "to_s 3" == stdout_calls[2][1]
|
|
197
|
+
fail "" unless "...ERROR:" == stdout_calls[2][2]
|
|
198
|
+
# (No need to check the error details.)
|
|
199
|
+
fail "" unless "" == stdout_calls[2][6]
|
|
200
|
+
fail "" unless 7 == stdout_calls[3].length
|
|
201
|
+
fail "" unless "FAILED TEST:" == stdout_calls[3][0]
|
|
202
|
+
fail "" unless "to_s 4" == stdout_calls[3][1]
|
|
203
|
+
fail "" unless "...ERROR:" == stdout_calls[3][2]
|
|
204
|
+
# (No need to check the error details.)
|
|
205
|
+
fail "" unless "" == stdout_calls[3][6]
|
|
301
206
|
stdout_calls.clear
|
|
302
207
|
|
|
303
|
-
#
|
|
304
|
-
#
|
|
305
|
-
#
|
|
306
|
-
|
|
307
|
-
|
|
208
|
+
# An output stream that raises an exception when notified of a failure
|
|
209
|
+
# should cause Blackstart.run to raise that exception and stop processing
|
|
210
|
+
# tests. (In general, the only exceptions Blackstart.run should rescue are
|
|
211
|
+
# StandardError exceptions raised by tests.)
|
|
212
|
+
second_test_run = false
|
|
213
|
+
source = [lambda { ::Kernel.raise "" }, lambda { second_test_run = true }]
|
|
308
214
|
begin
|
|
309
|
-
Blackstart.run source,
|
|
310
|
-
rescue
|
|
215
|
+
Blackstart.run source, invalid_ostream
|
|
216
|
+
rescue NoMethodError
|
|
311
217
|
else
|
|
312
218
|
fail ""
|
|
313
219
|
end
|
|
220
|
+
fail "" if second_test_run
|
|
314
221
|
fail "" unless 0 == stdout_calls.length
|
|
315
222
|
|
|
316
|
-
#
|
|
317
|
-
#
|
|
318
|
-
# exceptions
|
|
223
|
+
# When a test raises a non-StandardError exception, Blackstart.run should
|
|
224
|
+
# raise that exception and stop processing tests. (In general, the only
|
|
225
|
+
# exceptions Blackstart.run should rescue are StandardError exceptions
|
|
226
|
+
# raised by tests.)
|
|
227
|
+
second_test_run = false
|
|
228
|
+
non_standard_error = Class.new Exception
|
|
229
|
+
source = [lambda { ::Kernel.raise non_standard_error },
|
|
230
|
+
lambda { second_test_run = true }]
|
|
319
231
|
begin
|
|
320
|
-
Blackstart.run
|
|
321
|
-
rescue
|
|
232
|
+
Blackstart.run source, spy_stdout
|
|
233
|
+
rescue non_standard_error
|
|
322
234
|
else
|
|
323
235
|
fail ""
|
|
324
236
|
end
|
|
237
|
+
fail "" if second_test_run
|
|
325
238
|
fail "" unless 0 == stdout_calls.length
|
|
326
239
|
|
|
327
|
-
#
|
|
328
|
-
#
|
|
329
|
-
# (
|
|
240
|
+
# When the test sequence does not conform to the interface and raises an
|
|
241
|
+
# exception during iteration, Blackstart.run should raise that exception.
|
|
242
|
+
# (In general, the only exceptions Blackstart.run should rescue are
|
|
330
243
|
# StandardError exceptions raised by tests.)
|
|
331
|
-
source =
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
rescue ArgumentError
|
|
335
|
-
else
|
|
336
|
-
fail ""
|
|
244
|
+
source = Object.new
|
|
245
|
+
def source.each(*)
|
|
246
|
+
::Kernel.raise ::NoMethodError
|
|
337
247
|
end
|
|
338
|
-
source = [0]
|
|
339
248
|
begin
|
|
340
249
|
Blackstart.run source, spy_stdout
|
|
341
|
-
rescue
|
|
250
|
+
rescue NoMethodError
|
|
342
251
|
else
|
|
343
252
|
fail ""
|
|
344
253
|
end
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
254
|
+
fail "" unless 0 == stdout_calls.length
|
|
255
|
+
|
|
256
|
+
# When a test fails and converting the test object to a string raises an
|
|
257
|
+
# exception, Blackstart.run should raise that exception and stop processing
|
|
258
|
+
# tests. (In general, the only exceptions Blackstart.run should rescue are
|
|
259
|
+
# StandardError exceptions raised by tests.)
|
|
260
|
+
second_test_run = false
|
|
261
|
+
no_desc = lambda { ::Kernel.raise "" }
|
|
262
|
+
def no_desc.to_s
|
|
263
|
+
::Kernel.raise ::NoMethodError
|
|
348
264
|
end
|
|
349
|
-
source = [
|
|
265
|
+
source = [no_desc, lambda { second_test_run = true }]
|
|
350
266
|
begin
|
|
351
267
|
Blackstart.run source, spy_stdout
|
|
352
|
-
rescue
|
|
268
|
+
rescue NoMethodError
|
|
353
269
|
else
|
|
354
270
|
fail ""
|
|
355
271
|
end
|
|
272
|
+
fail "" if second_test_run
|
|
356
273
|
fail "" unless 0 == stdout_calls.length
|
|
357
274
|
ensure
|
|
358
275
|
$stdout = original_stdout
|
|
359
276
|
end
|
|
360
277
|
end
|
|
361
278
|
|
|
279
|
+
# When a test fails with an error whose backtrace message returns nil,
|
|
280
|
+
# Blackstart.run should send an empty array to the output stream in place of
|
|
281
|
+
# the backtrace.
|
|
282
|
+
class ::Object
|
|
283
|
+
e_class = Class.new StandardError
|
|
284
|
+
def e_class.to_s
|
|
285
|
+
"FakeError".freeze
|
|
286
|
+
end
|
|
287
|
+
e_no_bt = e_class.new "no backtrace".freeze
|
|
288
|
+
def e_no_bt.backtrace
|
|
289
|
+
nil
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
ostream = Object.new
|
|
293
|
+
ostream.instance_variable_set :@_test_calls, calls = []
|
|
294
|
+
def ostream.puts *args
|
|
295
|
+
@_test_calls << args
|
|
296
|
+
nil
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
result = Blackstart.run [lambda { ::Kernel.raise e_no_bt }], ostream
|
|
300
|
+
fail "" unless false.equal? result
|
|
301
|
+
fail "" unless 1 == calls.length
|
|
302
|
+
fail "" unless 7 == calls[0].length
|
|
303
|
+
fail "" unless "FAILED TEST:" == calls[0][0]
|
|
304
|
+
fail "" unless "...ERROR:" == calls[0][2]
|
|
305
|
+
fail "" unless "FakeError" == calls[0][3]
|
|
306
|
+
fail "" unless "no backtrace" == calls[0][4]
|
|
307
|
+
fail "" unless [] == calls[0][5]
|
|
308
|
+
fail "" unless "" == calls[0][6]
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# When a test fails with an error that raises an exception when queried,
|
|
312
|
+
# Blackstart.run should raise that exception and stop processing tests. (In
|
|
313
|
+
# general, the only exceptions Blackstart.run should rescue are StandardError
|
|
314
|
+
# exceptions raised by tests.)
|
|
315
|
+
class ::Object
|
|
316
|
+
second_test_run = false
|
|
317
|
+
e2_class = Class.new StandardError
|
|
318
|
+
e1 = StandardError.new
|
|
319
|
+
e1.instance_variable_set :@next_exception_class, e2_class
|
|
320
|
+
def e1.to_s
|
|
321
|
+
::Kernel.raise @next_exception_class
|
|
322
|
+
end
|
|
323
|
+
source = [lambda { ::Kernel.raise e1 }, lambda { second_test_run = true }]
|
|
324
|
+
begin
|
|
325
|
+
Blackstart.run source, nil
|
|
326
|
+
rescue e2_class
|
|
327
|
+
else
|
|
328
|
+
fail ""
|
|
329
|
+
end
|
|
330
|
+
fail "" if second_test_run
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Blackstart.run should run tests in order.
|
|
334
|
+
class ::Object
|
|
335
|
+
data = []
|
|
336
|
+
Blackstart.run [lambda { data << 1 }, lambda { data << 2 }], nil
|
|
337
|
+
fail "" unless [1, 2] == data
|
|
338
|
+
end
|
|
339
|
+
|
|
362
340
|
# Blackstart.run should call each test proc with no arguments.
|
|
363
341
|
class ::Object
|
|
364
342
|
args = nil
|
|
@@ -369,14 +347,74 @@ class ::Object
|
|
|
369
347
|
fail "" unless [] == args
|
|
370
348
|
end
|
|
371
349
|
|
|
372
|
-
# Blackstart.run should
|
|
373
|
-
#
|
|
350
|
+
# Blackstart.run should work with any source that responds to each. The object
|
|
351
|
+
# returned in response to the each message should not affect Blackstart.run's
|
|
352
|
+
# behavior.
|
|
374
353
|
class ::Object
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
354
|
+
source = Object.new
|
|
355
|
+
def source.each
|
|
356
|
+
ran = false
|
|
357
|
+
yield lambda { ran = true }
|
|
358
|
+
@ran = ran
|
|
359
|
+
self
|
|
360
|
+
end
|
|
361
|
+
fail "" unless true.equal? Blackstart.run(source, nil)
|
|
362
|
+
fail "" unless source.instance_variable_get :@ran
|
|
363
|
+
|
|
364
|
+
source = Object.new
|
|
365
|
+
def source.each
|
|
366
|
+
yield lambda {}
|
|
367
|
+
nil
|
|
368
|
+
end
|
|
369
|
+
fail "" unless true.equal? Blackstart.run(source, nil)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Blackstart.run should send exactly one each message to the source.
|
|
373
|
+
class ::Object
|
|
374
|
+
source = Object.new
|
|
375
|
+
source.instance_variable_set :@count, 0
|
|
376
|
+
def source.each
|
|
377
|
+
@count += 1
|
|
378
|
+
self
|
|
379
|
+
end
|
|
380
|
+
Blackstart.run source, nil
|
|
381
|
+
fail "" unless 1 == source.instance_variable_get(:@count)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# The block that Blackstart.run sends with the each message should return nil
|
|
385
|
+
# whether the test fails or succeeds, regardless of the objects returned by the
|
|
386
|
+
# test and the output stream.
|
|
387
|
+
class ::Object
|
|
388
|
+
ostream = Object.new
|
|
389
|
+
def ostream.puts(*)
|
|
390
|
+
::Object.new
|
|
391
|
+
end
|
|
392
|
+
source = Object.new
|
|
393
|
+
def source.each
|
|
394
|
+
pass_result = yield lambda { 42 }
|
|
395
|
+
fail_result = yield lambda { ::Kernel.raise "" }
|
|
396
|
+
@results = [pass_result, fail_result]
|
|
397
|
+
self
|
|
398
|
+
end
|
|
399
|
+
fail "" unless false.equal? Blackstart.run(source, ostream)
|
|
400
|
+
fail "" unless [nil, nil] == source.instance_variable_get(:@results)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# When Blackstart.run calls a test proc, the self object should be a unique
|
|
404
|
+
# instance of Blackstart::Scratchpad.
|
|
405
|
+
class ::Object
|
|
406
|
+
sp1 = sp2 = nil
|
|
407
|
+
Blackstart.run [lambda { sp1 = self }, lambda { sp2 = self }], nil
|
|
408
|
+
fail "" unless Blackstart::Scratchpad.equal? sp1.class
|
|
409
|
+
fail "" unless Blackstart::Scratchpad.equal? sp2.class
|
|
410
|
+
fail "" if sp1.equal? sp2
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# When Blackstart.run runs a test, the scratchpad should not be frozen.
|
|
414
|
+
class ::Object
|
|
415
|
+
frozen = true
|
|
416
|
+
Blackstart.run [lambda { frozen = frozen? }], nil
|
|
417
|
+
fail "" if frozen
|
|
380
418
|
end
|
|
381
419
|
|
|
382
420
|
# Blackstart.run should raise an exception if too few or too many non-block
|
|
@@ -387,11 +425,59 @@ rescue ArgumentError
|
|
|
387
425
|
else
|
|
388
426
|
fail ""
|
|
389
427
|
end
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
428
|
+
class ::Object
|
|
429
|
+
source = []
|
|
430
|
+
begin
|
|
431
|
+
Blackstart.run source, nil, nil
|
|
432
|
+
rescue ArgumentError
|
|
433
|
+
else
|
|
434
|
+
fail ""
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
# The following sections modify the state of the library, so they must be run
|
|
439
|
+
# after all the ordinary tests.
|
|
440
|
+
|
|
441
|
+
# Blackstart.run should run each test by sending instance_exec to a scratchpad.
|
|
442
|
+
class Blackstart::Scratchpad
|
|
443
|
+
def foo
|
|
444
|
+
2
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def instance_exec(*)
|
|
448
|
+
@ivar = 1
|
|
449
|
+
super
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
class ::Object
|
|
453
|
+
result = nil
|
|
454
|
+
Blackstart.run [lambda { result = [@ivar, foo()] }], nil
|
|
455
|
+
fail "" unless [1, 2] == result
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
# When creating a scratchpad raises an exception, Blackstart.run should raise
|
|
459
|
+
# that exception and stop processing tests instead of treating it as a test
|
|
460
|
+
# failure, even when the exception is a StandardError. (In general, the only
|
|
461
|
+
# exceptions Blackstart.run should rescue are StandardError exceptions raised
|
|
462
|
+
# by tests; this one is raised outside of a test.) This section makes creating
|
|
463
|
+
# a scratchpad always raise an exception, so it must be the last section that
|
|
464
|
+
# runs tests.
|
|
465
|
+
class ::Object
|
|
466
|
+
second_test_run = false
|
|
467
|
+
e_class = Class.new StandardError
|
|
468
|
+
scratchpad_class = Blackstart::Scratchpad
|
|
469
|
+
scratchpad_class.instance_variable_set :@_test_e_class, e_class
|
|
470
|
+
def scratchpad_class.new(*)
|
|
471
|
+
::Kernel.raise @_test_e_class
|
|
472
|
+
end
|
|
473
|
+
source = [lambda {}, lambda { second_test_run = true }]
|
|
474
|
+
begin
|
|
475
|
+
Blackstart.run source, nil
|
|
476
|
+
rescue e_class
|
|
477
|
+
else
|
|
478
|
+
fail ""
|
|
479
|
+
end
|
|
480
|
+
fail "" if second_test_run
|
|
395
481
|
end
|
|
396
482
|
|
|
397
483
|
# If this message doesn't get written, there was a problem.
|