Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matcher for less-restrictive comparison #318

Merged
merged 8 commits into from Dec 11, 2015
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/inspec_and_friends.rst
Expand Up @@ -64,7 +64,7 @@ One of the key differences is that InSpec targets more user groups. It is optimi
insecure SSHv1 connections anymore.
"
describe sshd_config do
its('Protocol') { should eq('2') }
its('Protocol') { should cmp 2 }
end
end

Expand Down
39 changes: 23 additions & 16 deletions docs/resources.rst
Expand Up @@ -275,6 +275,13 @@ This |inspec resource| matches any keyword that is listed in the ``auditd.conf``

its('log_format') { should eq 'raw' }

Since all option names and values are case insensitive for ``auditd_conf``, we recommend to compare values with `cmp` instead of the `eq`.

.. code-block:: ruby

its('log_format') { should cmp 'raw' }
its('max_log_file') { should cmp 6 }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we establish cmp as the default matcher instead of eq for auditd_conf? Since the resource would be perfect for that! (i.e. just swap with eq + love the explanation!)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a great idea. I updated the docs.

Examples
-----------------------------------------------------
The following examples show how to use this InSpec audit resource.
Expand All @@ -284,20 +291,20 @@ The following examples show how to use this InSpec audit resource.
.. code-block:: ruby

describe auditd_conf do
its('log_file') { should eq '/full/path/to/file' }
its('log_format') { should eq 'raw' }
its('flush') { should eq 'none' }
its('freq') { should eq '1' }
its('num_logs') { should eq '0' }
its('max_log_file') { should eq '6' }
its('max_log_file_action') { should eq 'email' }
its('space_left') { should eq '2' }
its('action_mail_acct') { should eq 'root' }
its('space_left_action') { should eq 'email' }
its('admin_space_left') { should eq '1' }
its('admin_space_left_action') { should eq 'halt' }
its('disk_full_action') { should eq 'halt' }
its('disk_error_action') { should eq 'halt' }
its('log_file') { should cmp '/full/path/to/file' }
its('log_format') { should cmp 'raw' }
its('flush') { should cmp 'none' }
its('freq') { should cmp 1 }
its('num_logs') { should cmp 0 }
its('max_log_file') { should cmp 6 }
its('max_log_file_action') { should cmp 'email' }
its('space_left') { should cmp 2 }
its('action_mail_acct') { should cmp 'root' }
its('space_left_action') { should cmp 'email' }
its('admin_space_left') { should cmp 1 }
its('admin_space_left_action') { should cmp 'halt' }
its('disk_full_action') { should cmp 'halt' }
its('disk_error_action') { should cmp 'halt' }
end


Expand Down Expand Up @@ -3910,7 +3917,7 @@ The following examples show how to use this InSpec audit resource.
.. code-block:: ruby

describe sshd_config do
its('Protocol') { should eq '2' }
its('Protocol') { should cmp 2 }
end

**Test ciphers**
Expand All @@ -3926,7 +3933,7 @@ The following examples show how to use this InSpec audit resource.
.. code-block:: ruby

describe sshd_config do
its('Port') { should eq '22' }
its('Port') { should cmp 22 }
its('UsePAM') { should eq 'yes' }
its('ListenAddress') { should eq nil }
its('HostKey') { should eq [
Expand Down
40 changes: 40 additions & 0 deletions lib/matchers/matchers.rb
Expand Up @@ -219,3 +219,43 @@
fail "[UNSUPPORTED] `contain` matcher. Please use the following syntax `its('content') { should match('value') }`."
end
end

# This matcher implements a compare feature that cannot be covered by the default
# `eq` matcher
# You can use it in the following cases:
# - compare strings case-insensitive
# - you expect a number (strings will be converted if possible)
#
RSpec::Matchers.define :cmp do |expected|

def integer?(value)
return true if value =~ /\A\d+\Z/
false
end

def float?(value)
true if Float(value) rescue false
end

match do |actual|
# if actual and expected are strings
if actual.is_a?(String) && expected.is_a?(String)
actual.casecmp(expected) == 0
elsif expected.is_a?(Integer) && integer?(actual)
expected == actual.to_i
elsif expected.is_a?(Float) && float?(actual)
expected == actual.to_f
# fallback to equal
else
actual == expected
end
end

failure_message do |actual|
"\nexpected: #{expected}\n got: #{actual}\n\n(compared using `cmp` matcher)\n"
end

failure_message_when_negated do |actual|
"\nexpected: value != #{expected}\n got: #{actual}\n\n(compared using `cmp` matcher)\n"
end
end
19 changes: 19 additions & 0 deletions test/integration/test/integration/default/compare_matcher_spec.rb
@@ -0,0 +1,19 @@
# encoding: utf-8

# uses the `cmp` matcher instead of the eq matcher
describe sshd_config do
its('Port') { should eq '22' }
its('Port') { should_not eq 22 }

its('Port') { should cmp '22' }
its('Port') { should cmp 22 }
its('Port') { should cmp 22.0 }
its('Port') { should_not cmp 22.1 }

its('LogLevel') { should eq 'INFO' }
its('LogLevel') { should_not eq 'info'}

its('LogLevel') { should cmp 'INFO' }
its('LogLevel') { should cmp 'info' }
its('LogLevel') { should cmp 'InfO' }
end