diff options
Diffstat (limited to 'spec/mspec/lib/mspec/helpers/ruby_exe.rb')
-rw-r--r-- | spec/mspec/lib/mspec/helpers/ruby_exe.rb | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb index 4948ec09f1..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 @@ -138,19 +140,44 @@ def ruby_exe(code = :not_given, opts = {}) expected_status = opts.fetch(:exit_status, 0) begin - platform_is_not :opal do - command = ruby_cmd(code, opts) - output = `#{command}` - - exit_status = Process.last_status.exitstatus - 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}" + 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 + + 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| |