зеркало из https://github.com/github/ruby.git
Update to ruby/mspec@dc2eb26
This commit is contained in:
Родитель
f38c6552f9
Коммит
de60139053
|
@ -140,28 +140,44 @@ def ruby_exe(code = :not_given, opts = {})
|
||||||
expected_status = opts.fetch(:exit_status, 0)
|
expected_status = opts.fetch(:exit_status, 0)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
platform_is_not :opal do
|
command = ruby_cmd(code, opts)
|
||||||
command = ruby_cmd(code, opts)
|
|
||||||
output = `#{command}`
|
|
||||||
status = Process.last_status
|
|
||||||
|
|
||||||
exit_status = if status.exited?
|
# Try to avoid the extra shell for 2>&1
|
||||||
status.exitstatus
|
# This is notably useful for TimeoutAction which can then signal the ruby subprocess and not the shell
|
||||||
elsif status.signaled?
|
popen_options = []
|
||||||
signame = Signal.signame status.termsig
|
if command.end_with?(' 2>&1')
|
||||||
raise "No signal name?" unless signame
|
command = command[0...-5]
|
||||||
:"SIG#{signame}"
|
popen_options = [{ err: [:child, :out] }]
|
||||||
else
|
|
||||||
raise SpecExpectationNotMetError, "#{exit_status.inspect} is neither exited? nor signaled?"
|
|
||||||
end
|
|
||||||
if exit_status != expected_status
|
|
||||||
formatted_output = output.lines.map { |line| " #{line}" }.join
|
|
||||||
raise SpecExpectationNotMetError,
|
|
||||||
"Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}"
|
|
||||||
end
|
|
||||||
|
|
||||||
output
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
output = IO.popen(command, *popen_options) do |io|
|
||||||
|
pid = io.pid
|
||||||
|
MSpec.subprocesses << pid
|
||||||
|
begin
|
||||||
|
io.read
|
||||||
|
ensure
|
||||||
|
MSpec.subprocesses.delete(pid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
status = Process.last_status
|
||||||
|
|
||||||
|
exit_status = if status.exited?
|
||||||
|
status.exitstatus
|
||||||
|
elsif status.signaled?
|
||||||
|
signame = Signal.signame status.termsig
|
||||||
|
raise "No signal name?" unless signame
|
||||||
|
:"SIG#{signame}"
|
||||||
|
else
|
||||||
|
raise SpecExpectationNotMetError, "#{exit_status.inspect} is neither exited? nor signaled?"
|
||||||
|
end
|
||||||
|
if exit_status != expected_status
|
||||||
|
formatted_output = output.lines.map { |line| " #{line}" }.join
|
||||||
|
raise SpecExpectationNotMetError,
|
||||||
|
"Expected exit status is #{expected_status.inspect} but actual is #{exit_status.inspect} for command ruby_exe(#{command.inspect})\nOutput:\n#{formatted_output}"
|
||||||
|
end
|
||||||
|
|
||||||
|
output
|
||||||
ensure
|
ensure
|
||||||
saved_env.each { |key, value| ENV[key] = value }
|
saved_env.each { |key, value| ENV[key] = value }
|
||||||
env.keys.each do |key|
|
env.keys.each do |key|
|
||||||
|
|
|
@ -3,6 +3,8 @@ class TimeoutAction
|
||||||
@timeout = timeout
|
@timeout = timeout
|
||||||
@queue = Queue.new
|
@queue = Queue.new
|
||||||
@started = now
|
@started = now
|
||||||
|
@fail = false
|
||||||
|
@error_message = "took longer than the configured timeout of #{@timeout}s"
|
||||||
end
|
end
|
||||||
|
|
||||||
def register
|
def register
|
||||||
|
@ -37,15 +39,25 @@ class TimeoutAction
|
||||||
elapsed = now - @started
|
elapsed = now - @started
|
||||||
if elapsed > @timeout
|
if elapsed > @timeout
|
||||||
if @current_state
|
if @current_state
|
||||||
STDERR.puts "\nExample took longer than the configured timeout of #{@timeout}s:"
|
STDERR.puts "\nExample #{@error_message}:"
|
||||||
STDERR.puts "#{@current_state.description}"
|
STDERR.puts "#{@current_state.description}"
|
||||||
else
|
else
|
||||||
STDERR.puts "\nSome code outside an example took longer than the configured timeout of #{@timeout}s"
|
STDERR.puts "\nSome code outside an example #{@error_message}"
|
||||||
end
|
end
|
||||||
STDERR.flush
|
STDERR.flush
|
||||||
|
|
||||||
show_backtraces
|
show_backtraces
|
||||||
exit 2
|
if MSpec.subprocesses.empty?
|
||||||
|
exit 2
|
||||||
|
else
|
||||||
|
# Do not exit but signal the subprocess so we can get their output
|
||||||
|
MSpec.subprocesses.each do |pid|
|
||||||
|
Process.kill :SIGTERM, pid
|
||||||
|
end
|
||||||
|
@fail = true
|
||||||
|
@current_state = nil
|
||||||
|
break # stop this thread, will fail in #after
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -65,6 +77,11 @@ class TimeoutAction
|
||||||
@queue << -> do
|
@queue << -> do
|
||||||
@current_state = nil
|
@current_state = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @fail
|
||||||
|
STDERR.puts "\n\nThe last example #{@error_message}. See above for the subprocess stacktrace."
|
||||||
|
exit 2
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish
|
def finish
|
||||||
|
@ -73,19 +90,38 @@ class TimeoutAction
|
||||||
end
|
end
|
||||||
|
|
||||||
private def show_backtraces
|
private def show_backtraces
|
||||||
if RUBY_ENGINE == 'truffleruby'
|
java_stacktraces = -> pid {
|
||||||
STDERR.puts 'Java stacktraces:'
|
if RUBY_ENGINE == 'truffleruby' || RUBY_ENGINE == 'jruby'
|
||||||
Process.kill :SIGQUIT, Process.pid
|
STDERR.puts 'Java stacktraces:'
|
||||||
sleep 1
|
Process.kill :SIGQUIT, pid
|
||||||
end
|
sleep 1
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
STDERR.puts "\nRuby backtraces:"
|
if MSpec.subprocesses.empty?
|
||||||
if defined?(Truffle::Debug.show_backtraces)
|
java_stacktraces.call Process.pid
|
||||||
Truffle::Debug.show_backtraces
|
|
||||||
|
STDERR.puts "\nRuby backtraces:"
|
||||||
|
if defined?(Truffle::Debug.show_backtraces)
|
||||||
|
Truffle::Debug.show_backtraces
|
||||||
|
else
|
||||||
|
Thread.list.each do |thread|
|
||||||
|
unless thread == Thread.current
|
||||||
|
STDERR.puts thread.inspect, thread.backtrace, ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Thread.list.each do |thread|
|
MSpec.subprocesses.each do |pid|
|
||||||
unless thread == Thread.current
|
STDERR.puts "\nFor subprocess #{pid}"
|
||||||
STDERR.puts thread.inspect, thread.backtrace, ''
|
java_stacktraces.call pid
|
||||||
|
|
||||||
|
if RUBY_ENGINE == 'truffleruby'
|
||||||
|
STDERR.puts "\nRuby backtraces:"
|
||||||
|
Process.kill :SIGALRM, pid
|
||||||
|
sleep 1
|
||||||
|
else
|
||||||
|
STDERR.puts "Don't know how to print backtraces of a subprocess on #{RUBY_ENGINE}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,9 +38,10 @@ module MSpec
|
||||||
@expectation = nil
|
@expectation = nil
|
||||||
@expectations = false
|
@expectations = false
|
||||||
@skips = []
|
@skips = []
|
||||||
|
@subprocesses = []
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
attr_reader :file, :include, :exclude, :skips
|
attr_reader :file, :include, :exclude, :skips, :subprocesses
|
||||||
attr_writer :repeat, :randomize
|
attr_writer :repeat, :randomize
|
||||||
attr_accessor :formatter
|
attr_accessor :formatter
|
||||||
end
|
end
|
||||||
|
|
|
@ -145,7 +145,7 @@ RSpec.describe Object, "#ruby_exe" do
|
||||||
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
|
stub_const 'RUBY_EXE', 'ruby_spec_exe -w -Q'
|
||||||
|
|
||||||
@script = RubyExeSpecs.new
|
@script = RubyExeSpecs.new
|
||||||
allow(@script).to receive(:`).and_return('OUTPUT')
|
allow(IO).to receive(:popen).and_return('OUTPUT')
|
||||||
|
|
||||||
status_successful = double(Process::Status, exited?: true, exitstatus: 0)
|
status_successful = double(Process::Status, exited?: true, exitstatus: 0)
|
||||||
allow(Process).to receive(:last_status).and_return(status_successful)
|
allow(Process).to receive(:last_status).and_return(status_successful)
|
||||||
|
@ -155,7 +155,7 @@ RSpec.describe Object, "#ruby_exe" do
|
||||||
code = "code"
|
code = "code"
|
||||||
options = {}
|
options = {}
|
||||||
output = "output"
|
output = "output"
|
||||||
allow(@script).to receive(:`).and_return(output)
|
expect(IO).to receive(:popen).and_return(output)
|
||||||
|
|
||||||
expect(@script.ruby_exe(code, options)).to eq output
|
expect(@script.ruby_exe(code, options)).to eq output
|
||||||
end
|
end
|
||||||
|
@ -168,7 +168,7 @@ RSpec.describe Object, "#ruby_exe" do
|
||||||
code = "code"
|
code = "code"
|
||||||
options = {}
|
options = {}
|
||||||
expect(@script).to receive(:ruby_cmd).and_return("ruby_cmd")
|
expect(@script).to receive(:ruby_cmd).and_return("ruby_cmd")
|
||||||
expect(@script).to receive(:`).with("ruby_cmd")
|
expect(IO).to receive(:popen).with("ruby_cmd")
|
||||||
@script.ruby_exe(code, options)
|
@script.ruby_exe(code, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ RSpec.describe Object, "#ruby_exe" do
|
||||||
expect(ENV).to receive(:[]=).with("ABC", "xyz")
|
expect(ENV).to receive(:[]=).with("ABC", "xyz")
|
||||||
expect(ENV).to receive(:[]=).with("ABC", "123")
|
expect(ENV).to receive(:[]=).with("ABC", "123")
|
||||||
|
|
||||||
expect(@script).to receive(:`).and_raise(Exception)
|
expect(IO).to receive(:popen).and_raise(Exception)
|
||||||
expect do
|
expect do
|
||||||
@script.ruby_exe nil, :env => { :ABC => "xyz" }
|
@script.ruby_exe nil, :env => { :ABC => "xyz" }
|
||||||
end.to raise_error(Exception)
|
end.to raise_error(Exception)
|
||||||
|
@ -248,7 +248,7 @@ RSpec.describe Object, "#ruby_exe" do
|
||||||
|
|
||||||
it "does not raise exception when command ends with expected status" do
|
it "does not raise exception when command ends with expected status" do
|
||||||
output = "output"
|
output = "output"
|
||||||
allow(@script).to receive(:`).and_return(output)
|
expect(IO).to receive(:popen).and_return(output)
|
||||||
|
|
||||||
expect(@script.ruby_exe("path", exit_status: 4)).to eq output
|
expect(@script.ruby_exe("path", exit_status: 4)).to eq output
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# This script is used to check that each *_spec.rb file has
|
||||||
|
# a relative_require for spec_helper which should live higher
|
||||||
|
# up in the ruby/spec repo directory tree.
|
||||||
|
#
|
||||||
|
# Prints errors to $stderr and returns a non-zero exit code when
|
||||||
|
# errors are found.
|
||||||
|
#
|
||||||
|
# Related to https://github.com/ruby/spec/pull/992
|
||||||
|
|
||||||
|
def check_file(fn)
|
||||||
|
File.foreach(fn) do |line|
|
||||||
|
return $1 if line =~ /^\s*require_relative\s*['"](.*spec_helper)['"]/
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
rootdir = ARGV[0] || "."
|
||||||
|
fglob = File.join(rootdir, "**", "*_spec.rb")
|
||||||
|
specfiles = Dir.glob(fglob)
|
||||||
|
raise "No spec files found in #{fglob.inspect}. Give an argument to specify the root-directory of ruby/spec" if specfiles.empty?
|
||||||
|
|
||||||
|
errors = 0
|
||||||
|
specfiles.sort.each do |fn|
|
||||||
|
result = check_file(fn)
|
||||||
|
if result.nil?
|
||||||
|
warn "Missing require_relative for *spec_helper for file: #{fn}"
|
||||||
|
errors += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "# Found #{errors} files with require_relative spec_helper issues."
|
||||||
|
exit 1 if errors > 0
|
Загрузка…
Ссылка в новой задаче