did_you_mean 1.6.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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