diff options
Diffstat (limited to 'bootstraptest/runner.rb')
-rwxr-xr-x | bootstraptest/runner.rb | 842 |
1 files changed, 546 insertions, 296 deletions
diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb index 11d5a6c17e..20f121cdf4 100755 --- a/bootstraptest/runner.rb +++ b/bootstraptest/runner.rb @@ -6,7 +6,8 @@ # Never use optparse in this file. # Never use test/unit in this file. # Never use Ruby extensions in this file. -# Maintain Ruby 1.8 compatibility for now + +$start_time = Time.now begin require 'fileutils' @@ -58,24 +59,114 @@ if !Dir.respond_to?(:mktmpdir) end end +# Configuration +bt = Struct.new(:ruby, + :verbose, + :color, + :tty, + :quiet, + :wn, + :progress, + :progress_bs, + :passed, + :failed, + :reset, + :columns, + :window_width, + :width, + :indent, + :platform, + ) +BT = Class.new(bt) do + def indent=(n) + super + if (self.columns ||= 0) < n + $stderr.print(' ' * (n - self.columns)) + end + self.columns = indent + end + + def putc(c) + unless self.quiet + if self.window_width == nil + unless w = ENV["COLUMNS"] and (w = w.to_i) > 0 + w = 80 + end + w -= 1 + self.window_width = w + end + if self.window_width and self.columns >= self.window_width + $stderr.print "\n", " " * (self.indent ||= 0) + self.columns = indent + end + $stderr.print c + $stderr.flush + self.columns += 1 + end + end + + def wn=(wn) + unless wn == 1 + if /(?:\A|\s)--jobserver-(?:auth|fds)=(?:(\d+),(\d+)|fifo:((?:\\.|\S)+))/ =~ ENV.delete("MAKEFLAGS") + begin + if fifo = $3 + fifo.gsub!(/\\(?=.)/, '') + r = File.open(fifo, IO::RDONLY|IO::NONBLOCK|IO::BINARY) + w = File.open(fifo, IO::WRONLY|IO::NONBLOCK|IO::BINARY) + else + r = IO.for_fd($1.to_i(10), "rb", autoclose: false) + w = IO.for_fd($2.to_i(10), "wb", autoclose: false) + end + rescue + r.close if r + else + r.close_on_exec = true + w.close_on_exec = true + tokens = r.read_nonblock(wn > 0 ? wn : 1024, exception: false) + r.close + if String === tokens + tokens.freeze + auth = w + w = nil + at_exit {auth << tokens; auth.close} + wn = tokens.size + 1 + else + w.close + wn = 1 + end + end + end + if wn <= 0 + require 'etc' + wn = [Etc.nprocessors / 2, 1].max + end + end + super wn + end +end.new + +BT_STATE = Struct.new(:count, :error).new + def main - @ruby = File.expand_path('miniruby') - @verbose = false + BT.ruby = File.expand_path('miniruby') + BT.verbose = false $VERBOSE = false $stress = false - @color = nil - @tty = nil - @quiet = false + BT.color = nil + BT.tty = nil + BT.quiet = false + # BT.wn = 1 dir = nil quiet = false tests = nil ARGV.delete_if {|arg| case arg when /\A--ruby=(.*)/ - @ruby = $1 - @ruby.gsub!(/^([^ ]*)/){File.expand_path($1)} - @ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)} - @ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)} + ruby = $1 + ruby.gsub!(/^([^ ]*)/){File.expand_path($1)} + ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)} + ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)} + BT.ruby = ruby true when /\A--sets=(.*)/ tests = Dir.glob("#{File.dirname($0)}/test_{#{$1}}*.rb").sort @@ -88,18 +179,23 @@ def main $stress = true when /\A--color(?:=(?:always|(auto)|(never)|(.*)))?\z/ warn "unknown --color argument: #$3" if $3 - @color = $1 ? nil : !$2 + BT.color = color = $1 ? nil : !$2 true when /\A--tty(=(?:yes|(no)|(.*)))?\z/ warn "unknown --tty argument: #$3" if $3 - @tty = !$1 || !$2 + BT.tty = !$1 || !$2 true when /\A(-q|--q(uiet))\z/ quiet = true - @quiet = true + BT.quiet = true + true + when /\A-j(\d+)?/ + BT.wn = $1.to_i true when /\A(-v|--v(erbose))\z/ - @verbose = true + BT.verbose = true + BT.quiet = false + true when /\A(-h|--h(elp)?)\z/ puts(<<-End) Usage: #{File.basename($0, '.*')} --ruby=PATH [--sets=NAME,NAME,...] @@ -121,22 +217,23 @@ End end } if tests and not ARGV.empty? - $stderr.puts "--tests and arguments are exclusive" - exit false + abort "--sets and arguments are exclusive" end tests ||= ARGV tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty? pathes = tests.map {|path| File.expand_path(path) } - @progress = %w[- \\ | /] - @progress_bs = "\b" * @progress[0].size - @tty = $stderr.tty? if @tty.nil? - case @color + BT.progress = %w[- \\ | /] + BT.progress_bs = "\b" * BT.progress[0].size + BT.tty = $stderr.tty? if BT.tty.nil? + BT.wn ||= /-j(\d+)?/ =~ (ENV["MAKEFLAGS"] || ENV["MFLAGS"]) ? $1.to_i : 1 + + case BT.color when nil - @color = @tty && /dumb/ !~ ENV["TERM"] + BT.color = BT.tty && /dumb/ !~ ENV["TERM"] end - @tty &&= !@verbose - if @color + BT.tty &&= !BT.verbose + if BT.color # dircolors-like style colors = (colors = ENV['TEST_COLORS']) ? Hash[colors.scan(/(\w+)=([^:\n]*)/)] : {} begin @@ -145,14 +242,16 @@ End end rescue end - @passed = "\e[;#{colors["pass"] || "32"}m" - @failed = "\e[;#{colors["fail"] || "31"}m" - @reset = "\e[m" + BT.passed = "\e[;#{colors["pass"] || "32"}m" + BT.failed = "\e[;#{colors["fail"] || "31"}m" + BT.reset = "\e[m" else - @passed = @failed = @reset = "" + BT.passed = BT.failed = BT.reset = "" end + target_version = `#{BT.ruby} -v`.chomp + BT.platform = target_version[/\[(.*)\]\z/, 1] unless quiet - puts Time.now + puts $start_time if defined?(RUBY_DESCRIPTION) puts "Driver is #{RUBY_DESCRIPTION}" elsif defined?(RUBY_PATCHLEVEL) @@ -160,272 +259,474 @@ End else puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" end - puts "Target is #{`#{@ruby} -v`.chomp}" + puts "Target is #{target_version}" puts $stdout.flush end - in_temporary_working_directory(dir) { + in_temporary_working_directory(dir) do exec_test pathes - } + end end def erase(e = true) - if e and @columns > 0 and @tty and !@verbose + if e and BT.columns > 0 and BT.tty and !BT.verbose "\e[1K\r" else "" end end -def exec_test(pathes) - @count = 0 - @error = 0 - @errbuf = [] - @location = nil - @columns = 0 - @width = pathes.map {|path| File.basename(path).size}.max + 2 +def load_test pathes pathes.each do |path| - @basename = File.basename(path) - $stderr.printf("%s%-*s ", erase(@quiet), @width, @basename) - $stderr.flush - @columns = @width + 1 - $stderr.puts if @verbose - count = @count - error = @error load File.expand_path(path) - if @tty - if @error == error - msg = "PASS #{@count-count}" - @columns += msg.size - 1 - $stderr.print "#{@progress_bs}#{@passed}#{msg}#{@reset}" + end +end + +def concurrent_exec_test + aq = Queue.new + rq = Queue.new + + ts = BT.wn.times.map do + Thread.new do + while as = aq.pop + as.call + rq << as + end + ensure + rq << nil + end + end + + Assertion.all.to_a.shuffle.each do |path, assertions| + assertions.each do |as| + aq << as + end + end + + BT.indent = 1 + aq.close + i = 1 + term_wn = 0 + begin + while BT.wn != term_wn + if r = rq.pop + case + when BT.quiet + when BT.tty + $stderr.print "#{BT.progress_bs}#{BT.progress[(i+=1) % BT.progress.size]}" + else + BT.putc '.' + end else - msg = "FAIL #{@error-error}/#{@count-count}" - $stderr.print "#{@progress_bs}#{@failed}#{msg}#{@reset}" - @columns = 0 + term_wn += 1 end end - $stderr.puts unless @quiet and @tty and @error == error + ensure + ts.each(&:kill) + ts.each(&:join) end - $stderr.print(erase) if @quiet - @errbuf.each do |msg| +end + +def exec_test(pathes) + # setup + load_test pathes + BT_STATE.count = 0 + BT_STATE.error = 0 + BT.columns = 0 + BT.width = pathes.map {|path| File.basename(path).size}.max + 2 + + # execute tests + if BT.wn > 1 + concurrent_exec_test + else + prev_basename = nil + Assertion.all.each do |basename, assertions| + if !BT.quiet && basename != prev_basename + prev_basename = basename + $stderr.printf("%s%-*s ", erase(BT.quiet), BT.width, basename) + $stderr.flush + end + BT.columns = BT.width + 1 + $stderr.puts if BT.verbose + count = BT_STATE.count + error = BT_STATE.error + + assertions.each do |assertion| + BT_STATE.count += 1 + assertion.call + end + + if BT.tty + if BT_STATE.error == error + msg = "PASS #{BT_STATE.count-count}" + BT.columns += msg.size - 1 + $stderr.print "#{BT.progress_bs}#{BT.passed}#{msg}#{BT.reset}" unless BT.quiet + else + msg = "FAIL #{BT_STATE.error-error}/#{BT_STATE.count-count}" + $stderr.print "#{BT.progress_bs}#{BT.failed}#{msg}#{BT.reset}" + BT.columns = 0 + end + end + $stderr.puts if !BT.quiet and (BT.tty or BT_STATE.error == error) + end + end + + # show results + unless BT.quiet + $stderr.puts(erase) + + sec = Time.now - $start_time + $stderr.puts "Finished in #{'%.2f' % sec} sec\n\n" if Assertion.count > 0 + end + + Assertion.errbuf.each do |msg| $stderr.puts msg end - if @error == 0 - if @count == 0 - $stderr.puts "No tests, no problem" + + out = BT.quiet ? $stdout : $stderr + + if BT_STATE.error == 0 + if Assertion.count == 0 + out.puts "No tests, no problem" unless BT.quiet else - $stderr.puts "#{@passed}PASS#{@reset} all #{@count} tests" + out.puts "#{BT.passed}PASS#{BT.reset} all #{Assertion.count} tests" end - exit true + true else - $stderr.puts "#{@failed}FAIL#{@reset} #{@error}/#{@count} tests failed" - exit false + $stderr.puts "#{BT.failed}FAIL#{BT.reset} #{BT_STATE.error}/#{BT_STATE.count} tests failed" + false end end -def show_progress(message = '') - if @verbose - $stderr.print "\##{@count} #{@location} " - elsif @tty - $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}" - end - t = Time.now if @verbose - faildesc, errout = with_stderr {yield} - t = Time.now - t if @verbose - if !faildesc - if @tty - $stderr.print "#{@progress_bs}#{@progress[@count % @progress.size]}" - elsif @verbose - $stderr.printf(". %.3f\n", t) - else - $stderr.print '.' +def target_platform + BT.platform or RUBY_PLATFORM +end + +class Assertion < Struct.new(:src, :path, :lineno, :proc) + @count = 0 + @all = Hash.new{|h, k| h[k] = []} + @errbuf = [] + + class << self + attr_reader :count, :errbuf + + def all + @all end - else - $stderr.print "#{@failed}F" - $stderr.printf(" %.3f", t) if @verbose - $stderr.print @reset - $stderr.puts if @verbose - error faildesc, message - unless errout.empty? - $stderr.print "#{@failed}stderr output is not empty#{@reset}\n", adjust_indent(errout) + + def add as + @all[as.path] << as + as.id = (@count += 1) end - if @tty and !@verbose - $stderr.printf("%-*s%s", @width, @basename, @progress[@count % @progress.size]) + end + + attr_accessor :id + attr_reader :err, :category + + def initialize(*args) + super + self.class.add self + @category = self.path[/\Atest_(.+)\.rb\z/, 1] + end + + def call + self.proc.call self + end + + def assert_check(message = '', opt = '', **argh) + show_progress(message) { + result = get_result_string(opt, **argh) + yield(result) + } + end + + def with_stderr + out = err = nil + r, w = IO.pipe + @err = w + err_reader = Thread.new{ r.read } + + begin + out = yield + ensure + w.close + err = err_reader.value + r.close rescue nil end + + return out, err end -rescue Interrupt - $stderr.puts "\##{@count} #{@location}" - raise -rescue Exception => err - $stderr.print 'E' - $stderr.puts if @verbose - error err.message, message -ensure - begin - check_coredump - rescue CoreDumpError => err + + def show_error(msg, additional_message) + msg = "#{BT.failed}\##{self.id} #{self.path}:#{self.lineno}#{BT.reset}: #{msg} #{additional_message}" + if BT.tty + $stderr.puts "#{erase}#{msg}" + else + Assertion.errbuf << msg + end + BT_STATE.error += 1 + end + + + def show_progress(message = '') + if BT.quiet || BT.wn > 1 + # do nothing + elsif BT.verbose + $stderr.print "\##{@id} #{self.path}:#{self.lineno} " + elsif BT.tty + $stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}" + end + + t = Time.now if BT.verbose + faildesc, errout = with_stderr {yield} + t = Time.now - t if BT.verbose + + if !faildesc + # success + if BT.quiet || BT.wn > 1 + # do nothing + elsif BT.tty + $stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}" + elsif BT.verbose + $stderr.printf(". %.3f\n", t) + else + BT.putc '.' + end + else + $stderr.print "#{BT.failed}F" + $stderr.printf(" %.3f", t) if BT.verbose + $stderr.print BT.reset + $stderr.puts if BT.verbose + show_error faildesc, message + unless errout.empty? + $stderr.print "#{BT.failed}stderr output is not empty#{BT.reset}\n", adjust_indent(errout) + end + + if BT.tty and !BT.verbose and BT.wn == 1 + $stderr.printf("%-*s%s", BT.width, path, BT.progress[BT_STATE.count % BT.progress.size]) + end + end + rescue Interrupt + $stderr.puts "\##{@id} #{path}:#{lineno}" + raise + rescue Exception => err $stderr.print 'E' - $stderr.puts if @verbose - error err.message, message + $stderr.puts if BT.verbose + show_error err.message, message + ensure + begin + check_coredump + rescue CoreDumpError => err + $stderr.print 'E' + $stderr.puts if BT.verbose + show_error err.message, message + cleanup_coredump + end end -end -def show_limit(testsrc, opt = '', **argh) - result = get_result_string(testsrc, opt, **argh) - if @tty and @verbose - $stderr.puts ".{#@reset}\n#{erase}#{result}" - else - @errbuf.push result + def get_result_string(opt = '', **argh) + if BT.ruby + filename = make_srcfile(**argh) + begin + kw = self.err ? {err: self.err} : {} + out = IO.popen("#{BT.ruby} -W0 #{opt} #{filename}", **kw) + pid = out.pid + out.read.tap{ Process.waitpid(pid); out.close } + ensure + raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"] + + begin + Process.kill :KILL, pid + rescue Errno::ESRCH + # OK + end + end + else + eval(src).to_s + end + end + + def make_srcfile(frozen_string_literal: nil) + filename = "bootstraptest.#{self.path}_#{self.lineno}_#{self.id}.rb" + File.open(filename, 'w') {|f| + f.puts "#frozen_string_literal:#{frozen_string_literal}" unless frozen_string_literal.nil? + if $stress + f.puts "GC.stress = true" if $stress + else + f.puts "" + end + f.puts "class BT_Skip < Exception; end; def skip(msg) = raise(BT_Skip, msg.to_s)" + f.puts "print(begin; #{self.src}; rescue BT_Skip; $!.message; end)" + } + filename end end -def assert_check(testsrc, message = '', opt = '', **argh) - show_progress(message) { - result = get_result_string(testsrc, opt, **argh) - yield(result) - } +def add_assertion src, pr + loc = caller_locations(2, 1).first + lineno = loc.lineno + path = File.basename(loc.path) + + Assertion.new(src, path, lineno, pr) end -def assert_equal(expected, testsrc, message = '', opt = '', **argh) - newtest - assert_check(testsrc, message, opt, **argh) {|result| - if expected == result - nil - else - desc = "#{result.inspect} (expected #{expected.inspect})" - pretty(testsrc, desc, result) - end - } +def assert_equal(expected, testsrc, message = '', opt = '', **kwargs) + add_assertion testsrc, -> as do + as.assert_check(message, opt, **kwargs) {|result| + if expected == result + nil + else + desc = "#{result.inspect} (expected #{expected.inspect})" + pretty(testsrc, desc, result) + end + } + end end -def assert_match(expected_pattern, testsrc, message = '') - newtest - assert_check(testsrc, message) {|result| - if expected_pattern =~ result - nil - else - desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}" - pretty(testsrc, desc, result) - end - } +def assert_match(expected_pattern, testsrc, message = '', **argh) + add_assertion testsrc, -> as do + as.assert_check(message, **argh) {|result| + if expected_pattern =~ result + nil + else + desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}" + pretty(testsrc, desc, result) + end + } + end end def assert_not_match(unexpected_pattern, testsrc, message = '') - newtest - assert_check(testsrc, message) {|result| - if unexpected_pattern !~ result - nil - else - desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}" - pretty(testsrc, desc, result) - end - } + add_assertion testsrc, -> as do + as.assert_check(message) {|result| + if unexpected_pattern !~ result + nil + else + desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}" + pretty(testsrc, desc, result) + end + } + end end def assert_valid_syntax(testsrc, message = '') - newtest - assert_check(testsrc, message, '-c') {|result| - result if /Syntax OK/ !~ result - } + add_assertion testsrc, -> as do + as.assert_check(message, '-c') {|result| + result if /Syntax OK/ !~ result + } + end end def assert_normal_exit(testsrc, *rest, timeout: nil, **opt) - newtest - message, ignore_signals = rest - message ||= '' - show_progress(message) { - faildesc = nil - filename = make_srcfile(testsrc) - old_stderr = $stderr.dup - timeout_signaled = false - begin - $stderr.reopen("assert_normal_exit.log", "w") - io = IO.popen("#{@ruby} -W0 #{filename}") - pid = io.pid - th = Thread.new { - io.read - io.close - $? - } - if !th.join(timeout) - Process.kill :KILL, pid - timeout_signaled = true - end - status = th.value - ensure - $stderr.reopen(old_stderr) - old_stderr.close - end - if status && status.signaled? - signo = status.termsig - signame = Signal.list.invert[signo] - unless ignore_signals and ignore_signals.include?(signame) - sigdesc = "signal #{signo}" - if signame - sigdesc = "SIG#{signame} (#{sigdesc})" - end - if timeout_signaled - sigdesc << " (timeout)" + add_assertion testsrc, -> as do + message, ignore_signals = rest + message ||= '' + as.show_progress(message) { + faildesc = nil + filename = as.make_srcfile + timeout_signaled = false + logfile = "assert_normal_exit.#{as.path}.#{as.lineno}.log" + + begin + err = open(logfile, "w") + io = IO.popen("#{BT.ruby} -W0 #{filename}", err: err) + pid = io.pid + th = Thread.new { + io.read + io.close + $? + } + if !th.join(timeout) + Process.kill :KILL, pid + timeout_signaled = true end - faildesc = pretty(testsrc, "killed by #{sigdesc}", nil) - stderr_log = File.read("assert_normal_exit.log") - if !stderr_log.empty? - faildesc << "\n" if /\n\z/ !~ faildesc - stderr_log << "\n" if /\n\z/ !~ stderr_log - stderr_log.gsub!(/^.*\n/) { '| ' + $& } - faildesc << stderr_log + status = th.value + ensure + err.close + end + if status && status.signaled? + signo = status.termsig + signame = Signal.list.invert[signo] + unless ignore_signals and ignore_signals.include?(signame) + sigdesc = "signal #{signo}" + if signame + sigdesc = "SIG#{signame} (#{sigdesc})" + end + if timeout_signaled + sigdesc << " (timeout)" + end + faildesc = pretty(testsrc, "killed by #{sigdesc}", nil) + stderr_log = File.read(logfile) + if !stderr_log.empty? + faildesc << "\n" if /\n\z/ !~ faildesc + stderr_log << "\n" if /\n\z/ !~ stderr_log + stderr_log.gsub!(/^.*\n/) { '| ' + $& } + faildesc << stderr_log + end end end - end - faildesc - } + faildesc + } + end end def assert_finish(timeout_seconds, testsrc, message = '') - if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # for --jit-wait - timeout_seconds *= 3 - end - newtest - show_progress(message) { - faildesc = nil - filename = make_srcfile(testsrc) - io = IO.popen("#{@ruby} -W0 #{filename}") - pid = io.pid - waited = false - tlimit = Time.now + timeout_seconds - diff = timeout_seconds - while diff > 0 - if Process.waitpid pid, Process::WNOHANG - waited = true - break - end - if io.respond_to?(:read_nonblock) - if IO.select([io], nil, nil, diff) - begin - io.read_nonblock(1024) - rescue Errno::EAGAIN, IO::WaitReadable, EOFError - break - end while true + add_assertion testsrc, -> as do + if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # for --jit-wait + timeout_seconds *= 3 + end + + as.show_progress(message) { + faildesc = nil + filename = as.make_srcfile + io = IO.popen("#{BT.ruby} -W0 #{filename}", err: as.err) + pid = io.pid + waited = false + tlimit = Time.now + timeout_seconds + diff = timeout_seconds + while diff > 0 + if Process.waitpid pid, Process::WNOHANG + waited = true + break end - else - sleep 0.1 + if io.respond_to?(:read_nonblock) + if IO.select([io], nil, nil, diff) + begin + io.read_nonblock(1024) + rescue Errno::EAGAIN, IO::WaitReadable, EOFError + break + end while true + end + else + sleep 0.1 + end + diff = tlimit - Time.now end - diff = tlimit - Time.now - end - if !waited - Process.kill(:KILL, pid) - Process.waitpid pid - faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil) - end - io.close - faildesc - } + if !waited + Process.kill(:KILL, pid) + Process.waitpid pid + faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil) + end + io.close + faildesc + } + end end def flunk(message = '') - newtest - show_progress('') { message } + add_assertion '', -> as do + as.show_progress('') { message } + end +end + +def show_limit(testsrc, opt = '', **argh) + return if BT.quiet + + add_assertion testsrc, -> as do + result = as.get_result_string(opt, **argh) + Assertion.errbuf << result + end end def pretty(src, desc, result) @@ -443,66 +744,6 @@ def untabify(str) str.gsub(/^\t+/) {' ' * (8 * $&.size) } end -def make_srcfile(src, frozen_string_literal: nil) - filename = 'bootstraptest.tmp.rb' - File.open(filename, 'w') {|f| - f.puts "#frozen_string_literal:true" if frozen_string_literal - f.puts "GC.stress = true" if $stress - f.puts "print(begin; #{src}; end)" - } - filename -end - -def get_result_string(src, opt = '', **argh) - if @ruby - filename = make_srcfile(src, **argh) - begin - `#{@ruby} -W0 #{opt} #{filename}` - ensure - raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"] - end - else - eval(src).to_s - end -end - -def with_stderr - out = err = nil - begin - r, w = IO.pipe - stderr = $stderr.dup - $stderr.reopen(w) - w.close - reader = Thread.start {r.read} - begin - out = yield - ensure - $stderr.reopen(stderr) - err = reader.value - end - ensure - w.close rescue nil - r.close rescue nil - end - return out, err -end - -def newtest - @location = File.basename(caller(2).first) - @count += 1 - cleanup_coredump -end - -def error(msg, additional_message) - msg = "#{@failed}\##{@count} #{@location}#{@reset}: #{msg} #{additional_message}" - if @tty - $stderr.puts "#{erase}#{msg}" - else - @errbuf.push msg - end - @error += 1 -end - def in_temporary_working_directory(dir) if dir Dir.mkdir dir @@ -530,21 +771,30 @@ def cleanup_coredump core_path = "/tmp/bootstraptest-core.#{Time.now.utc.iso8601}" warn "A core file is found. Saving it at: #{core_path.dump}" FileUtils.mv('core', core_path) - cmd = ['gdb', @ruby, '-c', core_path, '-ex', 'bt', '-batch'] + cmd = ['gdb', BT.ruby, '-c', core_path, '-ex', 'bt', '-batch'] p cmd # debugging why it's not working system(*cmd) end FileUtils.rm_f Dir.glob('core.*') - FileUtils.rm_f @ruby+'.stackdump' if @ruby + FileUtils.rm_f BT.ruby+'.stackdump' if BT.ruby end class CoreDumpError < StandardError; end def check_coredump if File.file?('core') or not Dir.glob('core.*').empty? or - (@ruby and File.exist?(@ruby+'.stackdump')) + (BT.ruby and File.exist?(BT.ruby+'.stackdump')) raise CoreDumpError, "core dumped" end end -main +def yjit_enabled? + ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit') +end + +def rjit_enabled? + # Don't check `RubyVM::RJIT.enabled?`. On btest-bruby, target Ruby != runner Ruby. + ENV.fetch('RUN_OPTS', '').include?('rjit') +end + +exit main |