rspec-core 3.7.1 → 3.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +29 -0
- data/README.md +1 -1
- data/lib/rspec/core/bisect/coordinator.rb +26 -30
- data/lib/rspec/core/bisect/example_minimizer.rb +12 -8
- data/lib/rspec/core/bisect/fork_runner.rb +134 -0
- data/lib/rspec/core/bisect/server.rb +4 -13
- data/lib/rspec/core/bisect/{runner.rb → shell_command.rb} +27 -70
- data/lib/rspec/core/bisect/shell_runner.rb +73 -0
- data/lib/rspec/core/bisect/utilities.rb +58 -0
- data/lib/rspec/core/configuration.rb +133 -53
- data/lib/rspec/core/configuration_options.rb +41 -4
- data/lib/rspec/core/example.rb +4 -4
- data/lib/rspec/core/example_group.rb +1 -0
- data/lib/rspec/core/formatters.rb +10 -6
- data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
- data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
- data/lib/rspec/core/formatters/bisect_progress_formatter.rb +29 -16
- data/lib/rspec/core/formatters/deprecation_formatter.rb +3 -1
- data/lib/rspec/core/formatters/exception_presenter.rb +1 -0
- data/lib/rspec/core/formatters/html_printer.rb +0 -2
- data/lib/rspec/core/formatters/protocol.rb +17 -17
- data/lib/rspec/core/formatters/syntax_highlighter.rb +19 -19
- data/lib/rspec/core/hooks.rb +1 -3
- data/lib/rspec/core/invocations.rb +8 -6
- data/lib/rspec/core/memoized_helpers.rb +2 -2
- data/lib/rspec/core/profiler.rb +3 -1
- data/lib/rspec/core/reporter.rb +3 -6
- data/lib/rspec/core/runner.rb +20 -14
- data/lib/rspec/core/shared_example_group.rb +1 -3
- data/lib/rspec/core/shell_escape.rb +2 -2
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +11 -0
- metadata +12 -8
- metadata.gz.sig +0 -0
- data/lib/rspec/core/formatters/bisect_formatter.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 01f0ed2875b8c4e0801d2857936e4a4116ceb309
|
4
|
+
data.tar.gz: 58b9a780de52779ef48a2c510d99c14dd7a22f1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc81061f5a9badff82a346285c6571447b9884906540c0502aeec96c1d100d4c764e2422f87dadd46148a8db96926b9c1a5e5d57a72adda28d6f05ddceae65e9
|
7
|
+
data.tar.gz: 940193670454593373c80e55c407e31a70b3eb8f9579b108663ec9234e2025149a93aed2d8aec8e2e7eeffd124853bf1a5a068d2a79e4bbcaed551b769d485fd
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
### 3.8.0 / 2018-08-04
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0)
|
3
|
+
|
4
|
+
Enhancements:
|
5
|
+
|
6
|
+
* Improve shell escaping used by `RSpec::Core::RakeTask` and `--bisect` so
|
7
|
+
that it works on `Pathname` objects. (Andrew Vit, #2479)
|
8
|
+
* Nicely format errors encountered while loading files specified
|
9
|
+
by `--require` option. (Myron Marston, #2504)
|
10
|
+
* Significantly improve the performance of `--bisect` on platforms that
|
11
|
+
support forking by replacing the shell-based runner with one that uses
|
12
|
+
forking so that RSpec and the application environment can be booted only
|
13
|
+
once, instead of once per spec run. (Myron Marston, #2511)
|
14
|
+
* Provide a configuration API to pick which bisect runner is used for
|
15
|
+
`--bisect`. Pick a runner via `config.bisect_runner = :shell` or
|
16
|
+
`config.bisect_runner = :fork` in a file loaded by a `--require`
|
17
|
+
option passed at the command line or set in `.rspec`. (Myron Marston, #2511)
|
18
|
+
* Support the [XDG Base Directory
|
19
|
+
Specification](https://specifications.freedesktop.org/basedir-spec/latest/)
|
20
|
+
for the global options file. `~/.rspec` is still supported when no
|
21
|
+
options file is found in `$XDG_CONFIG_HOME/rspec/options` (Magnus Bergmark, #2538)
|
22
|
+
* Extract `RSpec.world.prepare_example_filtering` that sets up the
|
23
|
+
example filtering for custom RSpec runners. (Oleg Pudeyev, #2552)
|
24
|
+
|
25
|
+
Bug Fixes:
|
26
|
+
|
27
|
+
* Prevent an `ArgumentError` when truncating backtraces with two identical
|
28
|
+
backtraces. (Systho, #2515, Benoit Tigeot, #2539)
|
29
|
+
|
1
30
|
### 3.7.1 / 2018-01-02
|
2
31
|
[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.0...v3.7.1)
|
3
32
|
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ RSpec repos as well. Add the following to your `Gemfile`:
|
|
15
15
|
|
16
16
|
```ruby
|
17
17
|
%w[rspec rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
|
18
|
-
gem lib, :git => "
|
18
|
+
gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
|
19
19
|
end
|
20
20
|
```
|
21
21
|
|
@@ -1,62 +1,58 @@
|
|
1
|
-
RSpec::Support.require_rspec_core "bisect/
|
2
|
-
RSpec::Support.require_rspec_core "bisect/runner"
|
1
|
+
RSpec::Support.require_rspec_core "bisect/shell_command"
|
3
2
|
RSpec::Support.require_rspec_core "bisect/example_minimizer"
|
3
|
+
RSpec::Support.require_rspec_core "bisect/utilities"
|
4
4
|
RSpec::Support.require_rspec_core "formatters/bisect_progress_formatter"
|
5
5
|
|
6
6
|
module RSpec
|
7
7
|
module Core
|
8
8
|
module Bisect
|
9
|
-
# @private
|
10
9
|
# The main entry point into the bisect logic. Coordinates among:
|
11
|
-
# - Bisect::
|
12
|
-
# - Bisect::Runner: Runs a set of examples and directs the results
|
13
|
-
# to the server.
|
10
|
+
# - Bisect::ShellCommand: Generates shell commands to run spec subsets
|
14
11
|
# - Bisect::ExampleMinimizer: Contains the core bisect logic.
|
15
|
-
# -
|
16
|
-
#
|
12
|
+
# - A bisect runner: runs a set of examples and returns the results.
|
13
|
+
# - A bisect formatter: provides progress updates to the user.
|
14
|
+
# @private
|
17
15
|
class Coordinator
|
18
|
-
def self.bisect_with(
|
19
|
-
new(
|
16
|
+
def self.bisect_with(spec_runner, original_cli_args, formatter)
|
17
|
+
new(spec_runner, original_cli_args, formatter).bisect
|
20
18
|
end
|
21
19
|
|
22
|
-
def initialize(
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@
|
20
|
+
def initialize(spec_runner, original_cli_args, formatter)
|
21
|
+
@spec_runner = spec_runner
|
22
|
+
@shell_command = ShellCommand.new(original_cli_args)
|
23
|
+
@notifier = Bisect::Notifier.new(formatter)
|
26
24
|
end
|
27
25
|
|
28
26
|
def bisect
|
29
|
-
|
30
|
-
|
31
|
-
reporter.close_after do
|
32
|
-
repro = Server.run do |server|
|
33
|
-
runner = Runner.new(server, @original_cli_args)
|
34
|
-
minimizer = ExampleMinimizer.new(runner, reporter)
|
27
|
+
repro = start_bisect_runner do |runner|
|
28
|
+
minimizer = ExampleMinimizer.new(@shell_command, runner, @notifier)
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
reporter.publish(:bisect_repro_command, :repro => repro)
|
30
|
+
gracefully_abort_on_sigint(minimizer)
|
31
|
+
minimizer.find_minimal_repro
|
32
|
+
minimizer.repro_command_for_currently_needed_ids
|
42
33
|
end
|
43
34
|
|
35
|
+
@notifier.publish(:bisect_repro_command, :repro => repro)
|
36
|
+
|
44
37
|
true
|
45
38
|
rescue BisectFailedError => e
|
46
|
-
|
39
|
+
@notifier.publish(:bisect_failed, :failure_explanation => e.message)
|
47
40
|
false
|
41
|
+
ensure
|
42
|
+
@notifier.publish(:close)
|
48
43
|
end
|
49
44
|
|
50
45
|
private
|
51
46
|
|
52
|
-
def
|
53
|
-
@configuration.
|
47
|
+
def start_bisect_runner(&block)
|
48
|
+
klass = @spec_runner.configuration.bisect_runner_class
|
49
|
+
klass.start(@shell_command, @spec_runner, &block)
|
54
50
|
end
|
55
51
|
|
56
52
|
def gracefully_abort_on_sigint(minimizer)
|
57
53
|
trap('INT') do
|
58
54
|
repro = minimizer.repro_command_for_currently_needed_ids
|
59
|
-
|
55
|
+
@notifier.publish(:bisect_aborted, :repro => repro)
|
60
56
|
exit(1)
|
61
57
|
end
|
62
58
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
RSpec::Support.require_rspec_core "bisect/utilities"
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Core
|
3
5
|
module Bisect
|
@@ -5,12 +7,13 @@ module RSpec
|
|
5
7
|
# Contains the core bisect logic. Searches for examples we can ignore by
|
6
8
|
# repeatedly running different subsets of the suite.
|
7
9
|
class ExampleMinimizer
|
8
|
-
attr_reader :
|
10
|
+
attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids
|
9
11
|
attr_accessor :remaining_ids
|
10
12
|
|
11
|
-
def initialize(runner,
|
12
|
-
@
|
13
|
-
@
|
13
|
+
def initialize(shell_command, runner, notifier)
|
14
|
+
@shell_command = shell_command
|
15
|
+
@runner = runner
|
16
|
+
@notifier = notifier
|
14
17
|
end
|
15
18
|
|
16
19
|
def find_minimal_repro
|
@@ -82,7 +85,7 @@ module RSpec
|
|
82
85
|
end
|
83
86
|
|
84
87
|
def repro_command_for_currently_needed_ids
|
85
|
-
return
|
88
|
+
return shell_command.repro_command_from(currently_needed_ids) if remaining_ids
|
86
89
|
"(Not yet enough information to provide any repro command)"
|
87
90
|
end
|
88
91
|
|
@@ -108,7 +111,8 @@ module RSpec
|
|
108
111
|
end
|
109
112
|
|
110
113
|
def prep
|
111
|
-
notify(:bisect_starting, :original_cli_args =>
|
114
|
+
notify(:bisect_starting, :original_cli_args => shell_command.original_cli_args,
|
115
|
+
:bisect_runner => runner.class.name)
|
112
116
|
|
113
117
|
_, duration = track_duration do
|
114
118
|
original_results = runner.original_results
|
@@ -135,7 +139,7 @@ module RSpec
|
|
135
139
|
ids_to_run = ids + failed_example_ids
|
136
140
|
notify(
|
137
141
|
:bisect_individual_run_start,
|
138
|
-
:command =>
|
142
|
+
:command => shell_command.repro_command_from(ids_to_run),
|
139
143
|
:ids_to_run => ids_to_run
|
140
144
|
)
|
141
145
|
|
@@ -161,7 +165,7 @@ module RSpec
|
|
161
165
|
end
|
162
166
|
|
163
167
|
def notify(*args)
|
164
|
-
|
168
|
+
@notifier.publish(*args)
|
165
169
|
end
|
166
170
|
end
|
167
171
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
RSpec::Support.require_rspec_core "formatters/base_bisect_formatter"
|
3
|
+
RSpec::Support.require_rspec_core "bisect/utilities"
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module Core
|
7
|
+
module Bisect
|
8
|
+
# A Bisect runner that runs requested subsets of the suite by forking
|
9
|
+
# sub-processes. The master process bootstraps RSpec and the application
|
10
|
+
# environment (including preloading files specified via `--require`) so
|
11
|
+
# that the individual spec runs do not have to re-pay that cost. Each
|
12
|
+
# spec run happens in a forked process, ensuring that the spec files are
|
13
|
+
# not loaded in the main process.
|
14
|
+
#
|
15
|
+
# For most projects, bisections that use `ForkRunner` instead of
|
16
|
+
# `ShellRunner` will finish significantly faster, because the `ShellRunner`
|
17
|
+
# pays the cost of booting RSpec and the app environment on _every_ run of
|
18
|
+
# a subset. In contrast, `ForkRunner` pays that cost only once.
|
19
|
+
#
|
20
|
+
# However, not all projects can use `ForkRunner`. Obviously, on platforms
|
21
|
+
# that do not support forking (e.g. Windows), it cannot be used. In addition,
|
22
|
+
# it can cause problems for some projects that put side-effectful spec
|
23
|
+
# bootstrapping logic that should run on every spec run directly at the top
|
24
|
+
# level in a file loaded by `--require`, rather than in a `before(:suite)`
|
25
|
+
# hook. For example, consider a project that relies on some top-level logic
|
26
|
+
# in `spec_helper` to boot a Redis server for the test suite, intending the
|
27
|
+
# Redis bootstrapping to happen on every spec run. With `ShellRunner`, the
|
28
|
+
# bootstrapping logic will happen for each run of any subset of the suite,
|
29
|
+
# but for `ForkRunner`, such logic will only get run once, when the
|
30
|
+
# `RunDispatcher` boots the application environment. This might cause
|
31
|
+
# problems. The solution is for users to move the bootstrapping logic into
|
32
|
+
# a `before(:suite)` hook, or use the slower `ShellRunner`.
|
33
|
+
#
|
34
|
+
# @private
|
35
|
+
class ForkRunner
|
36
|
+
def self.start(shell_command, spec_runner)
|
37
|
+
instance = new(shell_command, spec_runner)
|
38
|
+
yield instance
|
39
|
+
ensure
|
40
|
+
instance.shutdown
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.name
|
44
|
+
:fork
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(shell_command, spec_runner)
|
48
|
+
@shell_command = shell_command
|
49
|
+
@channel = Channel.new
|
50
|
+
@run_dispatcher = RunDispatcher.new(spec_runner, @channel)
|
51
|
+
end
|
52
|
+
|
53
|
+
def run(locations)
|
54
|
+
run_descriptor = ExampleSetDescriptor.new(locations, original_results.failed_example_ids)
|
55
|
+
dispatch_run(run_descriptor)
|
56
|
+
end
|
57
|
+
|
58
|
+
def original_results
|
59
|
+
@original_results ||= dispatch_run(ExampleSetDescriptor.new(
|
60
|
+
@shell_command.original_locations, []))
|
61
|
+
end
|
62
|
+
|
63
|
+
def shutdown
|
64
|
+
@channel.close
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def dispatch_run(run_descriptor)
|
70
|
+
@run_dispatcher.dispatch_specs(run_descriptor)
|
71
|
+
@channel.receive.tap do |result|
|
72
|
+
if result.is_a?(String)
|
73
|
+
raise BisectFailedError.for_failed_spec_run(result)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
class RunDispatcher
|
80
|
+
def initialize(runner, channel)
|
81
|
+
@runner = runner
|
82
|
+
@channel = channel
|
83
|
+
|
84
|
+
@spec_output = StringIO.new
|
85
|
+
|
86
|
+
runner.configuration.tap do |c|
|
87
|
+
c.reset_reporter
|
88
|
+
c.output_stream = @spec_output
|
89
|
+
c.error_stream = @spec_output
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def dispatch_specs(run_descriptor)
|
94
|
+
pid = fork { run_specs(run_descriptor) }
|
95
|
+
Process.waitpid(pid)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def run_specs(run_descriptor)
|
101
|
+
$stdout = $stderr = @spec_output
|
102
|
+
formatter = CaptureFormatter.new(run_descriptor.failed_example_ids)
|
103
|
+
|
104
|
+
@runner.configuration.tap do |c|
|
105
|
+
c.files_or_directories_to_run = run_descriptor.all_example_ids
|
106
|
+
c.formatter = formatter
|
107
|
+
c.load_spec_files
|
108
|
+
end
|
109
|
+
|
110
|
+
# `announce_filters` has the side effect of implementing the logic
|
111
|
+
# that honors `config.run_all_when_everything_filtered` so we need
|
112
|
+
# to call it here. When we remove `run_all_when_everything_filtered`
|
113
|
+
# (slated for RSpec 4), we can remove this call to `announce_filters`.
|
114
|
+
@runner.world.announce_filters
|
115
|
+
|
116
|
+
@runner.run_specs(@runner.world.ordered_example_groups)
|
117
|
+
latest_run_results = formatter.results
|
118
|
+
|
119
|
+
if latest_run_results.nil? || latest_run_results.all_example_ids.empty?
|
120
|
+
@channel.send(@spec_output.string)
|
121
|
+
else
|
122
|
+
@channel.send(latest_run_results)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class CaptureFormatter < Formatters::BaseBisectFormatter
|
128
|
+
attr_accessor :results
|
129
|
+
alias_method :notify_results, :results=
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'drb/drb'
|
2
2
|
require 'drb/acl'
|
3
|
+
RSpec::Support.require_rspec_core "bisect/utilities"
|
3
4
|
|
4
5
|
module RSpec
|
5
6
|
module Core
|
6
7
|
# @private
|
7
8
|
module Bisect
|
8
|
-
# @private
|
9
|
-
BisectFailedError = Class.new(StandardError)
|
10
|
-
|
11
9
|
# @private
|
12
10
|
# A DRb server that receives run results from a separate RSpec process
|
13
11
|
# started by the bisect process.
|
@@ -27,7 +25,7 @@ module RSpec
|
|
27
25
|
run_output = yield
|
28
26
|
|
29
27
|
if latest_run_results.nil? || latest_run_results.all_example_ids.empty?
|
30
|
-
|
28
|
+
raise BisectFailedError.for_failed_spec_run(run_output)
|
31
29
|
end
|
32
30
|
|
33
31
|
latest_run_results
|
@@ -49,21 +47,14 @@ module RSpec
|
|
49
47
|
@drb_port ||= Integer(@drb.uri[/\d+$/])
|
50
48
|
end
|
51
49
|
|
52
|
-
# Fetched via DRb by the
|
50
|
+
# Fetched via DRb by the BisectDRbFormatter to determine when to abort.
|
53
51
|
attr_accessor :expected_failures
|
54
52
|
|
55
|
-
# Set via DRb by the
|
53
|
+
# Set via DRb by the BisectDRbFormatter with the results of the run.
|
56
54
|
attr_accessor :latest_run_results
|
57
55
|
|
58
56
|
# Fetched via DRb to tell clients which files to run
|
59
57
|
attr_accessor :files_or_directories_to_run
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def raise_bisect_failed(run_output)
|
64
|
-
raise BisectFailedError, "Failed to get results from the spec " \
|
65
|
-
"run. Spec run output:\n\n#{run_output}"
|
66
|
-
end
|
67
58
|
end
|
68
59
|
end
|
69
60
|
end
|
@@ -1,36 +1,30 @@
|
|
1
1
|
RSpec::Support.require_rspec_core "shell_escape"
|
2
|
-
require 'open3'
|
3
2
|
require 'shellwords'
|
4
3
|
|
5
4
|
module RSpec
|
6
5
|
module Core
|
7
6
|
module Bisect
|
8
|
-
# Provides an API to run the suite for a
|
9
|
-
# the given bisect server to capture the results.
|
7
|
+
# Provides an API to generate shell commands to run the suite for a
|
8
|
+
# set of locations, using the given bisect server to capture the results.
|
10
9
|
# @private
|
11
|
-
class
|
10
|
+
class ShellCommand
|
12
11
|
attr_reader :original_cli_args
|
13
12
|
|
14
|
-
def initialize(
|
15
|
-
@server = server
|
13
|
+
def initialize(original_cli_args)
|
16
14
|
@original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") }
|
17
15
|
end
|
18
16
|
|
19
|
-
def
|
20
|
-
run_locations(locations, original_results.failed_example_ids)
|
21
|
-
end
|
22
|
-
|
23
|
-
def command_for(locations)
|
17
|
+
def command_for(locations, server)
|
24
18
|
parts = []
|
25
19
|
|
26
20
|
parts << RUBY << load_path
|
27
21
|
parts << open3_safe_escape(RSpec::Core.path_to_executable)
|
28
22
|
|
29
|
-
parts << "--format" << "bisect"
|
30
|
-
parts << "--drb-port" <<
|
23
|
+
parts << "--format" << "bisect-drb"
|
24
|
+
parts << "--drb-port" << server.drb_port
|
31
25
|
|
32
|
-
parts.concat
|
33
|
-
parts.concat
|
26
|
+
parts.concat(reusable_cli_options)
|
27
|
+
parts.concat(locations.map { |l| open3_safe_escape(l) })
|
34
28
|
|
35
29
|
parts.join(" ")
|
36
30
|
end
|
@@ -46,8 +40,24 @@ module RSpec
|
|
46
40
|
parts.join(" ")
|
47
41
|
end
|
48
42
|
|
49
|
-
def
|
50
|
-
|
43
|
+
def original_locations
|
44
|
+
parsed_original_cli_options.fetch(:files_or_directories_to_run)
|
45
|
+
end
|
46
|
+
|
47
|
+
def bisect_environment_hash
|
48
|
+
if ENV.key?('SPEC_OPTS')
|
49
|
+
{ 'SPEC_OPTS' => spec_opts_without_bisect }
|
50
|
+
else
|
51
|
+
{}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def spec_opts_without_bisect
|
56
|
+
Shellwords.join(
|
57
|
+
Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
|
58
|
+
arg =~ /^--bisect/
|
59
|
+
end
|
60
|
+
)
|
51
61
|
end
|
52
62
|
|
53
63
|
private
|
@@ -63,61 +73,12 @@ module RSpec
|
|
63
73
|
alias open3_safe_escape escape
|
64
74
|
end
|
65
75
|
|
66
|
-
def run_locations(*capture_args)
|
67
|
-
@server.capture_run_results(*capture_args) do
|
68
|
-
run_command command_for([])
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# `Open3.capture2e` does not work on JRuby:
|
73
|
-
# https://github.com/jruby/jruby/issues/2766
|
74
|
-
if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby?
|
75
|
-
def run_command(cmd)
|
76
|
-
Open3.capture2e(bisect_environment_hash, cmd).first
|
77
|
-
end
|
78
|
-
else # for 1.8.7
|
79
|
-
# :nocov:
|
80
|
-
def run_command(cmd)
|
81
|
-
out = err = nil
|
82
|
-
|
83
|
-
original_spec_opts = ENV['SPEC_OPTS']
|
84
|
-
ENV['SPEC_OPTS'] = spec_opts_without_bisect
|
85
|
-
|
86
|
-
Open3.popen3(cmd) do |_, stdout, stderr|
|
87
|
-
# Reading the streams blocks until the process is complete
|
88
|
-
out = stdout.read
|
89
|
-
err = stderr.read
|
90
|
-
end
|
91
|
-
|
92
|
-
"Stdout:\n#{out}\n\nStderr:\n#{err}"
|
93
|
-
ensure
|
94
|
-
ENV['SPEC_OPTS'] = original_spec_opts
|
95
|
-
end
|
96
|
-
# :nocov:
|
97
|
-
end
|
98
|
-
|
99
|
-
def bisect_environment_hash
|
100
|
-
if ENV.key?('SPEC_OPTS')
|
101
|
-
{ 'SPEC_OPTS' => spec_opts_without_bisect }
|
102
|
-
else
|
103
|
-
{}
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
76
|
def environment_repro_parts
|
108
77
|
bisect_environment_hash.map do |k, v|
|
109
78
|
%Q(#{k}="#{v}")
|
110
79
|
end
|
111
80
|
end
|
112
81
|
|
113
|
-
def spec_opts_without_bisect
|
114
|
-
Shellwords.join(
|
115
|
-
Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
|
116
|
-
arg =~ /^--bisect/
|
117
|
-
end
|
118
|
-
)
|
119
|
-
end
|
120
|
-
|
121
82
|
def reusable_cli_options
|
122
83
|
@reusable_cli_options ||= begin
|
123
84
|
opts = original_cli_args_without_locations
|
@@ -146,10 +107,6 @@ module RSpec
|
|
146
107
|
@parsed_original_cli_options ||= Parser.parse(@original_cli_args)
|
147
108
|
end
|
148
109
|
|
149
|
-
def original_locations
|
150
|
-
parsed_original_cli_options.fetch(:files_or_directories_to_run)
|
151
|
-
end
|
152
|
-
|
153
110
|
def load_path
|
154
111
|
@load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}"
|
155
112
|
end
|