class TurboTests::Runner
def start_subprocess(env, extra_args, tests, process_id, record_runtime:)
def start_subprocess(env, extra_args, tests, process_id, record_runtime:) if tests.empty? @messages << { type: "exit", process_id: process_id } else tmp_filename = "tmp/test-pipes/subprocess-#{process_id}" begin File.mkfifo(tmp_filename) rescue Errno::EEXIST end env["RUBYOPT"] = ["-I#{File.expand_path("..", __dir__)}", ENV["RUBYOPT"]].compact.join(" ") env["RSPEC_SILENCE_FILTER_ANNOUNCEMENTS"] = "1" record_runtime_options = if record_runtime [ "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", @runtime_log, ] else [] end command = [ ENV["BUNDLE_BIN_PATH"], "exec", "rspec", *extra_args, "--seed", rand(0xFFFF).to_s, "--format", "TurboTests::JsonRowsFormatter", "--out", tmp_filename, *record_runtime_options, *tests ] if @verbose command_str = [ env.map { |k, v| "#{k}=#{v}" }.join(" "), command.join(" ") ].select { |x| x.size > 0 }.join(" ") STDERR.puts "Process #{process_id}: #{command_str}" end stdin, stdout, stderr, wait_thr = Open3.popen3(env, *command) stdin.close @threads << Thread.new do File.open(tmp_filename) do |fd| fd.each_line do |line| message = JSON.parse(line, symbolize_names: true) message[:process_id] = process_id @messages << message end end @messages << {type: "exit", process_id: process_id} end @threads << start_copy_thread(stdout, STDOUT) @threads << start_copy_thread(stderr, STDERR) @threads << Thread.new { unless wait_thr.value.success? @messages << {type: "error"} end } wait_thr end end