Skip to content

Commit 5b458cc

Browse files
committed
Provide friendly warnings when we can’t access status file.
1 parent 3f2cbdc commit 5b458cc

File tree

4 files changed

+91
-9
lines changed

4 files changed

+91
-9
lines changed

lib/rspec/core/configuration.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,17 @@ def files_to_run
841841
def last_run_statuses
842842
@last_run_statuses ||= Hash.new(UNKNOWN_STATUS).tap do |statuses|
843843
if (path = example_status_persistence_file_path)
844-
ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example|
845-
hash[example.fetch(:example_id)] = example.fetch(:status)
846-
hash
844+
begin
845+
ExampleStatusPersister.load_from(path).inject(statuses) do |hash, example|
846+
hash[example.fetch(:example_id)] = example.fetch(:status)
847+
hash
848+
end
849+
rescue SystemCallError => e
850+
RSpec.warning "Could not read from #{path.inspect} (configured as " \
851+
"`config.example_status_persistence_file_path`) due " \
852+
"to a system error: #{e.inspect}. Please check that " \
853+
"the config option is set to an accessible, valid " \
854+
"file path", :call_site => nil
847855
end
848856
end
849857
end

lib/rspec/core/runner.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,14 @@ def run_specs(example_groups)
117117
private
118118

119119
def persist_example_statuses
120-
return unless @configuration.example_status_persistence_file_path
121-
122-
ExampleStatusPersister.persist(
123-
@world.all_examples,
124-
@configuration.example_status_persistence_file_path
125-
)
120+
return unless (path = @configuration.example_status_persistence_file_path)
121+
122+
ExampleStatusPersister.persist(@world.all_examples, path)
123+
rescue SystemCallError => e
124+
RSpec.warning "Could not write example statuses to #{path} (configured as " \
125+
"`config.example_status_persistence_file_path`) due to a " \
126+
"system error: #{e.inspect}. Please check that the config " \
127+
"option is set to an accessible, valid file path", :call_site => nil
126128
end
127129

128130
# @private
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
require 'support/aruba_support'
2+
3+
RSpec.describe 'Persistence failures' do
4+
include_context "aruba support"
5+
before { clean_current_dir }
6+
7+
context "when `config.example_status_persistence_file_path` is configured" do
8+
context "to an invalid file path (e.g. spec/spec_helper.rb/examples.txt)" do
9+
before do
10+
write_file_formatted "spec/1_spec.rb", "
11+
RSpec.configure do |c|
12+
c.example_status_persistence_file_path = 'spec/1_spec.rb/examples.txt'
13+
end
14+
RSpec.describe { example { } }
15+
"
16+
end
17+
18+
it 'emits a helpful warning to the user, indicating we cannot write to it, and still runs the spec suite' do
19+
run_command "spec/1_spec.rb"
20+
21+
expect(last_cmd_stderr).to include(
22+
"WARNING: Could not write",
23+
"spec/1_spec.rb/examples.txt",
24+
"config.example_status_persistence_file_path",
25+
"Errno:"
26+
)
27+
expect(last_cmd_stdout).to include("1 example")
28+
end
29+
end
30+
31+
context "to a file path for which we lack permissions" do
32+
before do
33+
write_file_formatted "spec/1_spec.rb", "
34+
RSpec.configure do |c|
35+
c.example_status_persistence_file_path = 'spec/examples.txt'
36+
end
37+
RSpec.describe { example { } }
38+
"
39+
40+
write_file_formatted "spec/examples.txt", ""
41+
in_current_dir do
42+
FileUtils.chmod 0000, "spec/examples.txt"
43+
end
44+
end
45+
46+
47+
it 'emits a helpful warning to the user, indicating we cannot read from it, and still runs the spec suite' do
48+
run_command "spec/1_spec.rb"
49+
50+
expected_snippets = [
51+
"WARNING: Could not read",
52+
"spec/examples.txt",
53+
"config.example_status_persistence_file_path",
54+
"Errno:"
55+
]
56+
57+
if RSpec::Support::OS.windows?
58+
# Not sure why, but on windows it doesn't trigger the read error, it
59+
# triggers a write error instead. The important thing is that whatever
60+
# system error occurs is reported accurately.
61+
expected_snippets[0] = "WARNING: Could not write"
62+
end
63+
64+
expect(last_cmd_stderr).to include(*expected_snippets)
65+
expect(last_cmd_stdout).to include("1 example")
66+
end
67+
end
68+
end
69+
end

spec/support/aruba_support.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ def run_command(cmd)
1717

1818
temp_stdout = StringIO.new
1919
temp_stderr = StringIO.new
20+
21+
# So that `RSpec.warning` will go to temp_stderr.
22+
allow(::Kernel).to receive(:warn) { |msg| temp_stderr.puts(msg) }
2023
cmd_parts = Shellwords.split(cmd)
2124

2225
handle_current_dir_change do

0 commit comments

Comments
 (0)