Skip to content

Commit 0040d5d

Browse files
committed
Enabled tests used by test suite of ruby core
1 parent 1f4e47c commit 0040d5d

File tree

11 files changed

+4221
-3
lines changed

11 files changed

+4221
-3
lines changed

Rakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ require "bundler/gem_tasks"
22
require "rake/testtask"
33

44
Rake::TestTask.new(:test) do |t|
5-
t.libs << "test"
5+
t.libs << "test" << "test/lib"
66
t.libs << "lib"
7-
t.test_files = FileList['test/**/*_test.rb']
7+
t.test_files = FileList['test/**/test_*.rb']
88
end
99

1010
task :default => :test

cmath.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ Gem::Specification.new do |spec|
1919

2020
spec.add_development_dependency "bundler"
2121
spec.add_development_dependency "rake"
22-
spec.add_development_dependency "minitest"
2322
end

test/lib/envutil.rb

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
# -*- coding: us-ascii -*-
2+
# frozen_string_literal: false
3+
require "open3"
4+
require "timeout"
5+
require_relative "find_executable"
6+
begin
7+
require 'rbconfig'
8+
rescue LoadError
9+
end
10+
begin
11+
require "rbconfig/sizeof"
12+
rescue LoadError
13+
end
14+
15+
module EnvUtil
16+
def rubybin
17+
if ruby = ENV["RUBY"]
18+
return ruby
19+
end
20+
ruby = "ruby"
21+
exeext = RbConfig::CONFIG["EXEEXT"]
22+
rubyexe = (ruby + exeext if exeext and !exeext.empty?)
23+
3.times do
24+
if File.exist? ruby and File.executable? ruby and !File.directory? ruby
25+
return File.expand_path(ruby)
26+
end
27+
if rubyexe and File.exist? rubyexe and File.executable? rubyexe
28+
return File.expand_path(rubyexe)
29+
end
30+
ruby = File.join("..", ruby)
31+
end
32+
if defined?(RbConfig.ruby)
33+
RbConfig.ruby
34+
else
35+
"ruby"
36+
end
37+
end
38+
module_function :rubybin
39+
40+
LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
41+
42+
DEFAULT_SIGNALS = Signal.list
43+
DEFAULT_SIGNALS.delete("TERM") if /mswin|mingw/ =~ RUBY_PLATFORM
44+
45+
class << self
46+
attr_accessor :subprocess_timeout_scale
47+
end
48+
49+
def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false,
50+
encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error,
51+
stdout_filter: nil, stderr_filter: nil,
52+
signal: :TERM,
53+
rubybin: EnvUtil.rubybin,
54+
**opt)
55+
if scale = EnvUtil.subprocess_timeout_scale
56+
timeout *= scale if timeout
57+
reprieve *= scale if reprieve
58+
end
59+
in_c, in_p = IO.pipe
60+
out_p, out_c = IO.pipe if capture_stdout
61+
err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout
62+
opt[:in] = in_c
63+
opt[:out] = out_c if capture_stdout
64+
opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr
65+
if encoding
66+
out_p.set_encoding(encoding) if out_p
67+
err_p.set_encoding(encoding) if err_p
68+
end
69+
c = "C"
70+
child_env = {}
71+
LANG_ENVS.each {|lc| child_env[lc] = c}
72+
if Array === args and Hash === args.first
73+
child_env.update(args.shift)
74+
end
75+
args = [args] if args.kind_of?(String)
76+
pid = spawn(child_env, rubybin, *args, **opt)
77+
in_c.close
78+
out_c.close if capture_stdout
79+
err_c.close if capture_stderr && capture_stderr != :merge_to_stdout
80+
if block_given?
81+
return yield in_p, out_p, err_p, pid
82+
else
83+
th_stdout = Thread.new { out_p.read } if capture_stdout
84+
th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout
85+
in_p.write stdin_data.to_str unless stdin_data.empty?
86+
in_p.close
87+
if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout))
88+
timeout_error = nil
89+
else
90+
signals = Array(signal).select do |sig|
91+
DEFAULT_SIGNALS[sig.to_s] or
92+
DEFAULT_SIGNALS[Signal.signame(sig)] rescue false
93+
end
94+
signals |= [:ABRT, :KILL]
95+
case pgroup = opt[:pgroup]
96+
when 0, true
97+
pgroup = -pid
98+
when nil, false
99+
pgroup = pid
100+
end
101+
while signal = signals.shift
102+
begin
103+
Process.kill signal, pgroup
104+
rescue Errno::EINVAL
105+
next
106+
rescue Errno::ESRCH
107+
break
108+
end
109+
if signals.empty? or !reprieve
110+
Process.wait(pid)
111+
else
112+
begin
113+
Timeout.timeout(reprieve) {Process.wait(pid)}
114+
rescue Timeout::Error
115+
end
116+
end
117+
end
118+
status = $?
119+
end
120+
stdout = th_stdout.value if capture_stdout
121+
stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout
122+
out_p.close if capture_stdout
123+
err_p.close if capture_stderr && capture_stderr != :merge_to_stdout
124+
status ||= Process.wait2(pid)[1]
125+
stdout = stdout_filter.call(stdout) if stdout_filter
126+
stderr = stderr_filter.call(stderr) if stderr_filter
127+
if timeout_error
128+
bt = caller_locations
129+
msg = "execution of #{bt.shift.label} expired"
130+
msg = Test::Unit::Assertions::FailDesc[status, msg, [stdout, stderr].join("\n")].()
131+
raise timeout_error, msg, bt.map(&:to_s)
132+
end
133+
return stdout, stderr, status
134+
end
135+
ensure
136+
[th_stdout, th_stderr].each do |th|
137+
th.kill if th
138+
end
139+
[in_c, in_p, out_c, out_p, err_c, err_p].each do |io|
140+
io&.close
141+
end
142+
[th_stdout, th_stderr].each do |th|
143+
th.join if th
144+
end
145+
end
146+
module_function :invoke_ruby
147+
148+
alias rubyexec invoke_ruby
149+
class << self
150+
alias rubyexec invoke_ruby
151+
end
152+
153+
def verbose_warning
154+
class << (stderr = "")
155+
alias write <<
156+
end
157+
stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
158+
yield stderr
159+
return $stderr
160+
ensure
161+
stderr, $stderr, $VERBOSE = $stderr, stderr, verbose
162+
end
163+
module_function :verbose_warning
164+
165+
def default_warning
166+
verbose, $VERBOSE = $VERBOSE, false
167+
yield
168+
ensure
169+
$VERBOSE = verbose
170+
end
171+
module_function :default_warning
172+
173+
def suppress_warning
174+
verbose, $VERBOSE = $VERBOSE, nil
175+
yield
176+
ensure
177+
$VERBOSE = verbose
178+
end
179+
module_function :suppress_warning
180+
181+
def under_gc_stress(stress = true)
182+
stress, GC.stress = GC.stress, stress
183+
yield
184+
ensure
185+
GC.stress = stress
186+
end
187+
module_function :under_gc_stress
188+
189+
def with_default_external(enc)
190+
verbose, $VERBOSE = $VERBOSE, nil
191+
origenc, Encoding.default_external = Encoding.default_external, enc
192+
$VERBOSE = verbose
193+
yield
194+
ensure
195+
verbose, $VERBOSE = $VERBOSE, nil
196+
Encoding.default_external = origenc
197+
$VERBOSE = verbose
198+
end
199+
module_function :with_default_external
200+
201+
def with_default_internal(enc)
202+
verbose, $VERBOSE = $VERBOSE, nil
203+
origenc, Encoding.default_internal = Encoding.default_internal, enc
204+
$VERBOSE = verbose
205+
yield
206+
ensure
207+
verbose, $VERBOSE = $VERBOSE, nil
208+
Encoding.default_internal = origenc
209+
$VERBOSE = verbose
210+
end
211+
module_function :with_default_internal
212+
213+
def labeled_module(name, &block)
214+
Module.new do
215+
singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s}
216+
class_eval(&block) if block
217+
end
218+
end
219+
module_function :labeled_module
220+
221+
def labeled_class(name, superclass = Object, &block)
222+
Class.new(superclass) do
223+
singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s}
224+
class_eval(&block) if block
225+
end
226+
end
227+
module_function :labeled_class
228+
229+
if /darwin/ =~ RUBY_PLATFORM
230+
DIAGNOSTIC_REPORTS_PATH = File.expand_path("~/Library/Logs/DiagnosticReports")
231+
DIAGNOSTIC_REPORTS_TIMEFORMAT = '%Y-%m-%d-%H%M%S'
232+
@ruby_install_name = RbConfig::CONFIG['RUBY_INSTALL_NAME']
233+
234+
def self.diagnostic_reports(signame, pid, now)
235+
return unless %w[ABRT QUIT SEGV ILL TRAP].include?(signame)
236+
cmd = File.basename(rubybin)
237+
cmd = @ruby_install_name if "ruby-runner#{RbConfig::CONFIG["EXEEXT"]}" == cmd
238+
path = DIAGNOSTIC_REPORTS_PATH
239+
timeformat = DIAGNOSTIC_REPORTS_TIMEFORMAT
240+
pat = "#{path}/#{cmd}_#{now.strftime(timeformat)}[-_]*.crash"
241+
first = true
242+
30.times do
243+
first ? (first = false) : sleep(0.1)
244+
Dir.glob(pat) do |name|
245+
log = File.read(name) rescue next
246+
if /\AProcess:\s+#{cmd} \[#{pid}\]$/ =~ log
247+
File.unlink(name)
248+
File.unlink("#{path}/.#{File.basename(name)}.plist") rescue nil
249+
return log
250+
end
251+
end
252+
end
253+
nil
254+
end
255+
else
256+
def self.diagnostic_reports(signame, pid, now)
257+
end
258+
end
259+
260+
def self.gc_stress_to_class?
261+
unless defined?(@gc_stress_to_class)
262+
_, _, status = invoke_ruby(["-e""exit GC.respond_to?(:add_stress_to_class)"])
263+
@gc_stress_to_class = status.success?
264+
end
265+
@gc_stress_to_class
266+
end
267+
end
268+
269+
if defined?(RbConfig)
270+
module RbConfig
271+
@ruby = EnvUtil.rubybin
272+
class << self
273+
undef ruby if method_defined?(:ruby)
274+
attr_reader :ruby
275+
end
276+
dir = File.dirname(ruby)
277+
name = File.basename(ruby, CONFIG['EXEEXT'])
278+
CONFIG['bindir'] = dir
279+
CONFIG['ruby_install_name'] = name
280+
CONFIG['RUBY_INSTALL_NAME'] = name
281+
Gem::ConfigMap[:bindir] = dir if defined?(Gem::ConfigMap)
282+
end
283+
end

test/lib/find_executable.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: false
2+
require "rbconfig"
3+
4+
module EnvUtil
5+
def find_executable(cmd, *args)
6+
exts = RbConfig::CONFIG["EXECUTABLE_EXTS"].split | [RbConfig::CONFIG["EXEEXT"]]
7+
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
8+
next if path.empty?
9+
path = File.join(path, cmd)
10+
exts.each do |ext|
11+
cmdline = [path + ext, *args]
12+
begin
13+
return cmdline if yield(IO.popen(cmdline, "r", err: [:child, :out], &:read))
14+
rescue
15+
next
16+
end
17+
end
18+
end
19+
nil
20+
end
21+
module_function :find_executable
22+
end

0 commit comments

Comments
 (0)