mirror of
https://github.com/inspec/inspec
synced 2024-11-10 23:24:18 +00:00
Merge pull request #1442 from chef/ap/ortest-negate
Add negate! support for describe.one object
This commit is contained in:
commit
a4d230e5ea
3 changed files with 236 additions and 25 deletions
|
@ -5,15 +5,30 @@ module Inspec
|
|||
attr_reader :tests
|
||||
def initialize(tests)
|
||||
@tests = tests
|
||||
@negated = false
|
||||
end
|
||||
|
||||
def skip
|
||||
nil
|
||||
end
|
||||
|
||||
def negate!
|
||||
@negated = !@negated
|
||||
end
|
||||
|
||||
def to_ruby
|
||||
all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
|
||||
format("describe.one do\n %s\nend", all_tests)
|
||||
if @negated
|
||||
# We don't use the describe.one wrapper when negated because:
|
||||
# !(test1 || test2) same as (!test1 && !test2) where && is implicit in inspec
|
||||
all_tests = @tests.map { |test|
|
||||
test.negate!
|
||||
test
|
||||
}.map(&:to_ruby).join("\n")
|
||||
return all_tests
|
||||
else
|
||||
all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
|
||||
return format("describe.one do\n %s\nend", all_tests)
|
||||
end
|
||||
end
|
||||
|
||||
def to_hash
|
||||
|
|
|
@ -67,7 +67,7 @@ module Inspec
|
|||
itsy = xtra.nil? ? 'it' : 'its(' + xtra.to_s.inspect + ')'
|
||||
naughty = @negated ? '_not' : ''
|
||||
xpect = defined?(@expectation) ? expectation.inspect : ''
|
||||
if matcher == 'match'
|
||||
if @expectation.class == Regexp
|
||||
# without this, xpect values like / \/zones\// will not be parsed properly
|
||||
xpect = "(#{xpect})"
|
||||
elsif xpect != ''
|
||||
|
|
|
@ -6,60 +6,256 @@ require 'helper'
|
|||
require 'inspec/objects'
|
||||
|
||||
describe 'Objects' do
|
||||
describe 'Test' do
|
||||
describe 'Inspec::Test' do
|
||||
let(:obj) { Inspec::Test.new }
|
||||
it 'constructs a simple resource+argument' do
|
||||
obj.qualifier = [['resource'], ['arg']]
|
||||
obj.to_ruby.must_equal "
|
||||
obj.qualifier = [['resource'], ['version']]
|
||||
obj.matcher = 'cmp >='
|
||||
obj.expectation = '2.4.2'
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource do
|
||||
its(\"arg\") { should }
|
||||
its("version") { should cmp >= "2.4.2" }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple resource+argument with to_s' do
|
||||
obj.qualifier = [['resource'], ['to_s']]
|
||||
obj.to_ruby.must_equal "
|
||||
obj.matcher = 'cmp'
|
||||
obj.expectation = Regexp.new('^Desc.+$')
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource.to_s do
|
||||
it { should }
|
||||
it { should cmp(/^Desc.+$/) }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple resource+argument with to_i' do
|
||||
obj.qualifier = [['resource'], ['to_i']]
|
||||
obj.to_ruby.must_equal "
|
||||
obj.matcher = 'cmp >'
|
||||
obj.expectation = 3
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource.to_i do
|
||||
it { should }
|
||||
it { should cmp > 3 }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple resource+argument with array accessors' do
|
||||
obj.qualifier = [['resource'], ['name[2]']]
|
||||
obj.to_ruby.must_equal "
|
||||
obj.matcher = 'exist'
|
||||
obj.matcher = 'eq'
|
||||
obj.expectation = 'mytest'
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource.name[2] do
|
||||
it { should }
|
||||
it { should eq "mytest" }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple resource+argument with method calls' do
|
||||
obj.qualifier = [['resource'], ['hello', 'world']]
|
||||
obj.to_ruby.must_equal "
|
||||
describe resource.hello(\"world\") do
|
||||
it { should }
|
||||
obj.matcher = 'eq'
|
||||
obj.expectation = 'mytest'
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource.hello("world") do
|
||||
it { should eq "mytest" }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple resource+argument with method calls' do
|
||||
obj.qualifier = [['resource'], [:world]]
|
||||
obj.to_ruby.must_equal "
|
||||
obj.qualifier = [['resource'], [:mode]]
|
||||
obj.matcher = 'cmp'
|
||||
obj.expectation = '0755'
|
||||
obj.to_ruby.must_equal '
|
||||
describe resource do
|
||||
its(\"world\") { should }
|
||||
its("mode") { should cmp "0755" }
|
||||
end
|
||||
".strip
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a resource+argument block with method call, matcher and expectation' do
|
||||
obj.qualifier = [['command','ls /etc'], ['exit_status']]
|
||||
obj.matcher = 'eq'
|
||||
obj.expectation = 0
|
||||
|
||||
obj.to_ruby.must_equal '
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should eq 0 }
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a simple describe with static data, negated regex matcher and expectation' do
|
||||
obj.qualifier = [['"aaa"']]
|
||||
obj.matcher = 'match'
|
||||
obj.negate!
|
||||
obj.expectation = Regexp.new('^aa.*')
|
||||
|
||||
obj.to_ruby.must_equal '
|
||||
describe "aaa" do
|
||||
it { should_not match(/^aa.*/) }
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a resource+argument block without a property call' do
|
||||
obj.qualifier = [['service', 'avahi-daemon']]
|
||||
obj.qualifier.push(["info['properties']['UnitFileState']"])
|
||||
obj.expectation = "enabled"
|
||||
obj.matcher = 'eq'
|
||||
obj.to_ruby.must_equal '
|
||||
describe service("avahi-daemon").info[\'properties\'][\'UnitFileState\'] do
|
||||
it { should eq "enabled" }
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe 'Inspec::EachLoop, each_loop' do
|
||||
it 'constructs an each loop to match listening addresses' do
|
||||
loop_obj = Inspec::EachLoop.new
|
||||
loop_obj.qualifier = [['port', 25]]
|
||||
loop_obj.qualifier.push(['addresses'])
|
||||
obj = Inspec::Test.new
|
||||
obj.matcher = 'match'
|
||||
obj.negate!
|
||||
obj.expectation = '0.0.0.0'
|
||||
loop_obj.add_test(obj)
|
||||
loop_obj.to_ruby.must_equal '
|
||||
port(25).addresses.each do |entry|
|
||||
describe entry do
|
||||
it { should_not match "0.0.0.0" }
|
||||
end
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe 'Inspec::List' do
|
||||
it 'constructs a list filtering test' do
|
||||
list_obj = Inspec::List.new([['passwd']])
|
||||
list_obj.qualifier.push(["where { user =~ /^(?!root|sync|shutdown|halt).*$/ }"])
|
||||
|
||||
obj = Inspec::Test.new
|
||||
obj.qualifier = list_obj.qualifier
|
||||
obj.matcher = 'be_empty'
|
||||
obj.qualifier.push(['entries'])
|
||||
obj.negate!
|
||||
obj.to_ruby.must_equal '
|
||||
describe passwd.where { user =~ /^(?!root|sync|shutdown|halt).*$/ } do
|
||||
its("entries") { should_not be_empty }
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe 'Inspec::OrTest and Inspec::Control' do
|
||||
let(:obj1) do
|
||||
obj1 = Inspec::Test.new
|
||||
obj1.qualifier = [['command','ls /etc'], ['exit_status']]
|
||||
obj1.matcher = 'eq'
|
||||
obj1.expectation = 0
|
||||
obj1
|
||||
end
|
||||
let(:obj2) do
|
||||
obj2 = obj1.dup
|
||||
obj2.negate!
|
||||
obj2.expectation = 100
|
||||
obj2
|
||||
end
|
||||
|
||||
it 'constructs a simple describe.one block wrapping two tests' do
|
||||
or_obj = Inspec::OrTest.new([obj1,obj2])
|
||||
or_obj.to_ruby.must_equal '
|
||||
describe.one do
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should eq 0 }
|
||||
end
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should_not eq 100 }
|
||||
end
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'negates a describe.one block, wow!' do
|
||||
or_obj = Inspec::OrTest.new([obj1,obj2])
|
||||
or_obj.negate!
|
||||
or_obj.to_ruby.must_equal '
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should_not eq 0 }
|
||||
end
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should eq 100 }
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
|
||||
it 'constructs a control' do
|
||||
control = Inspec::Control.new
|
||||
control.add_test(obj1)
|
||||
control.id = 'sample.control.id'
|
||||
control.title = 'Sample Control Important Title'
|
||||
control.desc = 'The most critical control the world has ever seen'
|
||||
control.impact = 1.0
|
||||
control.to_ruby.must_equal '
|
||||
control "sample.control.id" do
|
||||
title "Sample Control Important Title"
|
||||
desc "The most critical control the world has ever seen"
|
||||
impact 1.0
|
||||
describe command("ls /etc") do
|
||||
its("exit_status") { should eq 0 }
|
||||
end
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Inspec::Variable' do
|
||||
it 'constructs a control with variable to instantiate a resource only once' do
|
||||
control = Inspec::Control.new
|
||||
variable = Inspec::Value.new([['command','which grep']])
|
||||
variable_id = variable.name_variable.to_s
|
||||
|
||||
obj1 = Inspec::Test.new
|
||||
obj1.variables.push(variable)
|
||||
obj1.qualifier.push([variable_id])
|
||||
obj1.qualifier.push(['exit_status'])
|
||||
obj1.matcher = 'eq'
|
||||
obj1.expectation = 0
|
||||
control.add_test(obj1)
|
||||
|
||||
obj2 = Inspec::Test.new
|
||||
obj2.qualifier.push([variable_id.to_s])
|
||||
obj2.qualifier.push(['stdout'])
|
||||
obj2.matcher = 'contain'
|
||||
obj2.expectation = 'grep'
|
||||
control.add_test(obj2)
|
||||
|
||||
control.id = 'variable.control.id'
|
||||
control.title = 'Variable Control Important Title'
|
||||
control.desc = 'The most variable control the world has ever seen'
|
||||
control.impact = 1.0
|
||||
control.to_ruby.must_equal '
|
||||
control "variable.control.id" do
|
||||
title "Variable Control Important Title"
|
||||
desc "The most variable control the world has ever seen"
|
||||
impact 1.0
|
||||
a = command("which grep")
|
||||
describe a do
|
||||
its("exit_status") { should eq 0 }
|
||||
end
|
||||
describe a do
|
||||
its("stdout") { should contain "grep" }
|
||||
end
|
||||
end
|
||||
'.strip
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue