1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
RSpec::Support.require_rspec_core "shell_escape"
require 'open3'
module RSpec
module Core
module Bisect
# Provides an API to run the suite for a set of locations, using
# the given bisect server to capture the results.
# @private
class Runner
attr_reader :original_cli_args
def initialize(server, original_cli_args)
@server = server
@original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") }
end
def run(locations)
run_locations(locations, original_results.failed_example_ids)
end
def command_for(locations)
parts = []
parts << RUBY << load_path
parts << open3_safe_escape(RSpec::Core.path_to_executable)
parts << "--format" << "bisect"
parts << "--drb-port" << @server.drb_port
parts.concat reusable_cli_options
parts.concat locations.map { |l| open3_safe_escape(l) }
parts.join(" ")
end
def repro_command_from(locations)
parts = []
parts << "rspec"
parts.concat Formatters::Helpers.organize_ids(locations)
parts.concat original_cli_args_without_locations
parts.join(" ")
end
def original_results
@original_results ||= run_locations(original_locations)
end
private
include RSpec::Core::ShellEscape
# On JRuby, Open3.popen3 does not handle shellescaped args properly:
# https://github.com/jruby/jruby/issues/2767
if RSpec::Support::Ruby.jruby?
# :nocov:
alias open3_safe_escape quote
# :nocov:
else
alias open3_safe_escape escape
end
def run_locations(locations, *capture_args)
@server.capture_run_results(*capture_args) do
run_command command_for(locations)
end
end
# `Open3.capture2e` does not work on JRuby:
# https://github.com/jruby/jruby/issues/2766
if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby?
def run_command(cmd)
Open3.capture2e(cmd).first
end
else # for 1.8.7
# :nocov:
def run_command(cmd)
out = err = nil
Open3.popen3(cmd) do |_, stdout, stderr|
# Reading the streams blocks until the process is complete
out = stdout.read
err = stderr.read
end
"Stdout:\n#{out}\n\nStderr:\n#{err}"
end
# :nocov:
end
def reusable_cli_options
@reusable_cli_options ||= begin
opts = original_cli_args_without_locations
if (port = parsed_original_cli_options[:drb_port])
opts -= %W[ --drb-port #{port} ]
end
parsed_original_cli_options.fetch(:formatters) { [] }.each do |(name, out)|
opts -= %W[ --format #{name} -f -f#{name} ]
opts -= %W[ --out #{out} -o -o#{out} ]
end
opts
end
end
def original_cli_args_without_locations
@original_cli_args_without_locations ||= begin
files_or_dirs = parsed_original_cli_options.fetch(:files_or_directories_to_run)
@original_cli_args - files_or_dirs
end
end
def parsed_original_cli_options
@parsed_original_cli_options ||= Parser.parse(@original_cli_args)
end
def original_locations
parsed_original_cli_options.fetch(:files_or_directories_to_run)
end
def load_path
@load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}"
end
# Path to the currently running Ruby executable, borrowed from Rake:
# https://github.com/ruby/rake/blob/v10.4.2/lib/rake/file_utils.rb#L8-L12
# Note that we skip `ENV['RUBY']` because we don't have to deal with running
# RSpec from within a MRI source repository:
# https://github.com/ruby/rake/commit/968682759b3b65e42748cd2befb2ff3e982272d9
RUBY = File.join(
RbConfig::CONFIG['bindir'],
RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT']).
sub(/.*\s.*/m, '"\&"')
end
end
end
end
|