2008-04-23 11:22:13 -04:00
|
|
|
require "open3"
|
|
|
|
require "timeout"
|
|
|
|
|
2003-10-04 22:56:42 -04:00
|
|
|
module EnvUtil
|
|
|
|
def rubybin
|
2006-02-03 04:15:42 -05:00
|
|
|
unless ENV["RUBYOPT"]
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2006-02-03 04:15:42 -05:00
|
|
|
end
|
2004-05-19 10:45:49 -04:00
|
|
|
if ruby = ENV["RUBY"]
|
|
|
|
return ruby
|
|
|
|
end
|
2005-12-29 03:05:26 -05:00
|
|
|
ruby = "ruby"
|
2006-02-03 04:15:42 -05:00
|
|
|
rubyexe = ruby+".exe"
|
2003-10-13 09:05:24 -04:00
|
|
|
3.times do
|
2006-02-03 04:15:42 -05:00
|
|
|
if File.exist? ruby and File.executable? ruby and !File.directory? ruby
|
|
|
|
return File.expand_path(ruby)
|
|
|
|
end
|
|
|
|
if File.exist? rubyexe and File.executable? rubyexe
|
2008-05-12 08:35:37 -04:00
|
|
|
return File.expand_path(rubyexe)
|
2003-10-13 09:05:24 -04:00
|
|
|
end
|
2005-12-29 03:05:26 -05:00
|
|
|
ruby = File.join("..", ruby)
|
2003-10-13 10:59:25 -04:00
|
|
|
end
|
2010-01-12 02:41:40 -05:00
|
|
|
if defined?(RbConfig.ruby)
|
2009-12-31 10:00:04 -05:00
|
|
|
RbConfig.ruby
|
2010-01-12 02:41:40 -05:00
|
|
|
else
|
2003-10-13 10:59:25 -04:00
|
|
|
"ruby"
|
2003-10-04 22:56:42 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
module_function :rubybin
|
2008-04-23 11:22:13 -04:00
|
|
|
|
|
|
|
LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
|
2009-11-19 17:47:53 -05:00
|
|
|
|
2008-04-23 11:22:13 -04:00
|
|
|
def rubyexec(*args)
|
|
|
|
ruby = EnvUtil.rubybin
|
|
|
|
c = "C"
|
|
|
|
env = {}
|
|
|
|
LANG_ENVS.each {|lc| env[lc], ENV[lc] = ENV[lc], c}
|
2008-04-24 10:02:15 -04:00
|
|
|
stdin = stdout = stderr = nil
|
2008-04-23 11:22:13 -04:00
|
|
|
Timeout.timeout(10) do
|
2008-04-24 10:02:15 -04:00
|
|
|
stdin, stdout, stderr = Open3.popen3(*([ruby] + args))
|
|
|
|
env.each_pair {|lc, v|
|
|
|
|
if v
|
|
|
|
ENV[lc] = v
|
|
|
|
else
|
|
|
|
ENV.delete(lc)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
env = nil
|
2008-04-23 11:22:13 -04:00
|
|
|
yield(stdin, stdout, stderr)
|
|
|
|
end
|
|
|
|
|
|
|
|
ensure
|
|
|
|
env.each_pair {|lc, v|
|
|
|
|
if v
|
|
|
|
ENV[lc] = v
|
|
|
|
else
|
|
|
|
ENV.delete(lc)
|
|
|
|
end
|
|
|
|
} if env
|
|
|
|
stdin .close unless !stdin || stdin .closed?
|
|
|
|
stdout.close unless !stdout || stdout.closed?
|
|
|
|
stderr.close unless !stderr || stderr.closed?
|
|
|
|
end
|
|
|
|
module_function :rubyexec
|
2009-09-29 02:26:46 -04:00
|
|
|
|
2009-11-19 17:47:53 -05:00
|
|
|
def invoke_ruby(args, stdin_data="", capture_stdout=false, capture_stderr=false, opt={})
|
2010-06-05 09:47:09 -04:00
|
|
|
args = [args] if args.kind_of?(String)
|
2009-11-19 17:47:53 -05:00
|
|
|
begin
|
|
|
|
in_c, in_p = IO.pipe
|
|
|
|
out_p, out_c = IO.pipe if capture_stdout
|
|
|
|
err_p, err_c = IO.pipe if capture_stderr
|
|
|
|
opt = opt.dup
|
|
|
|
opt[:in] = in_c
|
|
|
|
opt[:out] = out_c if capture_stdout
|
|
|
|
opt[:err] = err_c if capture_stderr
|
2010-06-22 23:44:55 -04:00
|
|
|
if enc = opt.delete(:encoding)
|
|
|
|
out_p.set_encoding(enc) if out_p
|
|
|
|
err_p.set_encoding(enc) if err_p
|
|
|
|
end
|
2010-06-24 20:58:57 -04:00
|
|
|
c = "C"
|
|
|
|
child_env = ENV.dup
|
|
|
|
LANG_ENVS.each {|lc| child_env[lc] = c}
|
2010-06-05 02:15:55 -04:00
|
|
|
case args.first
|
|
|
|
when Hash
|
2010-06-24 20:58:57 -04:00
|
|
|
child_env.update(args.shift)
|
2010-06-05 02:15:55 -04:00
|
|
|
end
|
2010-06-24 20:58:57 -04:00
|
|
|
pid = spawn(child_env, EnvUtil.rubybin, *args, opt)
|
2009-11-19 17:47:53 -05:00
|
|
|
in_c.close
|
|
|
|
out_c.close if capture_stdout
|
|
|
|
err_c.close if capture_stderr
|
|
|
|
th_stdout = Thread.new { out_p.read } if capture_stdout
|
|
|
|
th_stderr = Thread.new { err_p.read } if capture_stderr
|
2010-06-24 20:57:03 -04:00
|
|
|
in_p.write stdin_data.to_str
|
|
|
|
in_p.close
|
2009-11-19 17:47:53 -05:00
|
|
|
if (!capture_stdout || th_stdout.join(10)) && (!capture_stderr || th_stderr.join(10))
|
|
|
|
stdout = th_stdout.value if capture_stdout
|
|
|
|
stderr = th_stderr.value if capture_stderr
|
|
|
|
else
|
2009-11-24 08:59:10 -05:00
|
|
|
raise Timeout::Error
|
2009-11-19 17:47:53 -05:00
|
|
|
end
|
|
|
|
out_p.close if capture_stdout
|
|
|
|
err_p.close if capture_stderr
|
|
|
|
Process.wait pid
|
|
|
|
status = $?
|
|
|
|
ensure
|
|
|
|
in_c.close if in_c && !in_c.closed?
|
|
|
|
in_p.close if in_p && !in_p.closed?
|
|
|
|
out_c.close if out_c && !out_c.closed?
|
|
|
|
out_p.close if out_p && !out_p.closed?
|
|
|
|
err_c.close if err_c && !err_c.closed?
|
|
|
|
err_p.close if err_p && !err_p.closed?
|
|
|
|
(th_stdout.kill; th_stdout.join) if th_stdout
|
|
|
|
(th_stderr.kill; th_stderr.join) if th_stderr
|
|
|
|
end
|
|
|
|
return stdout, stderr, status
|
|
|
|
end
|
|
|
|
module_function :invoke_ruby
|
2009-09-29 02:26:46 -04:00
|
|
|
|
|
|
|
def verbose_warning
|
|
|
|
class << (stderr = "")
|
|
|
|
alias write <<
|
|
|
|
end
|
|
|
|
stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
|
|
|
|
yield stderr
|
|
|
|
ensure
|
|
|
|
stderr, $stderr, $VERBOSE = $stderr, stderr, verbose
|
|
|
|
return stderr
|
|
|
|
end
|
|
|
|
module_function :verbose_warning
|
2010-06-05 21:44:38 -04:00
|
|
|
|
|
|
|
def under_gc_stress
|
|
|
|
stress, GC.stress = GC.stress, true
|
|
|
|
yield
|
|
|
|
ensure
|
|
|
|
GC.stress = stress
|
|
|
|
end
|
|
|
|
module_function :under_gc_stress
|
2003-10-04 22:56:42 -04:00
|
|
|
end
|
2008-05-03 07:57:55 -04:00
|
|
|
|
|
|
|
module Test
|
|
|
|
module Unit
|
|
|
|
module Assertions
|
|
|
|
public
|
|
|
|
def assert_normal_exit(testsrc, message = '')
|
2008-05-21 22:40:50 -04:00
|
|
|
in_c, in_p = IO.pipe
|
|
|
|
out_p, out_c = IO.pipe
|
|
|
|
pid = spawn(EnvUtil.rubybin, '-W0', STDIN=>in_c, STDOUT=>out_c, STDERR=>out_c)
|
|
|
|
in_c.close
|
|
|
|
out_c.close
|
2008-07-10 06:45:51 -04:00
|
|
|
in_p.write testsrc
|
|
|
|
in_p.close
|
2008-05-21 22:40:50 -04:00
|
|
|
msg = out_p.read
|
|
|
|
out_p.close
|
|
|
|
Process.wait pid
|
2008-05-03 07:57:55 -04:00
|
|
|
status = $?
|
|
|
|
faildesc = nil
|
|
|
|
if status.signaled?
|
|
|
|
signo = status.termsig
|
|
|
|
signame = Signal.list.invert[signo]
|
|
|
|
sigdesc = "signal #{signo}"
|
|
|
|
if signame
|
|
|
|
sigdesc = "SIG#{signame} (#{sigdesc})"
|
|
|
|
end
|
2008-05-31 21:32:54 -04:00
|
|
|
if status.coredump?
|
|
|
|
sigdesc << " (core dumped)"
|
|
|
|
end
|
2009-09-10 08:21:48 -04:00
|
|
|
full_message = ''
|
|
|
|
if !message.empty?
|
|
|
|
full_message << message << "\n"
|
|
|
|
end
|
2008-05-21 22:40:50 -04:00
|
|
|
if msg.empty?
|
2009-09-10 08:21:48 -04:00
|
|
|
full_message << "pid #{pid} killed by #{sigdesc}"
|
2008-05-21 22:40:50 -04:00
|
|
|
else
|
|
|
|
msg << "\n" if /\n\z/ !~ msg
|
2009-09-10 08:21:48 -04:00
|
|
|
full_message << "pid #{pid} killed by #{sigdesc}\n#{msg.gsub(/^/, '| ')}"
|
2008-05-21 22:40:50 -04:00
|
|
|
end
|
2008-05-03 07:57:55 -04:00
|
|
|
end
|
|
|
|
assert_block(full_message) { !status.signaled? }
|
2008-05-21 22:40:50 -04:00
|
|
|
ensure
|
|
|
|
in_c.close if in_c && !in_c.closed?
|
|
|
|
in_p.close if in_p && !in_p.closed?
|
|
|
|
out_c.close if out_c && !out_c.closed?
|
|
|
|
out_p.close if out_p && !out_p.closed?
|
2008-05-03 07:57:55 -04:00
|
|
|
end
|
2008-07-15 11:26:04 -04:00
|
|
|
|
2009-11-16 08:45:59 -05:00
|
|
|
def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, opt={})
|
2009-11-19 17:47:53 -05:00
|
|
|
stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, opt)
|
2009-11-16 08:45:59 -05:00
|
|
|
if block_given?
|
|
|
|
yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp })
|
|
|
|
else
|
|
|
|
if test_stdout.is_a?(Regexp)
|
|
|
|
assert_match(test_stdout, stdout, message)
|
|
|
|
else
|
|
|
|
assert_equal(test_stdout, stdout.lines.map {|l| l.chomp }, message)
|
|
|
|
end
|
|
|
|
if test_stderr.is_a?(Regexp)
|
|
|
|
assert_match(test_stderr, stderr, message)
|
|
|
|
else
|
|
|
|
assert_equal(test_stderr, stderr.lines.map {|l| l.chomp }, message)
|
|
|
|
end
|
|
|
|
end
|
2009-11-15 12:11:54 -05:00
|
|
|
end
|
|
|
|
|
2009-11-17 08:24:44 -05:00
|
|
|
def assert_ruby_status(args, test_stdin="", message=nil, opt={})
|
2009-11-19 17:47:53 -05:00
|
|
|
stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, false, false, opt)
|
2009-12-16 06:29:54 -05:00
|
|
|
m = message ? "#{message} (#{status.inspect})" : "ruby exit status is not success: #{status.inspect}"
|
2009-11-16 08:45:59 -05:00
|
|
|
assert(status.success?, m)
|
2009-11-15 11:24:45 -05:00
|
|
|
end
|
2009-11-15 12:11:54 -05:00
|
|
|
|
2008-05-03 07:57:55 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-01-12 02:41:40 -05:00
|
|
|
begin
|
|
|
|
require 'rbconfig'
|
|
|
|
rescue LoadError
|
|
|
|
else
|
|
|
|
module RbConfig
|
|
|
|
@ruby = EnvUtil.rubybin
|
|
|
|
class << self
|
2010-01-25 08:33:02 -05:00
|
|
|
undef ruby if method_defined?(:ruby)
|
2010-01-12 02:41:40 -05:00
|
|
|
attr_reader :ruby
|
|
|
|
end
|
|
|
|
dir = File.dirname(ruby)
|
|
|
|
name = File.basename(ruby, CONFIG['EXEEXT'])
|
|
|
|
CONFIG['bindir'] = dir
|
|
|
|
CONFIG['ruby_install_name'] = name
|
|
|
|
CONFIG['RUBY_INSTALL_NAME'] = name
|
2010-05-28 20:34:35 -04:00
|
|
|
Gem::ConfigMap[:bindir] = dir if defined?(Gem)
|
2010-01-12 02:41:40 -05:00
|
|
|
end
|
|
|
|
end
|