diff options
author | tyler-ball <tyleraball@gmail.com> | 2014-12-04 18:19:03 -0800 |
---|---|---|
committer | tyler-ball <tyleraball@gmail.com> | 2014-12-17 18:52:24 -0800 |
commit | 66727a7a3e8e986ca3499e0e8693c332ab309247 (patch) | |
tree | 9109e4c56457ecd9202ab85fb692c3eb2222d0a1 | |
parent | fc161e7f145d84d558c40a3e562312100dbf44a4 (diff) | |
download | chef-66727a7a3e8e986ca3499e0e8693c332ab309247.tar.gz |
Adding example of sandboxing
-rw-r--r-- | spec/functional/audit/runner_spec.rb | 80 | ||||
-rw-r--r-- | spec/spec_helper.rb | 2 | ||||
-rw-r--r-- | spec/support/audit_helper.rb | 61 |
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 |