did_you_mean 1.6.2 → 2.0.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.
@@ -1,757 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Test
4
- module Unit
5
- module Assertions
6
- def assert_raises(*exp, &b)
7
- raise NoMethodError, "use assert_raise", caller
8
- end
9
-
10
- def _assertions= n # :nodoc:
11
- @_assertions = n
12
- end
13
-
14
- def _assertions # :nodoc:
15
- @_assertions ||= 0
16
- end
17
-
18
- ##
19
- # Returns a proc that will output +msg+ along with the default message.
20
-
21
- def message msg = nil, ending = nil, &default
22
- proc {
23
- ending ||= (ending_pattern = /(?<!\.)\z/; ".")
24
- ending_pattern ||= /(?<!#{Regexp.quote(ending)})\z/
25
- msg = msg.call if Proc === msg
26
- ary = [msg, (default.call if default)].compact.reject(&:empty?)
27
- ary.map! {|str| str.to_s.sub(ending_pattern, ending) }
28
- begin
29
- ary.join("\n")
30
- rescue Encoding::CompatibilityError
31
- ary.map(&:b).join("\n")
32
- end
33
- }
34
- end
35
- end
36
-
37
- module CoreAssertions
38
- require_relative 'envutil'
39
- require 'pp'
40
- nil.pretty_inspect
41
-
42
- def mu_pp(obj) #:nodoc:
43
- obj.pretty_inspect.chomp
44
- end
45
-
46
- def assert_file
47
- AssertFile
48
- end
49
-
50
- FailDesc = proc do |status, message = "", out = ""|
51
- now = Time.now
52
- proc do
53
- EnvUtil.failure_description(status, now, message, out)
54
- end
55
- end
56
-
57
- def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil,
58
- success: nil, **opt)
59
- args = Array(args).dup
60
- args.insert((Hash === args[0] ? 1 : 0), '--disable=gems')
61
- stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, **opt)
62
- desc = FailDesc[status, message, stderr]
63
- if block_given?
64
- raise "test_stdout ignored, use block only or without block" if test_stdout != []
65
- raise "test_stderr ignored, use block only or without block" if test_stderr != []
66
- yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp }, status)
67
- else
68
- all_assertions(desc) do |a|
69
- [["stdout", test_stdout, stdout], ["stderr", test_stderr, stderr]].each do |key, exp, act|
70
- a.for(key) do
71
- if exp.is_a?(Regexp)
72
- assert_match(exp, act)
73
- elsif exp.all? {|e| String === e}
74
- assert_equal(exp, act.lines.map {|l| l.chomp })
75
- else
76
- assert_pattern_list(exp, act)
77
- end
78
- end
79
- end
80
- unless success.nil?
81
- a.for("success?") do
82
- if success
83
- assert_predicate(status, :success?)
84
- else
85
- assert_not_predicate(status, :success?)
86
- end
87
- end
88
- end
89
- end
90
- status
91
- end
92
- end
93
-
94
- if defined?(RubyVM::InstructionSequence)
95
- def syntax_check(code, fname, line)
96
- code = code.dup.force_encoding(Encoding::UTF_8)
97
- RubyVM::InstructionSequence.compile(code, fname, fname, line)
98
- :ok
99
- ensure
100
- raise if SyntaxError === $!
101
- end
102
- else
103
- def syntax_check(code, fname, line)
104
- code = code.b
105
- code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
106
- "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
107
- }
108
- code = code.force_encoding(Encoding::UTF_8)
109
- catch {|tag| eval(code, binding, fname, line - 1)}
110
- end
111
- end
112
-
113
- def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt)
114
- # TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail
115
- pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
116
-
117
- require_relative 'memory_status'
118
- raise Test::Unit::PendedError, "unsupported platform" unless defined?(Memory::Status)
119
-
120
- token_dump, token_re = new_test_token
121
- envs = args.shift if Array === args and Hash === args.first
122
- args = [
123
- "--disable=gems",
124
- "-r", File.expand_path("../memory_status", __FILE__),
125
- *args,
126
- "-v", "-",
127
- ]
128
- if defined? Memory::NO_MEMORY_LEAK_ENVS then
129
- envs ||= {}
130
- newenvs = envs.merge(Memory::NO_MEMORY_LEAK_ENVS) { |_, _, _| break }
131
- envs = newenvs if newenvs
132
- end
133
- args.unshift(envs) if envs
134
- cmd = [
135
- 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new}"}',
136
- prepare,
137
- 'STDERR.puts('"#{token_dump}"'"START=#{$initial_status = Memory::Status.new}")',
138
- '$initial_size = $initial_status.size',
139
- code,
140
- 'GC.start',
141
- ].join("\n")
142
- _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, **opt)
143
- before = err.sub!(/^#{token_re}START=(\{.*\})\n/, '') && Memory::Status.parse($1)
144
- after = err.sub!(/^#{token_re}FINAL=(\{.*\})\n/, '') && Memory::Status.parse($1)
145
- assert(status.success?, FailDesc[status, message, err])
146
- ([:size, (rss && :rss)] & after.members).each do |n|
147
- b = before[n]
148
- a = after[n]
149
- next unless a > 0 and b > 0
150
- assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"})
151
- end
152
- rescue LoadError
153
- pend
154
- end
155
-
156
- # :call-seq:
157
- # assert_nothing_raised( *args, &block )
158
- #
159
- #If any exceptions are given as arguments, the assertion will
160
- #fail if one of those exceptions are raised. Otherwise, the test fails
161
- #if any exceptions are raised.
162
- #
163
- #The final argument may be a failure message.
164
- #
165
- # assert_nothing_raised RuntimeError do
166
- # raise Exception #Assertion passes, Exception is not a RuntimeError
167
- # end
168
- #
169
- # assert_nothing_raised do
170
- # raise Exception #Assertion fails
171
- # end
172
- def assert_nothing_raised(*args)
173
- self._assertions += 1
174
- if Module === args.last
175
- msg = nil
176
- else
177
- msg = args.pop
178
- end
179
- begin
180
- yield
181
- rescue Test::Unit::PendedError, *(Test::Unit::AssertionFailedError if args.empty?)
182
- raise
183
- rescue *(args.empty? ? Exception : args) => e
184
- msg = message(msg) {
185
- "Exception raised:\n<#{mu_pp(e)}>\n""Backtrace:\n" <<
186
- Test.filter_backtrace(e.backtrace).map{|frame| " #{frame}"}.join("\n")
187
- }
188
- raise Test::Unit::AssertionFailedError, msg.call, e.backtrace
189
- end
190
- end
191
-
192
- def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil)
193
- fname ||= caller_locations(2, 1)[0]
194
- mesg ||= fname.to_s
195
- verbose, $VERBOSE = $VERBOSE, verbose
196
- case
197
- when Array === fname
198
- fname, line = *fname
199
- when defined?(fname.path) && defined?(fname.lineno)
200
- fname, line = fname.path, fname.lineno
201
- else
202
- line = 1
203
- end
204
- yield(code, fname, line, message(mesg) {
205
- if code.end_with?("\n")
206
- "```\n#{code}```\n"
207
- else
208
- "```\n#{code}\n```\n""no-newline"
209
- end
210
- })
211
- ensure
212
- $VERBOSE = verbose
213
- end
214
-
215
- def assert_valid_syntax(code, *args, **opt)
216
- prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg|
217
- yield if defined?(yield)
218
- assert_nothing_raised(SyntaxError, mesg) do
219
- assert_equal(:ok, syntax_check(src, fname, line), mesg)
220
- end
221
- end
222
- end
223
-
224
- def assert_normal_exit(testsrc, message = '', child_env: nil, **opt)
225
- assert_valid_syntax(testsrc, caller_locations(1, 1)[0])
226
- if child_env
227
- child_env = [child_env]
228
- else
229
- child_env = []
230
- end
231
- out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt)
232
- assert !status.signaled?, FailDesc[status, message, out]
233
- end
234
-
235
- def assert_ruby_status(args, test_stdin="", message=nil, **opt)
236
- out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt)
237
- desc = FailDesc[status, message, out]
238
- assert(!status.signaled?, desc)
239
- message ||= "ruby exit status is not success:"
240
- assert(status.success?, desc)
241
- end
242
-
243
- ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")
244
-
245
- def separated_runner(token, out = nil)
246
- include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) })
247
- out = out ? IO.new(out, 'w') : STDOUT
248
- at_exit {
249
- out.puts "#{token}<error>", [Marshal.dump($!)].pack('m'), "#{token}</error>", "#{token}assertions=#{self._assertions}"
250
- }
251
- Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) if defined?(Test::Unit::Runner)
252
- end
253
-
254
- def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
255
- unless file and line
256
- loc, = caller_locations(1,1)
257
- file ||= loc.path
258
- line ||= loc.lineno
259
- end
260
- capture_stdout = true
261
- unless /mswin|mingw/ =~ RbConfig::CONFIG['host_os']
262
- capture_stdout = false
263
- opt[:out] = Test::Unit::Runner.output if defined?(Test::Unit::Runner)
264
- res_p, res_c = IO.pipe
265
- opt[:ios] = [res_c]
266
- end
267
- token_dump, token_re = new_test_token
268
- src = <<eom
269
- # -*- coding: #{line += __LINE__; src.encoding}; -*-
270
- BEGIN {
271
- require "test/unit";include Test::Unit::Assertions;require #{__FILE__.dump};include Test::Unit::CoreAssertions
272
- separated_runner #{token_dump}, #{res_c&.fileno || 'nil'}
273
- }
274
- #{line -= __LINE__; src}
275
- eom
276
- args = args.dup
277
- args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
278
- args << "--debug" if RUBY_ENGINE == 'jruby' # warning: tracing (e.g. set_trace_func) will not capture all events without --debug flag
279
- stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)
280
- ensure
281
- if res_c
282
- res_c.close
283
- res = res_p.read
284
- res_p.close
285
- else
286
- res = stdout
287
- end
288
- raise if $!
289
- abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
290
- assert(!abort, FailDesc[status, nil, stderr])
291
- self._assertions += res[/^#{token_re}assertions=(\d+)/, 1].to_i
292
- begin
293
- res = Marshal.load(res[/^#{token_re}<error>\n\K.*\n(?=#{token_re}<\/error>$)/m].unpack1("m"))
294
- rescue => marshal_error
295
- ignore_stderr = nil
296
- res = nil
297
- end
298
- if res and !(SystemExit === res)
299
- if bt = res.backtrace
300
- bt.each do |l|
301
- l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
302
- end
303
- bt.concat(caller)
304
- else
305
- res.set_backtrace(caller)
306
- end
307
- raise res
308
- end
309
-
310
- # really is it succeed?
311
- unless ignore_stderr
312
- # the body of assert_separately must not output anything to detect error
313
- assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr])
314
- end
315
- assert(status.success?, FailDesc[status, "assert_separately failed", stderr])
316
- raise marshal_error if marshal_error
317
- end
318
-
319
- # Run Ractor-related test without influencing the main test suite
320
- def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
321
- return unless defined?(Ractor)
322
-
323
- require = "require #{require.inspect}" if require
324
- if require_relative
325
- dir = File.dirname(caller_locations[0,1][0].absolute_path)
326
- full_path = File.expand_path(require_relative, dir)
327
- require = "#{require}; require #{full_path.inspect}"
328
- end
329
-
330
- assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt)
331
- #{require}
332
- previous_verbose = $VERBOSE
333
- $VERBOSE = nil
334
- Ractor.new {} # trigger initial warning
335
- $VERBOSE = previous_verbose
336
- #{src}
337
- RUBY
338
- end
339
-
340
- # :call-seq:
341
- # assert_throw( tag, failure_message = nil, &block )
342
- #
343
- #Fails unless the given block throws +tag+, returns the caught
344
- #value otherwise.
345
- #
346
- #An optional failure message may be provided as the final argument.
347
- #
348
- # tag = Object.new
349
- # assert_throw(tag, "#{tag} was not thrown!") do
350
- # throw tag
351
- # end
352
- def assert_throw(tag, msg = nil)
353
- ret = catch(tag) do
354
- begin
355
- yield(tag)
356
- rescue UncaughtThrowError => e
357
- thrown = e.tag
358
- end
359
- msg = message(msg) {
360
- "Expected #{mu_pp(tag)} to have been thrown"\
361
- "#{%Q[, not #{thrown}] if thrown}"
362
- }
363
- assert(false, msg)
364
- end
365
- assert(true)
366
- ret
367
- end
368
-
369
- # :call-seq:
370
- # assert_raise( *args, &block )
371
- #
372
- #Tests if the given block raises an exception. Acceptable exception
373
- #types may be given as optional arguments. If the last argument is a
374
- #String, it will be used as the error message.
375
- #
376
- # assert_raise do #Fails, no Exceptions are raised
377
- # end
378
- #
379
- # assert_raise NameError do
380
- # puts x #Raises NameError, so assertion succeeds
381
- # end
382
- def assert_raise(*exp, &b)
383
- case exp.last
384
- when String, Proc
385
- msg = exp.pop
386
- end
387
-
388
- begin
389
- yield
390
- rescue Test::Unit::PendedError => e
391
- return e if exp.include? Test::Unit::PendedError
392
- raise e
393
- rescue Exception => e
394
- expected = exp.any? { |ex|
395
- if ex.instance_of? Module then
396
- e.kind_of? ex
397
- else
398
- e.instance_of? ex
399
- end
400
- }
401
-
402
- assert expected, proc {
403
- flunk(message(msg) {"#{mu_pp(exp)} exception expected, not #{mu_pp(e)}"})
404
- }
405
-
406
- return e
407
- ensure
408
- unless e
409
- exp = exp.first if exp.size == 1
410
-
411
- flunk(message(msg) {"#{mu_pp(exp)} expected but nothing was raised"})
412
- end
413
- end
414
- end
415
-
416
- # :call-seq:
417
- # assert_raise_with_message(exception, expected, msg = nil, &block)
418
- #
419
- #Tests if the given block raises an exception with the expected
420
- #message.
421
- #
422
- # assert_raise_with_message(RuntimeError, "foo") do
423
- # nil #Fails, no Exceptions are raised
424
- # end
425
- #
426
- # assert_raise_with_message(RuntimeError, "foo") do
427
- # raise ArgumentError, "foo" #Fails, different Exception is raised
428
- # end
429
- #
430
- # assert_raise_with_message(RuntimeError, "foo") do
431
- # raise "bar" #Fails, RuntimeError is raised but the message differs
432
- # end
433
- #
434
- # assert_raise_with_message(RuntimeError, "foo") do
435
- # raise "foo" #Raises RuntimeError with the message, so assertion succeeds
436
- # end
437
- def assert_raise_with_message(exception, expected, msg = nil, &block)
438
- case expected
439
- when String
440
- assert = :assert_equal
441
- when Regexp
442
- assert = :assert_match
443
- else
444
- raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}"
445
- end
446
-
447
- ex = m = nil
448
- EnvUtil.with_default_internal(expected.encoding) do
449
- ex = assert_raise(exception, msg || proc {"Exception(#{exception}) with message matches to #{expected.inspect}"}) do
450
- yield
451
- end
452
- m = ex.message
453
- end
454
- msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"}
455
-
456
- if assert == :assert_equal
457
- assert_equal(expected, m, msg)
458
- else
459
- msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp m}" }
460
- assert expected =~ m, msg
461
- block.binding.eval("proc{|_|$~=_}").call($~)
462
- end
463
- ex
464
- end
465
-
466
- TEST_DIR = File.join(__dir__, "test/unit") #:nodoc:
467
-
468
- # :call-seq:
469
- # assert(test, [failure_message])
470
- #
471
- #Tests if +test+ is true.
472
- #
473
- #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
474
- #as the failure message. Otherwise, the result of calling +msg+ will be
475
- #used as the message if the assertion fails.
476
- #
477
- #If no +msg+ is given, a default message will be used.
478
- #
479
- # assert(false, "This was expected to be true")
480
- def assert(test, *msgs)
481
- case msg = msgs.first
482
- when String, Proc
483
- when nil
484
- msgs.shift
485
- else
486
- bt = caller.reject { |s| s.start_with?(TEST_DIR) }
487
- raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
488
- end unless msgs.empty?
489
- super
490
- end
491
-
492
- # :call-seq:
493
- # assert_respond_to( object, method, failure_message = nil )
494
- #
495
- #Tests if the given Object responds to +method+.
496
- #
497
- #An optional failure message may be provided as the final argument.
498
- #
499
- # assert_respond_to("hello", :reverse) #Succeeds
500
- # assert_respond_to("hello", :does_not_exist) #Fails
501
- def assert_respond_to(obj, (meth, *priv), msg = nil)
502
- unless priv.empty?
503
- msg = message(msg) {
504
- "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
505
- }
506
- return assert obj.respond_to?(meth, *priv), msg
507
- end
508
- #get rid of overcounting
509
- if caller_locations(1, 1)[0].path.start_with?(TEST_DIR)
510
- return if obj.respond_to?(meth)
511
- end
512
- super(obj, meth, msg)
513
- end
514
-
515
- # :call-seq:
516
- # assert_not_respond_to( object, method, failure_message = nil )
517
- #
518
- #Tests if the given Object does not respond to +method+.
519
- #
520
- #An optional failure message may be provided as the final argument.
521
- #
522
- # assert_not_respond_to("hello", :reverse) #Fails
523
- # assert_not_respond_to("hello", :does_not_exist) #Succeeds
524
- def assert_not_respond_to(obj, (meth, *priv), msg = nil)
525
- unless priv.empty?
526
- msg = message(msg) {
527
- "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
528
- }
529
- return assert !obj.respond_to?(meth, *priv), msg
530
- end
531
- #get rid of overcounting
532
- if caller_locations(1, 1)[0].path.start_with?(TEST_DIR)
533
- return unless obj.respond_to?(meth)
534
- end
535
- refute_respond_to(obj, meth, msg)
536
- end
537
-
538
- # pattern_list is an array which contains regexp and :*.
539
- # :* means any sequence.
540
- #
541
- # pattern_list is anchored.
542
- # Use [:*, regexp, :*] for non-anchored match.
543
- def assert_pattern_list(pattern_list, actual, message=nil)
544
- rest = actual
545
- anchored = true
546
- pattern_list.each_with_index {|pattern, i|
547
- if pattern == :*
548
- anchored = false
549
- else
550
- if anchored
551
- match = rest.rindex(pattern, 0)
552
- else
553
- match = rest.index(pattern)
554
- end
555
- if match
556
- post_match = $~ ? $~.post_match : rest[match+pattern.size..-1]
557
- else
558
- msg = message(msg) {
559
- expect_msg = "Expected #{mu_pp pattern}\n"
560
- if /\n[^\n]/ =~ rest
561
- actual_mesg = +"to match\n"
562
- rest.scan(/.*\n+/) {
563
- actual_mesg << ' ' << $&.inspect << "+\n"
564
- }
565
- actual_mesg.sub!(/\+\n\z/, '')
566
- else
567
- actual_mesg = "to match " + mu_pp(rest)
568
- end
569
- actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters"
570
- expect_msg + actual_mesg
571
- }
572
- assert false, msg
573
- end
574
- rest = post_match
575
- anchored = true
576
- end
577
- }
578
- if anchored
579
- assert_equal("", rest)
580
- end
581
- end
582
-
583
- def assert_warning(pat, msg = nil)
584
- result = nil
585
- stderr = EnvUtil.with_default_internal(pat.encoding) {
586
- EnvUtil.verbose_warning {
587
- result = yield
588
- }
589
- }
590
- msg = message(msg) {diff pat, stderr}
591
- assert(pat === stderr, msg)
592
- result
593
- end
594
-
595
- def assert_warn(*args)
596
- assert_warning(*args) {$VERBOSE = false; yield}
597
- end
598
-
599
- def assert_deprecated_warning(mesg = /deprecated/)
600
- assert_warning(mesg) do
601
- Warning[:deprecated] = true if Warning.respond_to?(:[]=)
602
- yield
603
- end
604
- end
605
-
606
- def assert_deprecated_warn(mesg = /deprecated/)
607
- assert_warn(mesg) do
608
- Warning[:deprecated] = true if Warning.respond_to?(:[]=)
609
- yield
610
- end
611
- end
612
-
613
- class << (AssertFile = Struct.new(:failure_message).new)
614
- include Assertions
615
- include CoreAssertions
616
- def assert_file_predicate(predicate, *args)
617
- if /\Anot_/ =~ predicate
618
- predicate = $'
619
- neg = " not"
620
- end
621
- result = File.__send__(predicate, *args)
622
- result = !result if neg
623
- mesg = "Expected file ".dup << args.shift.inspect
624
- mesg << "#{neg} to be #{predicate}"
625
- mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty?
626
- mesg << " #{failure_message}" if failure_message
627
- assert(result, mesg)
628
- end
629
- alias method_missing assert_file_predicate
630
-
631
- def for(message)
632
- clone.tap {|a| a.failure_message = message}
633
- end
634
- end
635
-
636
- class AllFailures
637
- attr_reader :failures
638
-
639
- def initialize
640
- @count = 0
641
- @failures = {}
642
- end
643
-
644
- def for(key)
645
- @count += 1
646
- yield key
647
- rescue Exception => e
648
- @failures[key] = [@count, e]
649
- end
650
-
651
- def foreach(*keys)
652
- keys.each do |key|
653
- @count += 1
654
- begin
655
- yield key
656
- rescue Exception => e
657
- @failures[key] = [@count, e]
658
- end
659
- end
660
- end
661
-
662
- def message
663
- i = 0
664
- total = @count.to_s
665
- fmt = "%#{total.size}d"
666
- @failures.map {|k, (n, v)|
667
- v = v.message
668
- "\n#{i+=1}. [#{fmt%n}/#{total}] Assertion for #{k.inspect}\n#{v.b.gsub(/^/, ' | ').force_encoding(v.encoding)}"
669
- }.join("\n")
670
- end
671
-
672
- def pass?
673
- @failures.empty?
674
- end
675
- end
676
-
677
- # threads should respond to shift method.
678
- # Array can be used.
679
- def assert_join_threads(threads, message = nil)
680
- errs = []
681
- values = []
682
- while th = threads.shift
683
- begin
684
- values << th.value
685
- rescue Exception
686
- errs << [th, $!]
687
- th = nil
688
- end
689
- end
690
- values
691
- ensure
692
- if th&.alive?
693
- th.raise(Timeout::Error.new)
694
- th.join rescue errs << [th, $!]
695
- end
696
- if !errs.empty?
697
- msg = "exceptions on #{errs.length} threads:\n" +
698
- errs.map {|t, err|
699
- "#{t.inspect}:\n" +
700
- err.full_message(highlight: false, order: :top)
701
- }.join("\n---\n")
702
- if message
703
- msg = "#{message}\n#{msg}"
704
- end
705
- raise Test::Unit::AssertionFailedError, msg
706
- end
707
- end
708
-
709
- def assert_all?(obj, m = nil, &blk)
710
- failed = []
711
- obj.each do |*a, &b|
712
- unless blk.call(*a, &b)
713
- failed << (a.size > 1 ? a : a[0])
714
- end
715
- end
716
- assert(failed.empty?, message(m) {failed.pretty_inspect})
717
- end
718
-
719
- def assert_all_assertions(msg = nil)
720
- all = AllFailures.new
721
- yield all
722
- ensure
723
- assert(all.pass?, message(msg) {all.message.chomp(".")})
724
- end
725
- alias all_assertions assert_all_assertions
726
-
727
- def assert_all_assertions_foreach(msg = nil, *keys, &block)
728
- all = AllFailures.new
729
- all.foreach(*keys, &block)
730
- ensure
731
- assert(all.pass?, message(msg) {all.message.chomp(".")})
732
- end
733
- alias all_assertions_foreach assert_all_assertions_foreach
734
-
735
- def diff(exp, act)
736
- require 'pp'
737
- q = PP.new(+"")
738
- q.guard_inspect_key do
739
- q.group(2, "expected: ") do
740
- q.pp exp
741
- end
742
- q.text q.newline
743
- q.group(2, "actual: ") do
744
- q.pp act
745
- end
746
- q.flush
747
- end
748
- q.output
749
- end
750
-
751
- def new_test_token
752
- token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
753
- return token.dump, Regexp.quote(token)
754
- end
755
- end
756
- end
757
- end