summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortyler-ball <tyleraball@gmail.com>2014-12-04 18:19:03 -0800
committertyler-ball <tyleraball@gmail.com>2014-12-17 18:52:24 -0800
commit66727a7a3e8e986ca3499e0e8693c332ab309247 (patch)
tree9109e4c56457ecd9202ab85fb692c3eb2222d0a1
parentfc161e7f145d84d558c40a3e562312100dbf44a4 (diff)
downloadchef-66727a7a3e8e986ca3499e0e8693c332ab309247.tar.gz
Adding example of sandboxing
-rw-r--r--spec/functional/audit/runner_spec.rb80
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/audit_helper.rb61
3 files changed, 141 insertions, 2 deletions
diff --git a/spec/functional/audit/runner_spec.rb b/spec/functional/audit/runner_spec.rb
new file mode 100644
index 0000000000..cb998d66aa
--- /dev/null
+++ b/spec/functional/audit/runner_spec.rb
@@ -0,0 +1,80 @@
+require 'spec_helper'
+require 'spec/support/audit_helper'
+require 'chef/audit/runner'
+require 'chef/audit/audit_event_proxy'
+require 'chef/audit/rspec_formatter'
+require 'chef/run_context'
+require 'pry'
+
+##
+# This functional test ensures that our runner can be setup to not interfere with existing RSpec
+# configuration and world objects. When normally running Chef, there is only 1 RSpec instance
+# so this isn't needed. In unit testing the Runner should be mocked appropriately.
+
+describe Chef::Audit::Runner do
+
+ let(:events) { double("events") }
+ let(:run_context) { instance_double(Chef::RunContext) }
+ let(:runner) { Chef::Audit::Runner.new(run_context) }
+
+ # This is the first thing that gets called, and determines how the examples are ran
+ around(:each) do |ex|
+ Sandboxing.sandboxed { ex.run }
+ end
+
+ describe "#configure_rspec" do
+
+ it "adds the necessary formatters" do
+ # We don't expect the events to receive any calls because the AuditEventProxy that was registered from `runner.run`
+ # only existed in the Configuration object that got removed by the sandboxing
+ #expect(events).to receive(:control_example_success)
+
+ expect(RSpec.configuration.formatters.size).to eq(0)
+ expect(run_context).to receive(:events).and_return(events)
+ expect(Chef::Audit::AuditEventProxy).to receive(:events=)
+
+ runner.send(:add_formatters)
+
+ expect(RSpec.configuration.formatters.size).to eq(2)
+ expect(RSpec.configuration.formatters[0]).to be_instance_of(Chef::Audit::AuditEventProxy)
+ expect(RSpec.configuration.formatters[1]).to be_instance_of(Chef::Audit::RspecFormatter)
+
+ end
+
+ end
+
+ # When running these, because we are not mocking out any of the formatters we expect to get dual output on the
+ # command line
+ describe "#run" do
+
+ before do
+ expect(run_context).to receive(:events).and_return(events)
+ end
+
+ it "Correctly runs an empty controls block" do
+ expect(run_context).to receive(:audits).and_return({})
+ runner.run
+ end
+
+ it "Correctly runs a single successful control" do
+ should_pass = lambda do
+ it "should pass" do
+ expect(2 - 2).to eq(0)
+ end
+ end
+
+ expect(run_context).to receive(:audits).and_return({
+ "should pass" => {:args => [], :block => should_pass}
+ })
+
+ # TODO capture the output and verify it
+ runner.run
+ end
+
+ it "Correctly runs a single failing control", :pending do
+
+ end
+
+ end
+
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9f8cc754b7..995be5060b 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -169,8 +169,6 @@ RSpec.configure do |config|
config.before(:each) do
Chef::Config.reset
-
- allow_any_instance_of(Chef::Audit::Runner).to receive(:run).and_return(true)
end
config.before(:suite) do
diff --git a/spec/support/audit_helper.rb b/spec/support/audit_helper.rb
new file mode 100644
index 0000000000..d897de0453
--- /dev/null
+++ b/spec/support/audit_helper.rb
@@ -0,0 +1,61 @@
+# This code comes from https://github.com/rspec/rspec-core/blob/master/spec/spec_helper.rb and
+# https://github.com/rspec/rspec-core/blob/master/spec/support/sandboxing.rb
+
+# To leverage the sandboxing use an `around` block:
+# around(:each) do |ex|
+# Sandboxing.sandboxed { ex.run }
+# end
+
+# rspec-core did not include a license on Github
+
+# This is necessary, otherwise
+class << RSpec
+ attr_writer :configuration, :world
+end
+
+class NullObject
+ private
+ def method_missing(method, *args, &block)
+ # ignore
+ end
+end
+
+module Sandboxing
+ def self.sandboxed(&block)
+ orig_load_path = $LOAD_PATH.dup
+ orig_config = RSpec.configuration
+ orig_world = RSpec.world
+ orig_example = RSpec.current_example
+ new_config = RSpec::Core::Configuration.new
+ new_config.expose_dsl_globally = false
+ new_config.expecting_with_rspec = true
+ new_world = RSpec::Core::World.new(new_config)
+ RSpec.configuration = new_config
+ RSpec.world = new_world
+ object = Object.new
+ object.extend(RSpec::Core::SharedExampleGroup)
+
+ (class << RSpec::Core::ExampleGroup; self; end).class_exec do
+ alias_method :orig_run, :run
+ def run(reporter=nil)
+ RSpec.current_example = nil
+ orig_run(reporter || NullObject.new)
+ end
+ end
+
+ RSpec::Mocks.with_temporary_scope do
+ object.instance_exec(&block)
+ end
+ ensure
+ (class << RSpec::Core::ExampleGroup; self; end).class_exec do
+ remove_method :run
+ alias_method :run, :orig_run
+ remove_method :orig_run
+ end
+
+ RSpec.configuration = orig_config
+ RSpec.world = orig_world
+ RSpec.current_example = orig_example
+ $LOAD_PATH.replace(orig_load_path)
+ end
+end