test-unit-ruby-core 1.0.14 → 1.0.16
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.
- checksums.yaml +4 -4
- data/lib/core_assertions.rb +53 -22
- data/lib/envutil.rb +16 -5
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 542bb539eb9d5482af2e15d1f343129f6ce264e68a382e31b12205cb93f01e0d
|
|
4
|
+
data.tar.gz: 68ac63efa6ccc2e04299a7cee8443347553bf6670cd1fdf00d8a429b8b65d24f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d460cda4850819f3f04cfa3b9ca4a75df95982276e31bb60017515af5169734100bbd7371e3fbf79424d827c83d9de6d449531b40c0c2c526f141b18a8e8362c
|
|
7
|
+
data.tar.gz: aec38efd7edcdeb6b860ded7a6919ee48224229ba15cca086f2a2e73e35dc2c78937b5521fc9fb7d09567f9a1a885618125c8fb65f6f251abf140fc32172a1db
|
data/lib/core_assertions.rb
CHANGED
|
@@ -18,11 +18,11 @@ module Test
|
|
|
18
18
|
|
|
19
19
|
unless $DEBUG then
|
|
20
20
|
bt.each do |line|
|
|
21
|
-
break if pattern
|
|
21
|
+
break if pattern =~ line
|
|
22
22
|
new_bt << line
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
new_bt = bt.reject { |line| pattern
|
|
25
|
+
new_bt = bt.reject { |line| pattern =~ line } if new_bt.empty?
|
|
26
26
|
new_bt = bt.dup if new_bt.empty?
|
|
27
27
|
else
|
|
28
28
|
new_bt = bt.dup
|
|
@@ -303,9 +303,34 @@ module Test
|
|
|
303
303
|
|
|
304
304
|
def separated_runner(token, out = nil)
|
|
305
305
|
include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) })
|
|
306
|
+
|
|
306
307
|
out = out ? IO.new(out, 'w') : STDOUT
|
|
308
|
+
|
|
309
|
+
# avoid method redefinitions
|
|
310
|
+
out_write = out.method(:write)
|
|
311
|
+
integer_to_s = Integer.instance_method(:to_s)
|
|
312
|
+
array_pack = Array.instance_method(:pack)
|
|
313
|
+
marshal_dump = Marshal.method(:dump)
|
|
314
|
+
assertions_ivar_set = Test::Unit::Assertions.method(:instance_variable_set)
|
|
315
|
+
assertions_ivar_get = Test::Unit::Assertions.method(:instance_variable_get)
|
|
316
|
+
Test::Unit::Assertions.module_eval do
|
|
317
|
+
@_assertions = 0
|
|
318
|
+
|
|
319
|
+
undef _assertions=
|
|
320
|
+
define_method(:_assertions=, ->(n) {assertions_ivar_set.call(:@_assertions, n)})
|
|
321
|
+
|
|
322
|
+
undef _assertions
|
|
323
|
+
define_method(:_assertions, -> {assertions_ivar_get.call(:@_assertions)})
|
|
324
|
+
end
|
|
325
|
+
# assume Method#call and UnboundMethod#bind_call need to work as the original
|
|
326
|
+
|
|
307
327
|
at_exit {
|
|
308
|
-
|
|
328
|
+
assertions = assertions_ivar_get.call(:@_assertions)
|
|
329
|
+
out_write.call <<~OUT
|
|
330
|
+
<error id="#{token}" assertions=#{integer_to_s.bind(assertions).call}>
|
|
331
|
+
#{array_pack.bind([marshal_dump.call($!)]).call('m0')}
|
|
332
|
+
</error id="#{token}">
|
|
333
|
+
OUT
|
|
309
334
|
}
|
|
310
335
|
if defined?(Test::Unit::Runner)
|
|
311
336
|
Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true)
|
|
@@ -339,6 +364,8 @@ eom
|
|
|
339
364
|
args = args.dup
|
|
340
365
|
args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
|
|
341
366
|
args << "--debug" if RUBY_ENGINE == 'jruby' # warning: tracing (e.g. set_trace_func) will not capture all events without --debug flag
|
|
367
|
+
# power_assert 3 requires ruby 3.1 or later
|
|
368
|
+
args << "-W:no-experimental" if ("2.7."..."3.1.").cover?(RUBY_VERSION)
|
|
342
369
|
stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)
|
|
343
370
|
|
|
344
371
|
if sanitizers&.lsan_enabled?
|
|
@@ -357,27 +384,30 @@ eom
|
|
|
357
384
|
end
|
|
358
385
|
raise if $!
|
|
359
386
|
abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
|
|
387
|
+
marshal_error = nil
|
|
360
388
|
assert(!abort, FailDesc[status, nil, stderr])
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if res and !(SystemExit === res)
|
|
369
|
-
if bt = res.backtrace
|
|
370
|
-
bt.each do |l|
|
|
371
|
-
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
|
|
372
|
-
end
|
|
373
|
-
bt.concat(caller)
|
|
389
|
+
res.scan(/^<error id="#{token_re}" assertions=(\d+)>\n(.*?)\n(?=<\/error id="#{token_re}">$)/m) do
|
|
390
|
+
self._assertions += $1.to_i
|
|
391
|
+
begin
|
|
392
|
+
res = Marshal.load($2.unpack1("m")) or next
|
|
393
|
+
rescue => marshal_error
|
|
394
|
+
ignore_stderr = nil
|
|
395
|
+
res = nil
|
|
374
396
|
else
|
|
375
|
-
res
|
|
397
|
+
next if SystemExit === res
|
|
398
|
+
if bt = res.backtrace
|
|
399
|
+
bt.each do |l|
|
|
400
|
+
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
|
|
401
|
+
end
|
|
402
|
+
bt.concat(caller)
|
|
403
|
+
else
|
|
404
|
+
res.set_backtrace(caller)
|
|
405
|
+
end
|
|
406
|
+
raise res
|
|
376
407
|
end
|
|
377
|
-
raise res
|
|
378
408
|
end
|
|
379
409
|
|
|
380
|
-
# really
|
|
410
|
+
# really did it succeed?
|
|
381
411
|
unless ignore_stderr
|
|
382
412
|
# the body of assert_separately must not output anything to detect error
|
|
383
413
|
assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr])
|
|
@@ -388,7 +418,7 @@ eom
|
|
|
388
418
|
|
|
389
419
|
# Run Ractor-related test without influencing the main test suite
|
|
390
420
|
def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
|
|
391
|
-
|
|
421
|
+
omit unless defined?(Ractor)
|
|
392
422
|
|
|
393
423
|
# https://bugs.ruby-lang.org/issues/21262
|
|
394
424
|
shim_value = "class Ractor; alias value take; end" unless Ractor.method_defined?(:value)
|
|
@@ -883,10 +913,11 @@ eom
|
|
|
883
913
|
|
|
884
914
|
first = seq.first
|
|
885
915
|
*arg = pre.call(first)
|
|
886
|
-
|
|
916
|
+
raw_times = (0..(rehearsal || (2 * first))).map do
|
|
887
917
|
measure[arg, "rehearsal"].nonzero?
|
|
888
918
|
end
|
|
889
|
-
times.compact
|
|
919
|
+
times = raw_times.compact
|
|
920
|
+
raise "all measurements are zero: #{raw_times.inspect}" if times.empty?
|
|
890
921
|
tmin, tmax = times.minmax
|
|
891
922
|
|
|
892
923
|
# safe_factor * tmax * rehearsal_time_variance_factor(equals to 1 when variance is small)
|
data/lib/envutil.rb
CHANGED
|
@@ -63,6 +63,14 @@ module EnvUtil
|
|
|
63
63
|
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
if RUBY_ENGINE == "truffleruby"
|
|
67
|
+
# Tests relying on timeout have high variance on TruffleRuby due to the highly-optimizing JIT, deoptimization, profiling interpreter, different GC, etc.
|
|
68
|
+
# Setting a default timeout scale helps avoid transient failures for tests relying on timeouts.
|
|
69
|
+
# We choose 10 because it is the same number used in CRuby CI on macOS:
|
|
70
|
+
# https://github.com/ruby/ruby/blob/9d46b0c735877f152a0b4b16b8153c6f395dee28/.github/workflows/macos.yml#L133
|
|
71
|
+
self.timeout_scale = 10
|
|
72
|
+
end
|
|
73
|
+
|
|
66
74
|
def apply_timeout_scale(t)
|
|
67
75
|
if scale = EnvUtil.timeout_scale
|
|
68
76
|
t * scale
|
|
@@ -122,7 +130,7 @@ module EnvUtil
|
|
|
122
130
|
|
|
123
131
|
register("gdb") do
|
|
124
132
|
class << self
|
|
125
|
-
def usable?; system(*%w[gdb --batch --quiet --nx -ex exit]); end
|
|
133
|
+
def usable?; system(*%w[gdb --batch --quiet --nx -ex exit], out: IO::NULL, err: IO::NULL); end
|
|
126
134
|
def start(pid, *args, **opts)
|
|
127
135
|
spawn(*%W[gdb --batch --quiet --pid #{pid}], *args, **opts)
|
|
128
136
|
end
|
|
@@ -132,7 +140,7 @@ module EnvUtil
|
|
|
132
140
|
|
|
133
141
|
register("lldb") do
|
|
134
142
|
class << self
|
|
135
|
-
def usable?; system(*%w[lldb -Q --no-lldbinit -o exit]); end
|
|
143
|
+
def usable?; system(*%w[lldb -Q --no-lldbinit -o exit], out: IO::NULL, err: IO::NULL); end
|
|
136
144
|
def start(pid, *args, **opts)
|
|
137
145
|
spawn(*%W[lldb --batch -Q --attach-pid #{pid}], *args, **opts)
|
|
138
146
|
end
|
|
@@ -141,7 +149,10 @@ module EnvUtil
|
|
|
141
149
|
end
|
|
142
150
|
|
|
143
151
|
def self.search
|
|
144
|
-
|
|
152
|
+
# Cache the result even when no debugger is available, not to probe
|
|
153
|
+
# unusable debuggers repeatedly.
|
|
154
|
+
return @debugger if defined?(@debugger)
|
|
155
|
+
@debugger = @list.find(&:usable?)
|
|
145
156
|
end
|
|
146
157
|
end
|
|
147
158
|
|
|
@@ -228,7 +239,7 @@ module EnvUtil
|
|
|
228
239
|
args = [args] if args.kind_of?(String)
|
|
229
240
|
# use the same parser as current ruby
|
|
230
241
|
if (args.none? { |arg| arg.start_with?("--parser=") } and
|
|
231
|
-
/^ +--parser=/ =~ IO.popen([rubybin, "--help"], &:read))
|
|
242
|
+
/^ +--parser=/ =~ IO.popen([{"PAGER"=>nil, "RUBY_PAGER"=>nil}, rubybin, "--help", err: %i[child out]], &:read))
|
|
232
243
|
args = ["--parser=#{current_parser}"] + args
|
|
233
244
|
end
|
|
234
245
|
pid = spawn(child_env, *precommand, rubybin, *args, opt)
|
|
@@ -279,7 +290,7 @@ module EnvUtil
|
|
|
279
290
|
module_function :invoke_ruby
|
|
280
291
|
|
|
281
292
|
def current_parser
|
|
282
|
-
features = RUBY_DESCRIPTION[%r{\)\K [-+*/%._0-9a-zA-Z ]*(?=\[[-+*/%._0-9a-zA-Z]+\]\z)}]
|
|
293
|
+
features = RUBY_DESCRIPTION[%r{\)\K [-+*/%._0-9a-zA-Z\[\] ]*(?=\[[-+*/%._0-9a-zA-Z]+\]\z)}]
|
|
283
294
|
features&.split&.include?("+PRISM") ? "prism" : "parse.y"
|
|
284
295
|
end
|
|
285
296
|
module_function :current_parser
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test-unit-ruby-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.16
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hiroshi SHIBATA
|
|
8
8
|
- Nobu Nakada
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-08-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: test-unit
|