sspec-core 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.yardopts +8 -0
- data/Changelog.md +2232 -0
- data/LICENSE.md +26 -0
- data/README.md +384 -0
- data/exe/rspec +4 -0
- data/lib/rspec/autorun.rb +3 -0
- data/lib/rspec/core.rb +185 -0
- data/lib/rspec/core/backtrace_formatter.rb +65 -0
- data/lib/rspec/core/bisect/coordinator.rb +62 -0
- data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
- data/lib/rspec/core/bisect/fork_runner.rb +134 -0
- data/lib/rspec/core/bisect/server.rb +61 -0
- data/lib/rspec/core/bisect/shell_command.rb +126 -0
- 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 +2289 -0
- data/lib/rspec/core/configuration_options.rb +233 -0
- data/lib/rspec/core/drb.rb +113 -0
- data/lib/rspec/core/dsl.rb +98 -0
- data/lib/rspec/core/example.rb +653 -0
- data/lib/rspec/core/example_group.rb +885 -0
- data/lib/rspec/core/example_status_persister.rb +235 -0
- data/lib/rspec/core/filter_manager.rb +231 -0
- data/lib/rspec/core/flat_map.rb +20 -0
- data/lib/rspec/core/formatters.rb +269 -0
- data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
- data/lib/rspec/core/formatters/base_formatter.rb +70 -0
- data/lib/rspec/core/formatters/base_text_formatter.rb +75 -0
- data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
- data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
- data/lib/rspec/core/formatters/console_codes.rb +68 -0
- data/lib/rspec/core/formatters/deprecation_formatter.rb +223 -0
- data/lib/rspec/core/formatters/documentation_formatter.rb +70 -0
- data/lib/rspec/core/formatters/exception_presenter.rb +508 -0
- data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
- data/lib/rspec/core/formatters/helpers.rb +110 -0
- data/lib/rspec/core/formatters/html_formatter.rb +153 -0
- data/lib/rspec/core/formatters/html_printer.rb +414 -0
- data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
- data/lib/rspec/core/formatters/json_formatter.rb +102 -0
- data/lib/rspec/core/formatters/profile_formatter.rb +68 -0
- data/lib/rspec/core/formatters/progress_formatter.rb +29 -0
- data/lib/rspec/core/formatters/protocol.rb +182 -0
- data/lib/rspec/core/formatters/snippet_extractor.rb +134 -0
- data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
- data/lib/rspec/core/hooks.rb +624 -0
- data/lib/rspec/core/invocations.rb +87 -0
- data/lib/rspec/core/memoized_helpers.rb +554 -0
- data/lib/rspec/core/metadata.rb +499 -0
- data/lib/rspec/core/metadata_filter.rb +255 -0
- data/lib/rspec/core/minitest_assertions_adapter.rb +31 -0
- data/lib/rspec/core/mocking_adapters/flexmock.rb +31 -0
- data/lib/rspec/core/mocking_adapters/mocha.rb +57 -0
- data/lib/rspec/core/mocking_adapters/null.rb +14 -0
- data/lib/rspec/core/mocking_adapters/rr.rb +31 -0
- data/lib/rspec/core/mocking_adapters/rspec.rb +32 -0
- data/lib/rspec/core/notifications.rb +521 -0
- data/lib/rspec/core/option_parser.rb +309 -0
- data/lib/rspec/core/ordering.rb +158 -0
- data/lib/rspec/core/output_wrapper.rb +29 -0
- data/lib/rspec/core/pending.rb +165 -0
- data/lib/rspec/core/profiler.rb +34 -0
- data/lib/rspec/core/project_initializer.rb +48 -0
- data/lib/rspec/core/project_initializer/.rspec +1 -0
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +100 -0
- data/lib/rspec/core/rake_task.rb +168 -0
- data/lib/rspec/core/reporter.rb +257 -0
- data/lib/rspec/core/ruby_project.rb +53 -0
- data/lib/rspec/core/runner.rb +199 -0
- data/lib/rspec/core/sandbox.rb +37 -0
- data/lib/rspec/core/set.rb +54 -0
- data/lib/rspec/core/shared_context.rb +55 -0
- data/lib/rspec/core/shared_example_group.rb +269 -0
- data/lib/rspec/core/shell_escape.rb +49 -0
- data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
- data/lib/rspec/core/version.rb +9 -0
- data/lib/rspec/core/warnings.rb +40 -0
- data/lib/rspec/core/world.rb +275 -0
- metadata +257 -0
@@ -0,0 +1,257 @@
|
|
1
|
+
module RSpec::Core
|
2
|
+
# A reporter will send notifications to listeners, usually formatters for the
|
3
|
+
# spec suite run.
|
4
|
+
class Reporter
|
5
|
+
# @private
|
6
|
+
RSPEC_NOTIFICATIONS = Set.new(
|
7
|
+
[
|
8
|
+
:close, :deprecation, :deprecation_summary, :dump_failures, :dump_pending,
|
9
|
+
:dump_profile, :dump_summary, :example_failed, :example_group_finished,
|
10
|
+
:example_group_started, :example_passed, :example_pending, :example_started,
|
11
|
+
:message, :seed, :start, :start_dump, :stop, :example_finished
|
12
|
+
])
|
13
|
+
|
14
|
+
def initialize(configuration)
|
15
|
+
@configuration = configuration
|
16
|
+
@listeners = Hash.new { |h, k| h[k] = Set.new }
|
17
|
+
@examples = []
|
18
|
+
@failed_examples = []
|
19
|
+
@pending_examples = []
|
20
|
+
@duration = @start = @load_time = nil
|
21
|
+
@non_example_exception_count = 0
|
22
|
+
@setup_default = lambda {}
|
23
|
+
@setup = false
|
24
|
+
@profiler = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# @private
|
28
|
+
attr_reader :examples, :failed_examples, :pending_examples
|
29
|
+
|
30
|
+
# Registers a listener to a list of notifications. The reporter will send
|
31
|
+
# notification of events to all registered listeners.
|
32
|
+
#
|
33
|
+
# @param listener [Object] An obect that wishes to be notified of reporter
|
34
|
+
# events
|
35
|
+
# @param notifications [Array] Array of symbols represents the events a
|
36
|
+
# listener wishes to subscribe too
|
37
|
+
def register_listener(listener, *notifications)
|
38
|
+
notifications.each do |notification|
|
39
|
+
@listeners[notification.to_sym] << listener
|
40
|
+
end
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# @private
|
45
|
+
def prepare_default(loader, output_stream, deprecation_stream)
|
46
|
+
@setup_default = lambda do
|
47
|
+
loader.setup_default output_stream, deprecation_stream
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @private
|
52
|
+
def registered_listeners(notification)
|
53
|
+
@listeners[notification].to_a
|
54
|
+
end
|
55
|
+
|
56
|
+
# @overload report(count, &block)
|
57
|
+
# @overload report(count, &block)
|
58
|
+
# @param expected_example_count [Integer] the number of examples being run
|
59
|
+
# @yield [Block] block yields itself for further reporting.
|
60
|
+
#
|
61
|
+
# Initializes the report run and yields itself for further reporting. The
|
62
|
+
# block is required, so that the reporter can manage cleaning up after the
|
63
|
+
# run.
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
#
|
67
|
+
# reporter.report(group.examples.size) do |r|
|
68
|
+
# example_groups.map {|g| g.run(r) }
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
def report(expected_example_count)
|
72
|
+
start(expected_example_count)
|
73
|
+
begin
|
74
|
+
yield self
|
75
|
+
ensure
|
76
|
+
finish
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# @private
|
81
|
+
def start(expected_example_count, time=RSpec::Core::Time.now)
|
82
|
+
@start = time
|
83
|
+
@load_time = (@start - @configuration.start_time).to_f
|
84
|
+
notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?)
|
85
|
+
notify :start, Notifications::StartNotification.new(expected_example_count, @load_time)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param message [#to_s] A message object to send to formatters
|
89
|
+
#
|
90
|
+
# Send a custom message to supporting formatters.
|
91
|
+
def message(message)
|
92
|
+
notify :message, Notifications::MessageNotification.new(message)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param event [Symbol] Name of the custom event to trigger on formatters
|
96
|
+
# @param options [Hash] Hash of arguments to provide via `CustomNotification`
|
97
|
+
#
|
98
|
+
# Publish a custom event to supporting registered formatters.
|
99
|
+
# @see RSpec::Core::Notifications::CustomNotification
|
100
|
+
def publish(event, options={})
|
101
|
+
if RSPEC_NOTIFICATIONS.include? event
|
102
|
+
raise "RSpec::Core::Reporter#publish is intended for sending custom " \
|
103
|
+
"events not internal RSpec ones, please rename your custom event."
|
104
|
+
end
|
105
|
+
notify event, Notifications::CustomNotification.for(options)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @private
|
109
|
+
def example_group_started(group)
|
110
|
+
notify :example_group_started, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
# @private
|
114
|
+
def example_group_finished(group)
|
115
|
+
notify :example_group_finished, Notifications::GroupNotification.new(group) unless group.descendant_filtered_examples.empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
# @private
|
119
|
+
def example_started(example)
|
120
|
+
@examples << example
|
121
|
+
notify :example_started, Notifications::ExampleNotification.for(example)
|
122
|
+
end
|
123
|
+
|
124
|
+
# @private
|
125
|
+
def example_finished(example)
|
126
|
+
notify :example_finished, Notifications::ExampleNotification.for(example)
|
127
|
+
end
|
128
|
+
|
129
|
+
# @private
|
130
|
+
def example_passed(example)
|
131
|
+
notify :example_passed, Notifications::ExampleNotification.for(example)
|
132
|
+
end
|
133
|
+
|
134
|
+
# @private
|
135
|
+
def example_failed(example)
|
136
|
+
@failed_examples << example
|
137
|
+
notify :example_failed, Notifications::ExampleNotification.for(example)
|
138
|
+
end
|
139
|
+
|
140
|
+
# @private
|
141
|
+
def example_pending(example)
|
142
|
+
@pending_examples << example
|
143
|
+
notify :example_pending, Notifications::ExampleNotification.for(example)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @private
|
147
|
+
def deprecation(hash)
|
148
|
+
notify :deprecation, Notifications::DeprecationNotification.from_hash(hash)
|
149
|
+
end
|
150
|
+
|
151
|
+
# @private
|
152
|
+
# Provides a way to notify of an exception that is not tied to any
|
153
|
+
# particular example (such as an exception encountered in a :suite hook).
|
154
|
+
# Exceptions will be formatted the same way they normally are.
|
155
|
+
def notify_non_example_exception(exception, context_description)
|
156
|
+
@configuration.world.non_example_failure = true
|
157
|
+
@non_example_exception_count += 1
|
158
|
+
|
159
|
+
example = Example.new(AnonymousExampleGroup, context_description, {})
|
160
|
+
presenter = Formatters::ExceptionPresenter.new(exception, example, :indentation => 0)
|
161
|
+
message presenter.fully_formatted(nil)
|
162
|
+
end
|
163
|
+
|
164
|
+
# @private
|
165
|
+
def finish
|
166
|
+
close_after do
|
167
|
+
stop
|
168
|
+
notify :start_dump, Notifications::NullNotification
|
169
|
+
notify :dump_pending, Notifications::ExamplesNotification.new(self)
|
170
|
+
notify :dump_failures, Notifications::ExamplesNotification.new(self)
|
171
|
+
notify :deprecation_summary, Notifications::NullNotification
|
172
|
+
unless mute_profile_output?
|
173
|
+
notify :dump_profile, Notifications::ProfileNotification.new(@duration, @examples,
|
174
|
+
@configuration.profile_examples,
|
175
|
+
@profiler.example_groups)
|
176
|
+
end
|
177
|
+
notify :dump_summary, Notifications::SummaryNotification.new(@duration, @examples, @failed_examples,
|
178
|
+
@pending_examples, @load_time,
|
179
|
+
@non_example_exception_count)
|
180
|
+
notify :seed, Notifications::SeedNotification.new(@configuration.seed, seed_used?)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# @private
|
185
|
+
def close_after
|
186
|
+
yield
|
187
|
+
ensure
|
188
|
+
close
|
189
|
+
end
|
190
|
+
|
191
|
+
# @private
|
192
|
+
def stop
|
193
|
+
@duration = (RSpec::Core::Time.now - @start).to_f if @start
|
194
|
+
notify :stop, Notifications::ExamplesNotification.new(self)
|
195
|
+
end
|
196
|
+
|
197
|
+
# @private
|
198
|
+
def notify(event, notification)
|
199
|
+
ensure_listeners_ready
|
200
|
+
registered_listeners(event).each do |formatter|
|
201
|
+
formatter.__send__(event, notification)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# @private
|
206
|
+
def abort_with(msg, exit_status)
|
207
|
+
message(msg)
|
208
|
+
close
|
209
|
+
exit!(exit_status)
|
210
|
+
end
|
211
|
+
|
212
|
+
# @private
|
213
|
+
def fail_fast_limit_met?
|
214
|
+
return false unless (fail_fast = @configuration.fail_fast)
|
215
|
+
|
216
|
+
if fail_fast == true
|
217
|
+
@failed_examples.any?
|
218
|
+
else
|
219
|
+
fail_fast <= @failed_examples.size
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def ensure_listeners_ready
|
226
|
+
return if @setup
|
227
|
+
|
228
|
+
@setup_default.call
|
229
|
+
@profiler = Profiler.new
|
230
|
+
register_listener @profiler, *Profiler::NOTIFICATIONS
|
231
|
+
@setup = true
|
232
|
+
end
|
233
|
+
|
234
|
+
def close
|
235
|
+
notify :close, Notifications::NullNotification
|
236
|
+
end
|
237
|
+
|
238
|
+
def mute_profile_output?
|
239
|
+
# Don't print out profiled info if there are failures and `--fail-fast` is
|
240
|
+
# used, it just clutters the output.
|
241
|
+
!@configuration.profile_examples? || fail_fast_limit_met?
|
242
|
+
end
|
243
|
+
|
244
|
+
def seed_used?
|
245
|
+
@configuration.seed && @configuration.seed_used?
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# @private
|
250
|
+
# # Used in place of a {Reporter} for situations where we don't want reporting output.
|
251
|
+
class NullReporter
|
252
|
+
def self.method_missing(*)
|
253
|
+
# ignore
|
254
|
+
end
|
255
|
+
private_class_method :method_missing
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# This is borrowed (slightly modified) from Scott Taylor's
|
2
|
+
# project_path project:
|
3
|
+
# http://github.com/smtlaissezfaire/project_path
|
4
|
+
module RSpec
|
5
|
+
module Core
|
6
|
+
# @private
|
7
|
+
module RubyProject
|
8
|
+
def add_to_load_path(*dirs)
|
9
|
+
dirs.each { |dir| add_dir_to_load_path(File.join(root, dir)) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_dir_to_load_path(dir)
|
13
|
+
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
|
14
|
+
end
|
15
|
+
|
16
|
+
def root
|
17
|
+
@project_root ||= determine_root
|
18
|
+
end
|
19
|
+
|
20
|
+
def determine_root
|
21
|
+
find_first_parent_containing('spec') || '.'
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_first_parent_containing(dir)
|
25
|
+
ascend_until { |path| File.exist?(File.join(path, dir)) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def ascend_until
|
29
|
+
fs = File::SEPARATOR
|
30
|
+
escaped_slash = "\\#{fs}"
|
31
|
+
special = "_RSPEC_ESCAPED_SLASH_"
|
32
|
+
project_path = File.expand_path(".")
|
33
|
+
parts = project_path.gsub(escaped_slash, special).squeeze(fs).split(fs).map do |x|
|
34
|
+
x.gsub(special, escaped_slash)
|
35
|
+
end
|
36
|
+
|
37
|
+
until parts.empty?
|
38
|
+
path = parts.join(fs)
|
39
|
+
path = fs if path == ""
|
40
|
+
return path if yield(path)
|
41
|
+
parts.pop
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module_function :add_to_load_path
|
46
|
+
module_function :add_dir_to_load_path
|
47
|
+
module_function :root
|
48
|
+
module_function :determine_root
|
49
|
+
module_function :find_first_parent_containing
|
50
|
+
module_function :ascend_until
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
# Provides the main entry point to run a suite of RSpec examples.
|
4
|
+
class Runner
|
5
|
+
# @attr_reader
|
6
|
+
# @private
|
7
|
+
attr_reader :options, :configuration, :world
|
8
|
+
|
9
|
+
# Register an `at_exit` hook that runs the suite when the process exits.
|
10
|
+
#
|
11
|
+
# @note This is not generally needed. The `rspec` command takes care
|
12
|
+
# of running examples for you without involving an `at_exit`
|
13
|
+
# hook. This is only needed if you are running specs using
|
14
|
+
# the `ruby` command, and even then, the normal way to invoke
|
15
|
+
# this is by requiring `rspec/autorun`.
|
16
|
+
def self.autorun
|
17
|
+
if autorun_disabled?
|
18
|
+
RSpec.deprecate("Requiring `rspec/autorun` when running RSpec via the `rspec` command")
|
19
|
+
return
|
20
|
+
elsif installed_at_exit? || running_in_drb?
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
at_exit { perform_at_exit }
|
25
|
+
@installed_at_exit = true
|
26
|
+
end
|
27
|
+
|
28
|
+
# @private
|
29
|
+
def self.perform_at_exit
|
30
|
+
# Don't bother running any specs and just let the program terminate
|
31
|
+
# if we got here due to an unrescued exception (anything other than
|
32
|
+
# SystemExit, which is raised when somebody calls Kernel#exit).
|
33
|
+
return unless $!.nil? || $!.is_a?(SystemExit)
|
34
|
+
|
35
|
+
# We got here because either the end of the program was reached or
|
36
|
+
# somebody called Kernel#exit. Run the specs and then override any
|
37
|
+
# existing exit status with RSpec's exit status if any specs failed.
|
38
|
+
invoke
|
39
|
+
end
|
40
|
+
|
41
|
+
# Runs the suite of specs and exits the process with an appropriate exit
|
42
|
+
# code.
|
43
|
+
def self.invoke
|
44
|
+
disable_autorun!
|
45
|
+
status = run(ARGV, $stderr, $stdout).to_i
|
46
|
+
exit(status) if status != 0
|
47
|
+
end
|
48
|
+
|
49
|
+
# Run a suite of RSpec examples. Does not exit.
|
50
|
+
#
|
51
|
+
# This is used internally by RSpec to run a suite, but is available
|
52
|
+
# for use by any other automation tool.
|
53
|
+
#
|
54
|
+
# If you want to run this multiple times in the same process, and you
|
55
|
+
# want files like `spec_helper.rb` to be reloaded, be sure to load `load`
|
56
|
+
# instead of `require`.
|
57
|
+
#
|
58
|
+
# @param args [Array] command-line-supported arguments
|
59
|
+
# @param err [IO] error stream
|
60
|
+
# @param out [IO] output stream
|
61
|
+
# @return [Fixnum] exit status code. 0 if all specs passed,
|
62
|
+
# or the configured failure exit code (1 by default) if specs
|
63
|
+
# failed.
|
64
|
+
def self.run(args, err=$stderr, out=$stdout)
|
65
|
+
trap_interrupt
|
66
|
+
options = ConfigurationOptions.new(args)
|
67
|
+
|
68
|
+
if options.options[:runner]
|
69
|
+
options.options[:runner].call(options, err, out)
|
70
|
+
else
|
71
|
+
new(options).run(err, out)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(options, configuration=RSpec.configuration, world=RSpec.world)
|
76
|
+
@options = options
|
77
|
+
@configuration = configuration
|
78
|
+
@world = world
|
79
|
+
end
|
80
|
+
|
81
|
+
# Configures and runs a spec suite.
|
82
|
+
#
|
83
|
+
# @param err [IO] error stream
|
84
|
+
# @param out [IO] output stream
|
85
|
+
def run(err, out)
|
86
|
+
setup(err, out)
|
87
|
+
run_specs(@world.ordered_example_groups).tap do
|
88
|
+
persist_example_statuses
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Wires together the various configuration objects and state holders.
|
93
|
+
#
|
94
|
+
# @param err [IO] error stream
|
95
|
+
# @param out [IO] output stream
|
96
|
+
def setup(err, out)
|
97
|
+
configure(err, out)
|
98
|
+
@configuration.load_spec_files
|
99
|
+
@world.announce_filters
|
100
|
+
end
|
101
|
+
|
102
|
+
# Runs the provided example groups.
|
103
|
+
#
|
104
|
+
# @param example_groups [Array<RSpec::Core::ExampleGroup>] groups to run
|
105
|
+
# @return [Fixnum] exit status code. 0 if all specs passed,
|
106
|
+
# or the configured failure exit code (1 by default) if specs
|
107
|
+
# failed.
|
108
|
+
def run_specs(example_groups)
|
109
|
+
examples_count = @world.example_count(example_groups)
|
110
|
+
success = @configuration.reporter.report(examples_count) do |reporter|
|
111
|
+
@configuration.with_suite_hooks do
|
112
|
+
if examples_count == 0 && @configuration.fail_if_no_examples
|
113
|
+
return @configuration.failure_exit_code
|
114
|
+
end
|
115
|
+
|
116
|
+
example_groups.map { |g| g.run(reporter) }.all?
|
117
|
+
end
|
118
|
+
end && !@world.non_example_failure
|
119
|
+
|
120
|
+
success ? 0 : @configuration.failure_exit_code
|
121
|
+
end
|
122
|
+
|
123
|
+
# @private
|
124
|
+
def configure(err, out)
|
125
|
+
@configuration.error_stream = err
|
126
|
+
@configuration.output_stream = out if @configuration.output_stream == $stdout
|
127
|
+
@options.configure(@configuration)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @private
|
131
|
+
def self.disable_autorun!
|
132
|
+
@autorun_disabled = true
|
133
|
+
end
|
134
|
+
|
135
|
+
# @private
|
136
|
+
def self.autorun_disabled?
|
137
|
+
@autorun_disabled ||= false
|
138
|
+
end
|
139
|
+
|
140
|
+
# @private
|
141
|
+
def self.installed_at_exit?
|
142
|
+
@installed_at_exit ||= false
|
143
|
+
end
|
144
|
+
|
145
|
+
# @private
|
146
|
+
def self.running_in_drb?
|
147
|
+
return false unless defined?(DRb)
|
148
|
+
|
149
|
+
server = begin
|
150
|
+
DRb.current_server
|
151
|
+
rescue DRb::DRbServerNotFound
|
152
|
+
return false
|
153
|
+
end
|
154
|
+
|
155
|
+
return false unless server && server.alive?
|
156
|
+
|
157
|
+
require 'socket'
|
158
|
+
require 'uri'
|
159
|
+
|
160
|
+
local_ipv4 = begin
|
161
|
+
IPSocket.getaddress(Socket.gethostname)
|
162
|
+
rescue SocketError
|
163
|
+
return false
|
164
|
+
end
|
165
|
+
|
166
|
+
["127.0.0.1", "localhost", local_ipv4].any? { |addr| addr == URI(DRb.current_server.uri).host }
|
167
|
+
end
|
168
|
+
|
169
|
+
# @private
|
170
|
+
def self.trap_interrupt
|
171
|
+
trap('INT') { handle_interrupt }
|
172
|
+
end
|
173
|
+
|
174
|
+
# @private
|
175
|
+
def self.handle_interrupt
|
176
|
+
if RSpec.world.wants_to_quit
|
177
|
+
exit!(1)
|
178
|
+
else
|
179
|
+
RSpec.world.wants_to_quit = true
|
180
|
+
$stderr.puts "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit."
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def persist_example_statuses
|
187
|
+
return if @configuration.dry_run
|
188
|
+
return unless (path = @configuration.example_status_persistence_file_path)
|
189
|
+
|
190
|
+
ExampleStatusPersister.persist(@world.all_examples, path)
|
191
|
+
rescue SystemCallError => e
|
192
|
+
RSpec.warning "Could not write example statuses to #{path} (configured as " \
|
193
|
+
"`config.example_status_persistence_file_path`) due to a " \
|
194
|
+
"system error: #{e.inspect}. Please check that the config " \
|
195
|
+
"option is set to an accessible, valid file path", :call_site => nil
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|