Permalink
Browse files

formatters run better when $SAFE mode is on

Setting $SAFE=3 causes some file operations to raise a SecurityError. This patch allows you to run in SAFE mode without those SecurityErrors masking the real errors raised by the code under test and/or by RSpec matcher failures.

I extracted the SAFE setting/resetting logic into a helper method called "safely" since it's called from several places.
  • Loading branch information...
1 parent 9d8a6cc commit 576b82df34c60eb34662a96e56221e01cff35c6e @alexch alexch committed Apr 6, 2012
View
4 lib/rspec/core/formatters/base_formatter.rb
@@ -117,6 +117,8 @@ def configuration
def backtrace_line(line)
return nil if configuration.cleaned_from_backtrace?(line)
RSpec::Core::Metadata::relative_path(line)
+ rescue SecurityError
+ nil
end
def read_failed_line(exception, example)
@@ -131,6 +133,8 @@ def read_failed_line(exception, example)
else
"Unable to find #{file_path} to read failed line"
end
+ rescue SecurityError
+ "Unable to read failed line"
end
def find_failed_line(backtrace, path)
View
2 lib/rspec/core/metadata.rb
@@ -31,6 +31,8 @@ def self.relative_path(line)
line = line.sub(/\A([^:]+:\d+)$/, '\\1')
return nil if line == '-e:1'
line
+ rescue SecurityError
+ nil
end
# @private
View
16 spec/rspec/core/formatters/base_formatter_spec.rb
@@ -16,6 +16,12 @@
formatter.__send__(:backtrace_line, original_line)
original_line.should eq(File.expand_path(__FILE__))
end
+
+ it "deals gracefully with a security error" do
+ safely do
+ formatter.__send__(:backtrace_line, __FILE__).should be_nil
+ end
+ end
end
describe "read_failed_line" do
@@ -32,6 +38,16 @@
}.should_not raise_error
end
+ it "deals gracefully with a security error" do
+ exception = mock(:Exception, :backtrace => [ "#{__FILE__}:#{__LINE__}"])
+ example = mock(:Example, :file_path => __FILE__)
+ safely do
+ lambda {
+ formatter.send(:read_failed_line, exception, example).should == "Unable to read failed line"
+ }.should_not raise_error
+ end
+ end
+
context "when String alias to_int to_i" do
before do
String.class_eval do
View
9 spec/rspec/core/formatters/snippet_extractor_spec.rb
@@ -12,6 +12,15 @@ module Formatters
it "falls back on a default message when it doesn't find the file" do
RSpec::Core::Formatters::SnippetExtractor.new.lines_around("blech", 8).should eq("# Couldn't get snippet for blech")
end
+
+ it "falls back on a default message when it gets a security error" do
+ Thread.new {
+ $SAFE = 3
+ $SAFE.should == 3
+ RSpec::Core::Formatters::SnippetExtractor.new.lines_around("blech", 8).should eq("# Couldn't get snippet for blech")
+ }.run
+ $SAFE.should == 0
+ end
end
end
end
View
20 spec/rspec/core/metadata_spec.rb
@@ -4,6 +4,26 @@ module RSpec
module Core
describe Metadata do
+ describe '.relative_path' do
+ let(:here) { File.expand_path(".") }
+ it "transforms absolute paths to relative paths" do
+ Metadata.relative_path(here).should == "."
+ end
+ it "transforms absolute paths to relative paths anywhere in its argument" do
+ Metadata.relative_path("foo #{here} bar").should == "foo . bar"
+ end
+ it "returns nil if passed an unparseable file:line combo" do
+ Metadata.relative_path("-e:1").should be_nil
+ end
+ # I have no idea what line = line.sub(/\A([^:]+:\d+)$/, '\\1') is supposed to do
+ it "gracefully returns nil if run in a secure thread" do
+ safely do
+ Metadata.relative_path(".").should be_nil
+ end
+ end
+
+ end
+
describe "#process" do
Metadata::RESERVED_KEYS.each do |key|
it "prohibits :#{key} as a hash key" do
View
9 spec/support/helper_methods.rb
@@ -2,4 +2,13 @@ module RSpecHelpers
def relative_path(path)
RSpec::Core::Metadata.relative_path(path)
end
+
+ def safely
+ Thread.new do
+ $SAFE = 3
+ yield
+ end.join
+ $SAFE.should == 0 # just to be safe ;-)
+ end
+
end

0 comments on commit 576b82d

Please sign in to comment.