diff options
Diffstat (limited to 'spec/mspec/lib/mspec/helpers/ruby_exe.rb')
-rw-r--r-- | spec/mspec/lib/mspec/helpers/ruby_exe.rb | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb index c62c19f3aa..2e499d6f9a 100644 --- a/spec/mspec/lib/mspec/helpers/ruby_exe.rb +++ b/spec/mspec/lib/mspec/helpers/ruby_exe.rb @@ -112,6 +112,8 @@ unless Object.const_defined?(:RUBY_EXE) and RUBY_EXE end def ruby_exe(code = :not_given, opts = {}) + skip "WASI doesn't provide subprocess" if PlatformGuard.wasi? + if opts[:dir] raise "ruby_exe(..., dir: dir) is no longer supported, use Dir.chdir" end @@ -135,20 +137,47 @@ def ruby_exe(code = :not_given, opts = {}) code = tmpfile end - expected_exit_status = opts.fetch(:exit_status, 0) + expected_status = opts.fetch(:exit_status, 0) begin - platform_is_not :opal do - command = ruby_cmd(code, opts) - output = `#{command}` + command = ruby_cmd(code, opts) + + # Try to avoid the extra shell for 2>&1 + # This is notably useful for TimeoutAction which can then signal the ruby subprocess and not the shell + popen_options = [] + if command.end_with?(' 2>&1') + command = command[0...-5] + popen_options = [{ err: [:child, :out] }] + end - last_status = Process.last_status - if last_status.exitstatus != expected_exit_status - raise "Expected exit status is #{expected_exit_status.inspect} but actual is #{last_status.exitstatus.inspect} for command ruby_exe(#{command.inspect})" + output = IO.popen(command, *popen_options) do |io| + pid = io.pid + MSpec.subprocesses << pid + begin + io.read + ensure + MSpec.subprocesses.delete(pid) end + end - output + 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 saved_env.each { |key, value| ENV[key] = value } env.keys.each do |key| |