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