test-unit-ruby-core 1.0.7 → 1.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fbe8678b64c96aecfb825b2a2544e7089a681be164521d259880d07e5cf0589
4
- data.tar.gz: 2726f59cb0cf549b49a1250d11324fe26f2eb93eb685740086bed65491b3f00f
3
+ metadata.gz: dd98ff260648ee2456653769b0d62498de82504c7503d7a819195b0aa0ca19cf
4
+ data.tar.gz: a88004e98851e791fbbdf2441d927108f32d0ab3fc9e439c48852aac131287f4
5
5
  SHA512:
6
- metadata.gz: 3880a3106697e03f423822c456d1753755078378106d0e4bbfc7a2bbe7305a4860897aae9716dd77ab33a7b9503ef484beaa9a06bcdabd4bfa72f3036a191582
7
- data.tar.gz: 9626368354be4eecb5c13a0d0fac687cd2c0ad8179315e899f1d27d564cd95b958ef07eea561d98102d362c56b49a08fac761c1e1dce7045afd7f84006aeddd3
6
+ metadata.gz: 1856091125153792795a0da717dc1ace6ca6082ea382bb2822d09729fc9cd17b6040ebfa23daeb67cbc245c74b28ea9776e54faa8e70973d8efd92846401a674
7
+ data.tar.gz: e2d76e33fb30ba8cd0cfe66e6ec284dd27933bd7cc3fa30127a45e68a8f8a917f28772680e45694f9c9c0020c1061cfc4cc9d9c9780f428a309403e21f9b53a8
@@ -97,11 +97,12 @@ module Test
97
97
  end
98
98
 
99
99
  def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil,
100
- success: nil, **opt)
100
+ success: nil, failed: nil, **opt)
101
101
  args = Array(args).dup
102
102
  args.insert((Hash === args[0] ? 1 : 0), '--disable=gems')
103
103
  stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, **opt)
104
- desc = FailDesc[status, message, stderr]
104
+ desc = failed[status, message, stderr] if failed
105
+ desc ||= FailDesc[status, message, stderr]
105
106
  if block_given?
106
107
  raise "test_stdout ignored, use block only or without block" if test_stdout != []
107
108
  raise "test_stderr ignored, use block only or without block" if test_stderr != []
@@ -495,14 +496,13 @@ eom
495
496
  case expected
496
497
  when String
497
498
  assert = :assert_equal
498
- when Regexp
499
- assert = :assert_match
500
499
  else
501
- raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}"
500
+ assert_respond_to(expected, :===)
501
+ assert = :assert_match
502
502
  end
503
503
 
504
504
  ex = m = nil
505
- EnvUtil.with_default_internal(expected.encoding) do
505
+ EnvUtil.with_default_internal(of: expected) do
506
506
  ex = assert_raise(exception, msg || proc {"Exception(#{exception}) with message matches to #{expected.inspect}"}) do
507
507
  yield
508
508
  end
@@ -520,6 +520,43 @@ eom
520
520
  ex
521
521
  end
522
522
 
523
+ # :call-seq:
524
+ # assert_raise_kind_of(*args, &block)
525
+ #
526
+ #Tests if the given block raises one of the given exceptions or
527
+ #sub exceptions of the given exceptions. If the last argument
528
+ #is a String, it will be used as the error message.
529
+ #
530
+ # assert_raise do #Fails, no Exceptions are raised
531
+ # end
532
+ #
533
+ # assert_raise SystemCallErr do
534
+ # Dir.chdir(__FILE__) #Raises Errno::ENOTDIR, so assertion succeeds
535
+ # end
536
+ def assert_raise_kind_of(*exp, &b)
537
+ case exp.last
538
+ when String, Proc
539
+ msg = exp.pop
540
+ end
541
+
542
+ begin
543
+ yield
544
+ rescue Test::Unit::PendedError => e
545
+ raise e unless exp.include? Test::Unit::PendedError
546
+ rescue *exp => e
547
+ pass
548
+ rescue Exception => e
549
+ flunk(message(msg) {"#{mu_pp(exp)} family exception expected, not #{mu_pp(e)}"})
550
+ ensure
551
+ unless e
552
+ exp = exp.first if exp.size == 1
553
+
554
+ flunk(message(msg) {"#{mu_pp(exp)} family expected but nothing was raised"})
555
+ end
556
+ end
557
+ e
558
+ end
559
+
523
560
  TEST_DIR = File.join(__dir__, "test/unit") #:nodoc:
524
561
 
525
562
  # :call-seq:
@@ -639,7 +676,7 @@ eom
639
676
 
640
677
  def assert_warning(pat, msg = nil)
641
678
  result = nil
642
- stderr = EnvUtil.with_default_internal(pat.encoding) {
679
+ stderr = EnvUtil.with_default_internal(of: pat) {
643
680
  EnvUtil.verbose_warning {
644
681
  result = yield
645
682
  }
@@ -653,17 +690,15 @@ eom
653
690
  assert_warning(*args) {$VERBOSE = false; yield}
654
691
  end
655
692
 
656
- def assert_deprecated_warning(mesg = /deprecated/)
693
+ def assert_deprecated_warning(mesg = /deprecated/, &block)
657
694
  assert_warning(mesg) do
658
- Warning[:deprecated] = true if Warning.respond_to?(:[]=)
659
- yield
695
+ EnvUtil.deprecation_warning(&block)
660
696
  end
661
697
  end
662
698
 
663
- def assert_deprecated_warn(mesg = /deprecated/)
699
+ def assert_deprecated_warn(mesg = /deprecated/, &block)
664
700
  assert_warn(mesg) do
665
- Warning[:deprecated] = true if Warning.respond_to?(:[]=)
666
- yield
701
+ EnvUtil.deprecation_warning(&block)
667
702
  end
668
703
  end
669
704
 
@@ -867,6 +902,82 @@ eom
867
902
  token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
868
903
  return token.dump, Regexp.quote(token)
869
904
  end
905
+
906
+ # Platform predicates
907
+
908
+ def self.mswin?
909
+ defined?(@mswin) ? @mswin : @mswin = RUBY_PLATFORM.include?('mswin')
910
+ end
911
+ private def mswin?
912
+ CoreAssertions.mswin?
913
+ end
914
+
915
+ def self.mingw?
916
+ defined?(@mingw) ? @mingw : @mingw = RUBY_PLATFORM.include?('mingw')
917
+ end
918
+ private def mingw?
919
+ CoreAssertions.mingw?
920
+ end
921
+
922
+ module_function def windows?
923
+ mswin? or mingw?
924
+ end
925
+
926
+ def self.version_compare(expected, actual)
927
+ expected.zip(actual).each {|e, a| z = (e <=> a); return z if z.nonzero?}
928
+ 0
929
+ end
930
+
931
+ def self.version_match?(expected, actual)
932
+ if !actual
933
+ false
934
+ elsif expected.empty?
935
+ true
936
+ elsif expected.size == 1 and Range === (range = expected.first)
937
+ b, e = range.begin, range.end
938
+ return false if b and (c = version_compare(Array(b), actual)) > 0
939
+ return false if e and (c = version_compare(Array(e), actual)) < 0
940
+ return false if e and range.exclude_end? and c == 0
941
+ true
942
+ else
943
+ version_compare(expected, actual).zero?
944
+ end
945
+ end
946
+
947
+ def self.linux?(*ver)
948
+ unless defined?(@linux)
949
+ @linux = RUBY_PLATFORM.include?('linux') && `uname -r`.scan(/\d+/).map(&:to_i)
950
+ end
951
+ version_match? ver, @linux
952
+ end
953
+ private def linux?(*ver)
954
+ CoreAssertions.linux?(*ver)
955
+ end
956
+
957
+ def self.glibc?(*ver)
958
+ unless defined?(@glibc)
959
+ libc = `/usr/bin/ldd /bin/sh`[/^\s*libc.*=> *\K\S*/]
960
+ if libc and /version (\d+)\.(\d+)\.$/ =~ IO.popen([libc], &:read)[]
961
+ @glibc = [$1.to_i, $2.to_i]
962
+ else
963
+ @glibc = false
964
+ end
965
+ end
966
+ version_match? ver, @glibc
967
+ end
968
+ private def glibc?(*ver)
969
+ CoreAssertions.glibc?(*ver)
970
+ end
971
+
972
+ def self.macos?(*ver)
973
+ unless defined?(@macos)
974
+ @macos = RUBY_PLATFORM.include?('darwin') && `sw_vers -productVersion`.scan(/\d+/).map(&:to_i)
975
+ end
976
+ version_match? ver, @macos
977
+ end
978
+ private def macos?(*ver)
979
+ CoreAssertions.macos?(*ver)
980
+ end
870
981
  end
871
982
  end
872
983
  end
data/lib/envutil.rb CHANGED
@@ -79,6 +79,70 @@ module EnvUtil
79
79
  end
80
80
  module_function :timeout
81
81
 
82
+ class Debugger
83
+ @list = []
84
+
85
+ attr_accessor :name
86
+
87
+ def self.register(name, &block)
88
+ @list << new(name, &block)
89
+ end
90
+
91
+ def initialize(name, &block)
92
+ @name = name
93
+ instance_eval(&block)
94
+ end
95
+
96
+ def usable?; false; end
97
+
98
+ def start(pid, *args) end
99
+
100
+ def dump(pid, timeout: 60, reprieve: timeout&.div(4))
101
+ dpid = start(pid, *command_file(File.join(__dir__, "dump.#{name}")), out: :err)
102
+ rescue Errno::ENOENT
103
+ return
104
+ else
105
+ return unless dpid
106
+ [[timeout, :TERM], [reprieve, :KILL]].find do |t, sig|
107
+ return EnvUtil.timeout(t) {Process.wait(dpid)}
108
+ rescue Timeout::Error
109
+ Process.kill(sig, dpid)
110
+ end
111
+ true
112
+ end
113
+
114
+ # sudo -n: --non-interactive
115
+ PRECOMMAND = (%[sudo -n] if /darwin/ =~ RUBY_PLATFORM)
116
+
117
+ def spawn(*args, **opts)
118
+ super(*PRECOMMAND, *args, **opts)
119
+ end
120
+
121
+ register("gdb") do
122
+ class << self
123
+ def usable?; system(*%w[gdb --batch --quiet --nx -ex exit]); end
124
+ def start(pid, *args, **opts)
125
+ spawn(*%W[gdb --batch --quiet --pid #{pid}], *args, **opts)
126
+ end
127
+ def command_file(file) "--command=#{file}"; end
128
+ end
129
+ end
130
+
131
+ register("lldb") do
132
+ class << self
133
+ def usable?; system(*%w[lldb -Q --no-lldbinit -o exit]); end
134
+ def start(pid, *args, **opts)
135
+ spawn(*%W[lldb --batch -Q --attach-pid #{pid}], *args, **opts)
136
+ end
137
+ def command_file(file) ["--source", file]; end
138
+ end
139
+ end
140
+
141
+ def self.search
142
+ @debugger ||= @list.find(&:usable?)
143
+ end
144
+ end
145
+
82
146
  def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1)
83
147
  reprieve = apply_timeout_scale(reprieve) if reprieve
84
148
 
@@ -94,17 +158,12 @@ module EnvUtil
94
158
  pgroup = pid
95
159
  end
96
160
 
97
- lldb = true if /darwin/ =~ RUBY_PLATFORM
98
-
161
+ dumped = false
99
162
  while signal = signals.shift
100
163
 
101
- if lldb and [:ABRT, :KILL].include?(signal)
102
- lldb = false
103
- # sudo -n: --non-interactive
104
- # lldb -p: attach
105
- # -o: run command
106
- system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit])
107
- true
164
+ if !dumped and [:ABRT, :KILL].include?(signal)
165
+ Debugger.search&.dump(pid)
166
+ dumped = true
108
167
  end
109
168
 
110
169
  begin
@@ -165,6 +224,10 @@ module EnvUtil
165
224
  }
166
225
 
167
226
  args = [args] if args.kind_of?(String)
227
+ # use the same parser as current ruby
228
+ if args.none? { |arg| arg.start_with?("--parser=") }
229
+ args = ["--parser=#{current_parser}"] + args
230
+ end
168
231
  pid = spawn(child_env, *precommand, rubybin, *args, opt)
169
232
  in_c.close
170
233
  out_c&.close
@@ -212,6 +275,12 @@ module EnvUtil
212
275
  end
213
276
  module_function :invoke_ruby
214
277
 
278
+ def current_parser
279
+ features = RUBY_DESCRIPTION[%r{\)\K [-+*/%._0-9a-zA-Z ]*(?=\[[-+*/%._0-9a-zA-Z]+\]\z)}]
280
+ features&.split&.include?("+PRISM") ? "prism" : "parse.y"
281
+ end
282
+ module_function :current_parser
283
+
215
284
  def verbose_warning
216
285
  class << (stderr = "".dup)
217
286
  alias write concat
@@ -228,6 +297,21 @@ module EnvUtil
228
297
  end
229
298
  module_function :verbose_warning
230
299
 
300
+ if defined?(Warning.[]=)
301
+ def deprecation_warning
302
+ previous_deprecated = Warning[:deprecated]
303
+ Warning[:deprecated] = true
304
+ yield
305
+ ensure
306
+ Warning[:deprecated] = previous_deprecated
307
+ end
308
+ else
309
+ def deprecation_warning
310
+ yield
311
+ end
312
+ end
313
+ module_function :deprecation_warning
314
+
231
315
  def default_warning
232
316
  $VERBOSE = false
233
317
  yield
@@ -254,11 +338,15 @@ module EnvUtil
254
338
 
255
339
  def under_gc_compact_stress(val = :empty, &block)
256
340
  raise "compaction doesn't work well on s390x. Omit the test in the caller." if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
257
- auto_compact = GC.auto_compact
258
- GC.auto_compact = val
341
+
342
+ if GC.respond_to?(:auto_compact)
343
+ auto_compact = GC.auto_compact
344
+ GC.auto_compact = val
345
+ end
346
+
259
347
  under_gc_stress(&block)
260
348
  ensure
261
- GC.auto_compact = auto_compact
349
+ GC.auto_compact = auto_compact if GC.respond_to?(:auto_compact)
262
350
  end
263
351
  module_function :under_gc_compact_stress
264
352
 
@@ -270,7 +358,8 @@ module EnvUtil
270
358
  end
271
359
  module_function :without_gc
272
360
 
273
- def with_default_external(enc)
361
+ def with_default_external(enc = nil, of: nil)
362
+ enc = of.encoding if defined?(of.encoding)
274
363
  suppress_warning { Encoding.default_external = enc }
275
364
  yield
276
365
  ensure
@@ -278,7 +367,8 @@ module EnvUtil
278
367
  end
279
368
  module_function :with_default_external
280
369
 
281
- def with_default_internal(enc)
370
+ def with_default_internal(enc = nil, of: nil)
371
+ enc = of.encoding if defined?(of.encoding)
282
372
  suppress_warning { Encoding.default_internal = enc }
283
373
  yield
284
374
  ensure
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+ begin
3
+ require '-test-/memory_status.so'
4
+ rescue LoadError
5
+ end
6
+
7
+ module Memory
8
+ keys = []
9
+
10
+ case
11
+ when File.exist?(procfile = "/proc/self/status") && (pat = /^Vm(\w+):\s+(\d+)/) =~ (data = File.binread(procfile))
12
+ PROC_FILE = procfile
13
+ VM_PAT = pat
14
+ def self.read_status
15
+ File.foreach(PROC_FILE, encoding: Encoding::ASCII_8BIT) do |l|
16
+ yield($1.downcase.intern, $2.to_i * 1024) if VM_PAT =~ l
17
+ end
18
+ end
19
+
20
+ data.scan(pat) {|k, v| keys << k.downcase.intern}
21
+
22
+ when /mswin|mingw/ =~ RUBY_PLATFORM
23
+ require 'fiddle/import'
24
+ require 'fiddle/types'
25
+
26
+ module Win32
27
+ extend Fiddle::Importer
28
+ dlload "kernel32.dll", "psapi.dll"
29
+ include Fiddle::Win32Types
30
+ typealias "SIZE_T", "size_t"
31
+
32
+ PROCESS_MEMORY_COUNTERS = struct [
33
+ "DWORD cb",
34
+ "DWORD PageFaultCount",
35
+ "SIZE_T PeakWorkingSetSize",
36
+ "SIZE_T WorkingSetSize",
37
+ "SIZE_T QuotaPeakPagedPoolUsage",
38
+ "SIZE_T QuotaPagedPoolUsage",
39
+ "SIZE_T QuotaPeakNonPagedPoolUsage",
40
+ "SIZE_T QuotaNonPagedPoolUsage",
41
+ "SIZE_T PagefileUsage",
42
+ "SIZE_T PeakPagefileUsage",
43
+ ]
44
+
45
+ typealias "PPROCESS_MEMORY_COUNTERS", "PROCESS_MEMORY_COUNTERS*"
46
+
47
+ extern "HANDLE GetCurrentProcess()", :stdcall
48
+ extern "BOOL GetProcessMemoryInfo(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD)", :stdcall
49
+
50
+ module_function
51
+ def memory_info
52
+ size = PROCESS_MEMORY_COUNTERS.size
53
+ data = PROCESS_MEMORY_COUNTERS.malloc
54
+ data.cb = size
55
+ data if GetProcessMemoryInfo(GetCurrentProcess(), data, size)
56
+ end
57
+ end
58
+
59
+ keys.push(:size, :rss, :peak)
60
+ def self.read_status
61
+ if info = Win32.memory_info
62
+ yield :size, info.PagefileUsage
63
+ yield :rss, info.WorkingSetSize
64
+ yield :peak, info.PeakWorkingSetSize
65
+ end
66
+ end
67
+ when (require_relative 'find_executable'
68
+ pat = /^\s*(\d+)\s+(\d+)$/
69
+ pscmd = EnvUtil.find_executable("ps", "-ovsz=", "-orss=", "-p", $$.to_s) {|out| pat =~ out})
70
+ pscmd.pop
71
+ PAT = pat
72
+ PSCMD = pscmd
73
+
74
+ keys << :size << :rss
75
+ def self.read_status
76
+ if PAT =~ IO.popen(PSCMD + [$$.to_s], "r", err: [:child, :out], &:read)
77
+ yield :size, $1.to_i*1024
78
+ yield :rss, $2.to_i*1024
79
+ end
80
+ end
81
+ else
82
+ def self.read_status
83
+ raise NotImplementedError, "unsupported platform"
84
+ end
85
+ end
86
+
87
+ if !keys.empty?
88
+ Status = Struct.new(*keys)
89
+ end
90
+ end unless defined?(Memory::Status)
91
+
92
+ if defined?(Memory::Status)
93
+ class Memory::Status
94
+ def _update
95
+ Memory.read_status do |key, val|
96
+ self[key] = val
97
+ end
98
+ self
99
+ end unless method_defined?(:_update)
100
+
101
+ Header = members.map {|k| k.to_s.upcase.rjust(6)}.join('')
102
+ Format = "%6d"
103
+
104
+ def initialize
105
+ _update
106
+ end
107
+
108
+ def to_s
109
+ status = each_pair.map {|n,v|
110
+ "#{n}:#{v}"
111
+ }
112
+ "{#{status.join(",")}}"
113
+ end
114
+
115
+ def self.parse(str)
116
+ status = allocate
117
+ str.scan(/(?:\A\{|\G,)(#{members.join('|')}):(\d+)(?=,|\}\z)/) do
118
+ status[$1] = $2.to_i
119
+ end
120
+ status
121
+ end
122
+ end
123
+
124
+ # On some platforms (e.g. Solaris), libc malloc does not return
125
+ # freed memory to OS because of efficiency, and linking with extra
126
+ # malloc library is needed to detect memory leaks.
127
+ #
128
+ case RUBY_PLATFORM
129
+ when /solaris2\.(?:9|[1-9][0-9])/i # Solaris 9, 10, 11,...
130
+ bits = [nil].pack('p').size == 8 ? 64 : 32
131
+ if ENV['LD_PRELOAD'].to_s.empty? &&
132
+ ENV["LD_PRELOAD_#{bits}"].to_s.empty? &&
133
+ (ENV['UMEM_OPTIONS'].to_s.empty? ||
134
+ ENV['UMEM_OPTIONS'] == 'backend=mmap') then
135
+ envs = {
136
+ 'LD_PRELOAD' => 'libumem.so',
137
+ 'UMEM_OPTIONS' => 'backend=mmap'
138
+ }
139
+ args = [
140
+ envs,
141
+ "--disable=gems",
142
+ "-v", "-",
143
+ ]
144
+ _, err, status = EnvUtil.invoke_ruby(args, "exit(0)", true, true)
145
+ if status.exitstatus == 0 && err.to_s.empty? then
146
+ Memory::NO_MEMORY_LEAK_ENVS = envs
147
+ end
148
+ end
149
+ end #case RUBY_PLATFORM
150
+
151
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-unit-ruby-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi SHIBATA
@@ -35,6 +35,7 @@ files:
35
35
  - lib/core_assertions.rb
36
36
  - lib/envutil.rb
37
37
  - lib/find_executable.rb
38
+ - lib/memory_status.rb
38
39
  homepage: https://github.com/ruby/test-unit-ruby-core
39
40
  licenses:
40
41
  - Ruby
@@ -56,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
57
  - !ruby/object:Gem::Version
57
58
  version: '0'
58
59
  requirements: []
59
- rubygems_version: 3.7.0.dev
60
+ rubygems_version: 3.8.0.dev
60
61
  specification_version: 4
61
62
  summary: Additional test assertions for Ruby standard libraries.
62
63
  test_files: []