diff --git a/lib/inspec/objects/input.rb b/lib/inspec/objects/input.rb index 784569c0b..c2aa4749d 100644 --- a/lib/inspec/objects/input.rb +++ b/lib/inspec/objects/input.rb @@ -26,9 +26,9 @@ module Inspec :provider, # Name of the plugin :priority, # Priority of this plugin for resolving conflicts. 1-100, higher numbers win. :value, # New value, if provided. - :file, # File containing the attribute-changing action, if known - :line, # Line in file containing the attribute-changing action, if known - :hit, # if action is :fetch, true if the remote source had the attribute + :file, # File containing the input-changing action, if known + :line, # Line in file containing the input-changing action, if known + :hit, # if action is :fetch, true if the remote source had the input ].freeze # Value has a special handler @@ -178,7 +178,7 @@ module Inspec end def diagnostic_string - "Attribute #{name}, with history:\n" + + "Input #{name}, with history:\n" + events.map(&:diagnostic_string).map { |line| " #{line}" }.join("\n") end @@ -218,7 +218,7 @@ module Inspec def make_creation_event(options) loc = options[:location] || probe_stack - Attribute::Event.new( + Input::Event.new( action: :create, provider: options[:provider], file: loc.path, @@ -227,9 +227,9 @@ module Inspec end def probe_stack - locs = caller_locations(2, 40) - # TODO: - refine huristics - locs[0] + frames = caller_locations(2, 40) + frames.reject! { |f| f.path && f.path.include?('/lib/inspec/') } + frames.first end # We can determine a value: @@ -240,7 +240,7 @@ module Inspec # Don't rely on this working; you really should be passing a proper Input::Event # with the context information you have. location = probe_stack - event = Attribute::Event.new( + event = Input::Event.new( action: :set, provider: :unknown, priority: options[:priority] || Inspec::Input::DEFAULT_PRIORITY_FOR_UNKNOWN_CALLER, @@ -302,7 +302,7 @@ module Inspec end def has_value? - !current_value.is_a? DEFAULT_ATTRIBUTE + !current_value.is_a? NO_VALUE_SET end #--------------------------------------------------------------------------# @@ -341,7 +341,7 @@ module Inspec #--------------------------------------------------------------------------# def to_s - "Attribute #{name} with #{current_value}" + "Input #{name} with #{current_value}" end #--------------------------------------------------------------------------# @@ -385,11 +385,11 @@ module Inspec end if invalid_type == true - error = Inspec::Attribute::ValidationError.new - error.attribute_name = @name - error.attribute_value = proposed_value - error.attribute_type = type_req - raise error, "Attribute '#{error.attribute_name}' with value '#{error.attribute_value}' does not validate to type '#{error.attribute_type}'." + error = Inspec::Input::ValidationError.new + error.input_name = @name + error.input_value = proposed_value + error.input_type = type_req + raise error, "Input '#{error.input_name}' with value '#{error.input_value}' does not validate to type '#{error.input_type}'." end end @@ -403,9 +403,9 @@ module Inspec } type_req = abbreviations[type_req] if abbreviations.key?(type_req) if !VALID_TYPES.include?(type_req) - error = Inspec::Attribute::TypeError.new - error.attribute_type = type_req - raise error, "Type '#{error.attribute_type}' is not a valid attribute type." + error = Inspec::Input::TypeError.new + error.input_type = type_req + raise error, "Type '#{error.input_type}' is not a valid input type." end @type = type_req end diff --git a/test/unit/inputs/events_test.rb b/test/unit/inputs/events_test.rb index e6ddddb16..7c1903a17 100644 --- a/test/unit/inputs/events_test.rb +++ b/test/unit/inputs/events_test.rb @@ -2,88 +2,115 @@ require 'helper' require 'inspec/objects/input' describe 'Inspec::Input and Events' do - let(:ipt { Inspec::Input.new('input') } + let(:ipt) { Inspec::Input.new('input') } + + #==============================================================# + # Create Event + #==============================================================# describe 'when creating an input' do it 'should have a creation event' do - creation_events = att.events.select { |e| e.action == :create } + creation_events = ipt.events.select { |e| e.action == :create } creation_events.wont_be_empty end it 'should only have a creation event if no value was provided' do - creation_events = att.events.select { |e| e.action == :create } + creation_events = ipt.events.select { |e| e.action == :create } creation_events.count.must_equal 1 end it 'should have a create and a set event if a value was provided' do - att = Inspec::Input.new('input', value: 42) - creation_events = att.events.select { |e| e.action == :create } + ipt = Inspec::Input.new('input', value: 42) + creation_events = ipt.events.select { |e| e.action == :create } creation_events.count.must_equal 1 - set_events = att.set_events + set_events = ipt.set_events set_events.count.must_equal 1 set_events.first.value.must_equal 42 end end + #==============================================================# + # Set Events + #==============================================================# describe 'when setting an input using value=' do it 'should add a set event' do - att.set_events.count.must_equal 0 - att.value = 42 - att.set_events.count.must_equal 1 + ipt.set_events.count.must_equal 0 + ipt.value = 42 + ipt.set_events.count.must_equal 1 end it 'should add one event for each value= operation' do - att.set_events.count.must_equal 0 - att.value = 1 - att.value = 2 - att.value = 3 - att.set_events.count.must_equal 3 + ipt.set_events.count.must_equal 0 + ipt.value = 1 + ipt.value = 2 + ipt.value = 3 + ipt.set_events.count.must_equal 3 end end + #==============================================================# + # Picking a Winner + #==============================================================# + # For more real-world testing of metadata vs --attrs vs inline, see # test/functional/inputs_test.rb describe 'priority voting' do it 'value() should return the correct value when there is just one set operation' do evt = Inspec::Input::Event.new(value: 42, priority: 25, action: :set) - att.update(event: evt) - att.value.must_equal 42 + ipt.update(event: evt) + ipt.value.must_equal 42 end it 'should return the highest priority regardless of order' do evt1 = Inspec::Input::Event.new(value: 1, priority: 25, action: :set) - att.update(event: evt1) + ipt.update(event: evt1) evt2 = Inspec::Input::Event.new(value: 2, priority: 35, action: :set) - att.update(event: evt2) + ipt.update(event: evt2) evt3 = Inspec::Input::Event.new(value: 3, priority: 15, action: :set) - att.update(event: evt3) + ipt.update(event: evt3) - att.value.must_equal 2 + ipt.value.must_equal 2 end it 'breaks ties using the last event of the highest priority' do evt1 = Inspec::Input::Event.new(value: 1, priority: 15, action: :set) - att.update(event: evt1) + ipt.update(event: evt1) evt2 = Inspec::Input::Event.new(value: 2, priority: 25, action: :set) - att.update(event: evt2) + ipt.update(event: evt2) evt3 = Inspec::Input::Event.new(value: 3, priority: 25, action: :set) - att.update(event: evt3) + ipt.update(event: evt3) - att.value.must_equal 3 + ipt.value.must_equal 3 end end - # TODO: test stack hueristics? + #==============================================================# + # Stack Hueristics + #==============================================================# + + describe 'when determining where the call came from' do + it 'should get the line and file correct in the constructor' do + expected_file = __FILE__ + expected_line = __LINE__; ipt = Inspec::Input.new('some_input') # Important to keep theses on one line + event = ipt.events.first + event.file.must_equal expected_file + event.line.must_equal expected_line + end + end + + #==============================================================# + # Diagnostics + #==============================================================# describe 'input diagnostics' do it 'should dump the events' do evt1 = Inspec::Input::Event.new(value: {a:1, b:2}, priority: 15, action: :set, provider: :unit_test) - att.update(event: evt1) + ipt.update(event: evt1) evt2 = Inspec::Input::Event.new(action: :fetch, provider: :alcubierre, hit: false) - att.update(event: evt2) + ipt.update(event: evt2) evt3 = Inspec::Input::Event.new(value: 12, action: :set, provider: :control_dsl, file: '/tmp/some/file.rb', line: 2) - att.update(event: evt3) + ipt.update(event: evt3) - text = att.diagnostic_string + text = ipt.diagnostic_string lines = text.split("\n") lines.count.must_equal 5 # 3 events above + 1 create + 1 input name line lines.shift # Not testing the inputs top line here diff --git a/test/unit/inputs/input_registry_test.rb b/test/unit/inputs/input_registry_test.rb index 1bbe8b5f7..4ee327060 100644 --- a/test/unit/inputs/input_registry_test.rb +++ b/test/unit/inputs/input_registry_test.rb @@ -77,13 +77,8 @@ describe Inspec::InputRegistry do before do Inspec::InputRegistry.any_instance.stubs(:validate_inputs_file_readability!) end - let(:profile) do - p = mock() - p.expects(:profile_name).returns('test_fixture_profile').at_least_once - p - end let(:seen_inputs) do - registry.bind_profile_inputs(profile, sources) + registry.bind_profile_inputs('test_fixture_profile', sources) inputs = registry.list_inputs_for_profile('test_fixture_profile') # Flatten Input objects down to their values inputs.keys.each { |input_name| inputs[input_name] = inputs[input_name].value } diff --git a/test/unit/inputs/input_test.rb b/test/unit/inputs/input_test.rb index 4accad9a8..64e0a3579 100644 --- a/test/unit/inputs/input_test.rb +++ b/test/unit/inputs/input_test.rb @@ -4,7 +4,8 @@ require 'helper' require 'inspec/objects/input' describe Inspec::Input do - let(:input) { Inspec::Input.new('test_input') } + let(:opts) { { } } + let(:input) { Inspec::Input.new('test_input', opts) } #==============================================================# # Metadata @@ -73,7 +74,9 @@ describe Inspec::Input do } ipt.to_hash.must_equal expected end - end #==============================================================# + end + + #==============================================================# # Setting Value - One Shot # (see events_test.rb for overwrite support) #==============================================================# @@ -90,7 +93,7 @@ describe Inspec::Input do end it 'the dummy value responds true to the legacy class checks' do - input.value.is_a?(Inspec::ATTRIBUTE::DEFAULT_ATTRIBUTE).must_equal true + input.value.is_a?(Inspec::Attribute::DEFAULT_ATTRIBUTE).must_equal true input.value.must_be_kind_of Inspec::Attribute::DEFAULT_ATTRIBUTE end diff --git a/test/unit/inputs/validation.rb b/test/unit/inputs/validation_test.rb similarity index 96% rename from test/unit/inputs/validation.rb rename to test/unit/inputs/validation_test.rb index 795dbddef..2a52c4079 100644 --- a/test/unit/inputs/validation.rb +++ b/test/unit/inputs/validation_test.rb @@ -39,7 +39,7 @@ describe 'type validation' do { 'string' => { good: 'a_string', bad: 123.3, norm: 'String' }, 'numeric' => { good: 123, bad: 'not a number', norm: 'Numeric' }, - 'regex' => { good: /\d+.+/, bad: '/(.+/', norm: 'Regexp' } + 'regex' => { good: /\d+.+/, bad: '/(.+/', norm: 'Regexp' }, 'array' => { good: [1, 2, 3], bad: { a: 1, b: 2, c: 3 }, norm: 'Array' }, 'hash' => { good: { a: 1, b: 2, c: 3 }, bad: 'i am not a hash', norm: 'Hash' }, 'boolean' => { good: true, bad: 'i am not a boolean', norm: 'Boolean' }, @@ -84,17 +84,17 @@ describe 'type validation' do describe 'validate type option' do it 'converts regex to Regexp' do opts[:type] = 'regex' - input.type_restriction.must_equal 'Regexp' + input.type.must_equal 'Regexp' end it 'returns the same value if there is nothing to clean' do opts[:type] = 'String' - input.type_restriction.must_equal 'String' + input.type.must_equal 'String' end it 'returns an error if a invalid type is sent' do opts[:type] = 'dressing' - ex = assert_raises(Inspec::Attribute::TypeError) { input } + ex = assert_raises(Inspec::Input::TypeError) { input } ex.message.must_match /Type 'Dressing' is not a valid input type./ end end