puppet-lint-halyard 1.1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +20 -0
  6. data/README.md +210 -0
  7. data/Rakefile +14 -0
  8. data/bin/puppet-lint +7 -0
  9. data/lib/puppet-lint.rb +214 -0
  10. data/lib/puppet-lint/bin.rb +79 -0
  11. data/lib/puppet-lint/checkplugin.rb +176 -0
  12. data/lib/puppet-lint/checks.rb +91 -0
  13. data/lib/puppet-lint/configuration.rb +153 -0
  14. data/lib/puppet-lint/data.rb +521 -0
  15. data/lib/puppet-lint/lexer.rb +373 -0
  16. data/lib/puppet-lint/lexer/token.rb +101 -0
  17. data/lib/puppet-lint/monkeypatches.rb +2 -0
  18. data/lib/puppet-lint/monkeypatches/string_percent.rb +52 -0
  19. data/lib/puppet-lint/monkeypatches/string_prepend.rb +13 -0
  20. data/lib/puppet-lint/optparser.rb +118 -0
  21. data/lib/puppet-lint/plugins.rb +74 -0
  22. data/lib/puppet-lint/plugins/check_classes.rb +285 -0
  23. data/lib/puppet-lint/plugins/check_comments.rb +55 -0
  24. data/lib/puppet-lint/plugins/check_conditionals.rb +65 -0
  25. data/lib/puppet-lint/plugins/check_documentation.rb +31 -0
  26. data/lib/puppet-lint/plugins/check_nodes.rb +29 -0
  27. data/lib/puppet-lint/plugins/check_resources.rb +194 -0
  28. data/lib/puppet-lint/plugins/check_strings.rb +174 -0
  29. data/lib/puppet-lint/plugins/check_variables.rb +19 -0
  30. data/lib/puppet-lint/plugins/check_whitespace.rb +170 -0
  31. data/lib/puppet-lint/tasks/puppet-lint.rb +91 -0
  32. data/lib/puppet-lint/version.rb +3 -0
  33. data/puppet-lint.gemspec +24 -0
  34. data/spec/fixtures/test/manifests/fail.pp +2 -0
  35. data/spec/fixtures/test/manifests/ignore.pp +1 -0
  36. data/spec/fixtures/test/manifests/ignore_multiple_block.pp +6 -0
  37. data/spec/fixtures/test/manifests/ignore_multiple_line.pp +2 -0
  38. data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
  39. data/spec/fixtures/test/manifests/init.pp +3 -0
  40. data/spec/fixtures/test/manifests/malformed.pp +1 -0
  41. data/spec/fixtures/test/manifests/url_interpolation.pp +12 -0
  42. data/spec/fixtures/test/manifests/warning.pp +2 -0
  43. data/spec/puppet-lint/bin_spec.rb +326 -0
  44. data/spec/puppet-lint/configuration_spec.rb +56 -0
  45. data/spec/puppet-lint/ignore_overrides_spec.rb +109 -0
  46. data/spec/puppet-lint/lexer/token_spec.rb +18 -0
  47. data/spec/puppet-lint/lexer_spec.rb +783 -0
  48. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +105 -0
  49. data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +35 -0
  50. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +33 -0
  51. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
  52. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +76 -0
  53. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +73 -0
  54. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +25 -0
  55. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +196 -0
  56. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +45 -0
  57. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +84 -0
  58. data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +98 -0
  59. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +36 -0
  60. data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +52 -0
  61. data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +146 -0
  62. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +100 -0
  63. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +55 -0
  64. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +89 -0
  65. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +113 -0
  66. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +45 -0
  67. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +216 -0
  68. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +199 -0
  69. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +114 -0
  70. data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +62 -0
  71. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +129 -0
  72. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +17 -0
  73. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +73 -0
  74. data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +37 -0
  75. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +21 -0
  76. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +54 -0
  77. data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +524 -0
  78. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +45 -0
  79. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +101 -0
  80. data/spec/puppet-lint_spec.rb +20 -0
  81. data/spec/spec_helper.rb +129 -0
  82. metadata +229 -0
@@ -0,0 +1,19 @@
1
+ # Public: Test the manifest tokens for variables that contain a dash and
2
+ # record a warning for each instance found.
3
+ PuppetLint.new_check(:variable_contains_dash) do
4
+ VARIABLE_TYPES = Set[:VARIABLE, :UNENC_VARIABLE]
5
+
6
+ def check
7
+ tokens.select { |r|
8
+ VARIABLE_TYPES.include? r.type
9
+ }.each do |token|
10
+ if token.value.gsub(/\[.+?\]/, '').match(/-/)
11
+ notify :warning, {
12
+ :message => 'variable contains a dash',
13
+ :line => token.line,
14
+ :column => token.column,
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,170 @@
1
+ # Public: Check the raw manifest string for lines containing hard tab
2
+ # characters and record an error for each instance found.
3
+ PuppetLint.new_check(:hard_tabs) do
4
+ WHITESPACE_TYPES = Set[:INDENT, :WHITESPACE]
5
+
6
+ def check
7
+ tokens.select { |r|
8
+ WHITESPACE_TYPES.include?(r.type) && r.value.include?("\t")
9
+ }.each do |token|
10
+ notify :error, {
11
+ :message => 'tab character found',
12
+ :line => token.line,
13
+ :column => token.column,
14
+ :token => token,
15
+ }
16
+ end
17
+ end
18
+
19
+ def fix(problem)
20
+ problem[:token].value.gsub!("\t", ' ')
21
+ end
22
+ end
23
+
24
+ # Public: Check the manifest tokens for lines ending with whitespace and record
25
+ # an error for each instance found.
26
+ PuppetLint.new_check(:trailing_whitespace) do
27
+ def check
28
+ tokens.select { |token|
29
+ [:WHITESPACE, :INDENT].include?(token.type)
30
+ }.select { |token|
31
+ token.next_token.nil? || token.next_token.type == :NEWLINE
32
+ }.each do |token|
33
+ notify :error, {
34
+ :message => 'trailing whitespace found',
35
+ :line => token.line,
36
+ :column => token.column,
37
+ :token => token,
38
+ }
39
+ end
40
+ end
41
+
42
+ def fix(problem)
43
+ prev_token = problem[:token].prev_token
44
+ next_token = problem[:token].next_token
45
+ prev_token.next_token = next_token
46
+ next_token.prev_token = prev_token unless next_token.nil?
47
+ tokens.delete(problem[:token])
48
+ end
49
+ end
50
+
51
+ # Public: Test the raw manifest string for lines containing more than 80
52
+ # characters and record a warning for each instance found. The only exceptions
53
+ # to this rule are lines containing URLs and template() calls which would hurt
54
+ # readability if split.
55
+ PuppetLint.new_check(:'80chars') do
56
+ def check
57
+ manifest_lines.each_with_index do |line, idx|
58
+ unless line =~ /:\/\// || line =~ /template\(/
59
+ if line.scan(/./mu).size > 80
60
+ notify :warning, {
61
+ :message => 'line has more than 80 characters',
62
+ :line => idx + 1,
63
+ :column => 80,
64
+ }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ # Public: Check the manifest tokens for any indentation not using 2 space soft
72
+ # tabs and record an error for each instance found.
73
+ PuppetLint.new_check(:'2sp_soft_tabs') do
74
+ def check
75
+ tokens.select { |r|
76
+ r.type == :INDENT
77
+ }.reject { |r|
78
+ r.value.length % 2 == 0
79
+ }.each do |token|
80
+ notify :error, {
81
+ :message => 'two-space soft tabs not used',
82
+ :line => token.line,
83
+ :column => token.column,
84
+ }
85
+ end
86
+ end
87
+ end
88
+
89
+ # Public: Check the manifest tokens for any arrows (=>) in a grouping ({}) that
90
+ # are not aligned with other arrows in that grouping.
91
+ PuppetLint.new_check(:arrow_alignment) do
92
+ COMMENT_TYPES = Set[:COMMENT, :SLASH_COMMENT, :MLCOMMENT]
93
+
94
+ def check
95
+ resource_indexes.each do |res_idx|
96
+ indent_depth = [0]
97
+ indent_depth_idx = 0
98
+ level_tokens = []
99
+ resource_tokens = res_idx[:tokens]
100
+ resource_tokens.reject! do |token|
101
+ COMMENT_TYPES.include? token.type
102
+ end
103
+
104
+ # If this is a single line resource, skip it
105
+ first_arrow = resource_tokens.index { |r| r.type == :FARROW }
106
+ last_arrow = resource_tokens.rindex { |r| r.type == :FARROW }
107
+ next if first_arrow.nil?
108
+ next if last_arrow.nil?
109
+ next unless resource_tokens[first_arrow..last_arrow].any? { |r| r.type == :NEWLINE }
110
+
111
+ resource_tokens.each_with_index do |token, idx|
112
+ if token.type == :FARROW
113
+ (level_tokens[indent_depth_idx] ||= []) << token
114
+ prev_indent_token = resource_tokens[0..idx].rindex { |t| t.type == :INDENT }
115
+ indent_token_length = prev_indent_token.nil? ? 0 : resource_tokens[prev_indent_token].to_manifest.length
116
+ indent_length = indent_token_length + token.prev_code_token.to_manifest.length + 2
117
+
118
+ if indent_depth[indent_depth_idx] < indent_length
119
+ indent_depth[indent_depth_idx] = indent_length
120
+ end
121
+
122
+ elsif token.type == :LBRACE
123
+ indent_depth_idx += 1
124
+ indent_depth << 0
125
+ level_tokens[indent_depth_idx] ||= []
126
+ elsif token.type == :RBRACE
127
+ level_tokens[indent_depth_idx].each do |arrow_tok|
128
+ unless arrow_tok.column == indent_depth[indent_depth_idx] || level_tokens[indent_depth_idx].size == 1
129
+ arrows_on_line = level_tokens[indent_depth_idx].select { |t| t.line == arrow_tok.line }
130
+ notify :warning, {
131
+ :message => 'indentation of => is not properly aligned',
132
+ :line => arrow_tok.line,
133
+ :column => arrow_tok.column,
134
+ :token => arrow_tok,
135
+ :indent_depth => indent_depth[indent_depth_idx],
136
+ :newline => !(arrows_on_line.index(arrow_tok) == 0),
137
+ :newline_indent => arrows_on_line.first.prev_code_token.prev_token.value,
138
+ }
139
+ end
140
+ end
141
+ indent_depth[indent_depth_idx] = 0
142
+ level_tokens[indent_depth_idx].clear
143
+ indent_depth_idx -= 1
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ def fix(problem)
150
+ new_ws_len = (problem[:indent_depth] - (problem[:newline_indent].length + problem[:token].prev_code_token.to_manifest.length + 1))
151
+ new_ws = ' ' * new_ws_len
152
+ if problem[:newline]
153
+ index = tokens.index(problem[:token].prev_code_token.prev_token)
154
+
155
+ #insert newline
156
+ tokens.insert(index, PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0))
157
+
158
+ # indent the parameter to the correct depth
159
+ problem[:token].prev_code_token.prev_token.type = :INDENT
160
+ problem[:token].prev_code_token.prev_token.value = problem[:newline_indent].dup
161
+ end
162
+
163
+ if problem[:token].prev_token.type == :WHITESPACE
164
+ problem[:token].prev_token.value = new_ws
165
+ else
166
+ index = tokens.index(problem[:token].prev_token)
167
+ tokens.insert(index + 1, PuppetLint::Lexer::Token.new(:WHITESPACE, new_ws, 0, 0))
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,91 @@
1
+ require 'puppet-lint'
2
+ require 'puppet-lint/optparser'
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+
6
+ class PuppetLint
7
+ # Public: A Rake task that can be loaded and used with everything you need.
8
+ #
9
+ # Examples
10
+ #
11
+ # require 'puppet-lint'
12
+ # PuppetLint::RakeTask.new
13
+ class RakeTask < ::Rake::TaskLib
14
+ include ::Rake::DSL if defined?(::Rake::DSL)
15
+
16
+ DEFAULT_PATTERN = '**/*.pp'
17
+
18
+ attr_accessor :name
19
+ attr_accessor :pattern
20
+ attr_accessor :ignore_paths
21
+ attr_accessor :with_filename
22
+ attr_accessor :disable_checks
23
+ attr_accessor :fail_on_warnings
24
+ attr_accessor :error_level
25
+ attr_accessor :log_format
26
+ attr_accessor :with_context
27
+ attr_accessor :fix
28
+ attr_accessor :show_ignored
29
+ attr_accessor :relative
30
+
31
+ # Public: Initialise a new PuppetLint::RakeTask.
32
+ #
33
+ # args - Not used.
34
+ #
35
+ # Example
36
+ #
37
+ # PuppetLint::RakeTask.new
38
+ def initialize(*args, &task_block)
39
+ @name = args.shift || :lint
40
+ @pattern = DEFAULT_PATTERN
41
+ @with_filename = true
42
+ @disable_checks = []
43
+ @ignore_paths = []
44
+
45
+ define(args, &task_block)
46
+ end
47
+
48
+ def define(args, &task_block)
49
+ desc 'Run puppet-lint'
50
+
51
+ task_block.call(*[self, args].slice(0, task_block.arity)) if task_block
52
+
53
+ # clear any (auto-)pre-existing task
54
+ Rake::Task[@name].clear if Rake::Task.task_defined?(@name)
55
+ task @name do
56
+ PuppetLint::OptParser.build
57
+
58
+ Array(@disable_checks).each do |check|
59
+ PuppetLint.configuration.send("disable_#{check}")
60
+ end
61
+
62
+ %w{with_filename fail_on_warnings error_level log_format with_context fix show_ignored relative}.each do |config|
63
+ value = instance_variable_get("@#{config}")
64
+ PuppetLint.configuration.send("#{config}=".to_sym, value) unless value.nil?
65
+ end
66
+
67
+ if PuppetLint.configuration.ignore_paths
68
+ @ignore_paths = PuppetLint.configuration.ignore_paths
69
+ end
70
+
71
+ RakeFileUtils.send(:verbose, true) do
72
+ linter = PuppetLint.new
73
+ matched_files = FileList[@pattern]
74
+
75
+ matched_files = matched_files.exclude(*@ignore_paths)
76
+
77
+ matched_files.to_a.each do |puppet_file|
78
+ linter.file = puppet_file
79
+ linter.run
80
+ linter.print_problems
81
+ end
82
+ abort if linter.errors? || (
83
+ linter.warnings? && PuppetLint.configuration.fail_on_warnings
84
+ )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ PuppetLint::RakeTask.new
@@ -0,0 +1,3 @@
1
+ class PuppetLint
2
+ VERSION = '1.1.0.1'
3
+ end
@@ -0,0 +1,24 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require 'puppet-lint/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'puppet-lint-halyard'
6
+ s.version = PuppetLint::VERSION
7
+ s.homepage = 'https://github.com/rodjek/puppet-lint/'
8
+ s.summary = 'Ensure your Puppet manifests conform with the Puppetlabs style guide'
9
+ s.description = 'Checks your Puppet manifests against the Puppetlabs
10
+ style guide and alerts you to any discrepancies.'
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_development_dependency 'rake', '~> 10.0'
18
+ s.add_development_dependency 'rspec', '~> 3.0'
19
+ s.add_development_dependency 'rspec-its', '~> 1.0'
20
+ s.add_development_dependency 'rspec-collection_matchers', '~> 1.0'
21
+
22
+ s.authors = ['Tim Sharpe']
23
+ s.email = 'tim@sharpe.id.au'
24
+ end
@@ -0,0 +1,2 @@
1
+ # foo
2
+ class test::foo { }
@@ -0,0 +1 @@
1
+ "test" # lint:ignore:double_quoted_strings
@@ -0,0 +1,6 @@
1
+ # lint:ignore:double_quoted_strings lint:ignore:quoted_booleans
2
+ "true"
3
+ "false"
4
+ # lint:endignore
5
+
6
+ "true"
@@ -0,0 +1,2 @@
1
+ "true" # lint:ignore:double_quoted_strings lint:ignore:quoted_booleans
2
+ "false" # lint:ignore:quoted_booleans lint:ignore:double_quoted_strings reason
@@ -0,0 +1 @@
1
+ "test" # lint:ignore:double_quoted_strings for a good reason
@@ -0,0 +1,3 @@
1
+ # foo
2
+ class test {
3
+ }
@@ -0,0 +1 @@
1
+ class { 'apacheds': master => true' }
@@ -0,0 +1,12 @@
1
+ file { 'test1':
2
+ source => 'puppet:///foo'
3
+ }
4
+ file { 'test2':
5
+ source => "puppet:///foo/${::fqdn}"
6
+ }
7
+ file { 'test3':
8
+ source => "puppet:///${::fqdn}/foo"
9
+ }
10
+ file { 'test4':
11
+ source => "puppet:///foo/${::fqdn}/bar"
12
+ }
@@ -0,0 +1,2 @@
1
+ # foo
2
+ define test::warning($foo='bar', $baz) { }
@@ -0,0 +1,326 @@
1
+ require 'spec_helper'
2
+ require 'rspec/mocks'
3
+ require 'optparse'
4
+
5
+ class CommandRun
6
+ attr_accessor :stdout, :stderr, :exitstatus
7
+
8
+ def initialize(args)
9
+ out = StringIO.new
10
+ err = StringIO.new
11
+
12
+ $stdout = out
13
+ $stderr = err
14
+
15
+ PuppetLint.configuration.defaults
16
+ @exitstatus = PuppetLint::Bin.new(args).run
17
+ PuppetLint.configuration.defaults
18
+
19
+ @stdout = out.string.strip
20
+ @stderr = err.string.strip
21
+
22
+ $stdout = STDOUT
23
+ $stderr = STDERR
24
+ end
25
+ end
26
+
27
+ describe PuppetLint::Bin do
28
+ subject do
29
+ if args.is_a? Array
30
+ sane_args = args
31
+ else
32
+ sane_args = [args]
33
+ end
34
+
35
+ CommandRun.new(sane_args)
36
+ end
37
+
38
+ context 'when running normally' do
39
+ let(:args) { 'spec/fixtures/test/manifests/init.pp' }
40
+
41
+ its(:exitstatus) { is_expected.to eq(0) }
42
+ end
43
+
44
+ context 'when running without arguments' do
45
+ let(:args) { [] }
46
+
47
+ its(:exitstatus) { is_expected.to eq(1) }
48
+ end
49
+
50
+ context 'when asked to display version' do
51
+ let(:args) { '--version' }
52
+
53
+ its(:exitstatus) { is_expected.to eq(0) }
54
+ its(:stdout) { is_expected.to eq("puppet-lint #{PuppetLint::VERSION}") }
55
+ end
56
+
57
+ context 'when passed multiple files' do
58
+ let(:args) { [
59
+ 'spec/fixtures/test/manifests/warning.pp',
60
+ 'spec/fixtures/test/manifests/fail.pp',
61
+ ] }
62
+
63
+ its(:exitstatus) { is_expected.to eq(1) }
64
+ its(:stdout) { is_expected.to eq([
65
+ "#{args[0]} - WARNING: optional parameter listed before required parameter on line 2",
66
+ "#{args[1]} - ERROR: test::foo not in autoload module layout on line 2",
67
+ ].join("\n")) }
68
+ end
69
+
70
+ context 'when passed a malformed file' do
71
+ let(:args) { 'spec/fixtures/test/manifests/malformed.pp' }
72
+
73
+ its(:exitstatus) { is_expected.to eq(1) }
74
+ its(:stdout) { is_expected.to eq('ERROR: Syntax error (try running `puppet parser validate <file>`) on line 1') }
75
+ end
76
+
77
+ context 'when limited to errors only' do
78
+ let(:args) { [
79
+ '--error-level', 'error',
80
+ 'spec/fixtures/test/manifests/warning.pp',
81
+ 'spec/fixtures/test/manifests/fail.pp',
82
+ ] }
83
+
84
+ its(:exitstatus) { is_expected.to eq(1) }
85
+ its(:stdout) { is_expected.to match(/^#{args.last} - ERROR/) }
86
+ end
87
+
88
+ context 'when limited to warnings only' do
89
+ let(:args) { [
90
+ '--error-level', 'warning',
91
+ 'spec/fixtures/test/manifests/warning.pp',
92
+ 'spec/fixtures/test/manifests/fail.pp',
93
+ ] }
94
+
95
+ its(:exitstatus) { is_expected.to eq(1) }
96
+ its(:stdout) { is_expected.to match(/WARNING/) }
97
+ its(:stdout) { is_expected.to_not match(/ERROR/) }
98
+ end
99
+
100
+ context 'when specifying a specific check to run' do
101
+ let(:args) { [
102
+ '--only-check', 'parameter_order',
103
+ 'spec/fixtures/test/manifests/warning.pp',
104
+ 'spec/fixtures/test/manifests/fail.pp',
105
+ ] }
106
+
107
+ its(:exitstatus) { is_expected.to eq(0) }
108
+ its(:stdout) { is_expected.to_not match(/ERROR/) }
109
+ its(:stdout) { is_expected.to match(/WARNING/) }
110
+ end
111
+
112
+ context 'when asked to display filenames ' do
113
+ let(:args) { ['--with-filename', 'spec/fixtures/test/manifests/fail.pp'] }
114
+
115
+ its(:exitstatus) { is_expected.to eq(1) }
116
+ its(:stdout) { is_expected.to match(%r{^spec/fixtures/test/manifests/fail\.pp -}) }
117
+ end
118
+
119
+ context 'when not asked to fail on warnings' do
120
+ let(:args) { ['spec/fixtures/test/manifests/warning.pp'] }
121
+
122
+ its(:exitstatus) { is_expected.to eq(0) }
123
+ its(:stdout) { is_expected.to match(/optional parameter/) }
124
+ end
125
+
126
+ context 'when asked to provide context to problems' do
127
+ let(:args) { [
128
+ '--with-context',
129
+ 'spec/fixtures/test/manifests/warning.pp',
130
+ ] }
131
+
132
+ its(:exitstatus) { is_expected.to eq(0) }
133
+ its(:stdout) { is_expected.to eq([
134
+ 'WARNING: optional parameter listed before required parameter on line 2',
135
+ '',
136
+ " define test::warning($foo='bar', $baz) { }",
137
+ ' ^',
138
+ ].join("\n"))
139
+ }
140
+ end
141
+
142
+ context 'when asked to fail on warnings' do
143
+ let(:args) { [
144
+ '--fail-on-warnings',
145
+ 'spec/fixtures/test/manifests/warning.pp',
146
+ ] }
147
+
148
+ its(:exitstatus) { is_expected.to eq(1) }
149
+ its(:stdout) { is_expected.to match(/optional parameter/) }
150
+ end
151
+
152
+ context 'when used with an invalid option' do
153
+ let(:args) { '--foo-bar-baz' }
154
+
155
+ its(:exitstatus) { is_expected.to eq(1) }
156
+ its(:stdout) { is_expected.to match(/invalid option/) }
157
+ end
158
+
159
+ context 'when passed a file that does not exist' do
160
+ let(:args) { 'spec/fixtures/test/manifests/enoent.pp' }
161
+
162
+ its(:exitstatus) { is_expected.to eq(1) }
163
+ its(:stdout) { is_expected.to match(/specified file does not exist/) }
164
+ end
165
+
166
+ context 'when passed a directory' do
167
+ let(:args) { 'spec/fixtures/' }
168
+
169
+ its(:exitstatus) { is_expected.to eq(1) }
170
+ its(:stdout) { is_expected.to match(/ERROR/) }
171
+ end
172
+
173
+ context 'when disabling a check' do
174
+ let(:args) { [
175
+ '--no-autoloader_layout',
176
+ 'spec/fixtures/test/manifests/fail.pp'
177
+ ] }
178
+
179
+ its(:exitstatus) { is_expected.to eq(0) }
180
+ its(:stdout) { is_expected.to eq("") }
181
+ end
182
+
183
+ context 'when changing the log format' do
184
+ context 'to print %{filename}' do
185
+ let(:args) { [
186
+ '--log-format', '%{filename}',
187
+ 'spec/fixtures/test/manifests/fail.pp'
188
+ ] }
189
+
190
+ its(:exitstatus) { is_expected.to eq(1) }
191
+ its(:stdout) { is_expected.to eq('fail.pp') }
192
+ end
193
+
194
+ context 'to print %{path}' do
195
+ let(:args) { [
196
+ '--log-format', '%{path}',
197
+ 'spec/fixtures/test/manifests/fail.pp'
198
+ ] }
199
+
200
+ its(:exitstatus) { is_expected.to eq(1) }
201
+ its(:stdout) { is_expected.to eq('spec/fixtures/test/manifests/fail.pp') }
202
+ end
203
+
204
+ context 'to print %{fullpath}' do
205
+ let(:args) { [
206
+ '--log-format', '%{fullpath}',
207
+ 'spec/fixtures/test/manifests/fail.pp'
208
+ ] }
209
+
210
+ its(:exitstatus) { is_expected.to eq(1) }
211
+ its(:stdout) {
212
+ is_expected.to match(%r{^/.+/spec/fixtures/test/manifests/fail\.pp$})
213
+ }
214
+ end
215
+
216
+ context 'to print %{linenumber}' do
217
+ let(:args) { [
218
+ '--log-format', '%{linenumber}',
219
+ 'spec/fixtures/test/manifests/fail.pp'
220
+ ] }
221
+
222
+ its(:exitstatus) { is_expected.to eq(1) }
223
+ its(:stdout) { is_expected.to eq('2') }
224
+ its(:stderr) { is_expected.to eq('DEPRECATION: Please use %{line} instead of %{linenumber}') }
225
+ end
226
+
227
+ context 'to print %{line}' do
228
+ let(:args) { [
229
+ '--log-format', '%{line}',
230
+ 'spec/fixtures/test/manifests/fail.pp'
231
+ ] }
232
+
233
+ its(:exitstatus) { is_expected.to eq(1) }
234
+ its(:stdout) { is_expected.to eq('2') }
235
+ end
236
+
237
+ context 'to print %{kind}' do
238
+ let(:args) { [
239
+ '--log-format', '%{kind}',
240
+ 'spec/fixtures/test/manifests/fail.pp'
241
+ ] }
242
+
243
+ its(:exitstatus) { is_expected.to eq(1) }
244
+ its(:stdout) { is_expected.to eq('error') }
245
+ end
246
+
247
+ context 'to print %{KIND}' do
248
+ let(:args) { [
249
+ '--log-format', '%{KIND}',
250
+ 'spec/fixtures/test/manifests/fail.pp'
251
+ ] }
252
+
253
+ its(:exitstatus) { is_expected.to eq(1) }
254
+ its(:stdout) { is_expected.to eq('ERROR') }
255
+ end
256
+
257
+ context 'to print %{check}' do
258
+ let(:args) { [
259
+ '--log-format', '%{check}',
260
+ 'spec/fixtures/test/manifests/fail.pp'
261
+ ] }
262
+
263
+ its(:exitstatus) { is_expected.to eq(1) }
264
+ its(:stdout) { is_expected.to eq('autoloader_layout') }
265
+ end
266
+
267
+ context 'to print %{message}' do
268
+ let(:args) { [
269
+ '--log-format', '%{message}',
270
+ 'spec/fixtures/test/manifests/fail.pp'
271
+ ] }
272
+
273
+ its(:exitstatus) { is_expected.to eq(1) }
274
+ its(:stdout) { is_expected.to eq('test::foo not in autoload module layout') }
275
+ end
276
+ end
277
+
278
+ context 'when hiding ignored problems' do
279
+ let(:args) { [
280
+ 'spec/fixtures/test/manifests/ignore.pp'
281
+ ] }
282
+
283
+ its(:exitstatus) { is_expected.to eq(0) }
284
+ its(:stdout) { is_expected.to_not match(/IGNORED/) }
285
+ end
286
+
287
+ context 'when showing ignored problems' do
288
+ let(:args) { [
289
+ '--show-ignored',
290
+ 'spec/fixtures/test/manifests/ignore.pp',
291
+ ] }
292
+
293
+ its(:exitstatus) { is_expected.to eq(0) }
294
+ its(:stdout) { is_expected.to match(/IGNORED/) }
295
+ end
296
+
297
+ context 'when showing ignored problems with a reason' do
298
+ let(:args) { [
299
+ '--show-ignored',
300
+ 'spec/fixtures/test/manifests/ignore_reason.pp',
301
+ ] }
302
+
303
+ its(:exitstatus) { is_expected.to eq(0) }
304
+ its(:stdout) { is_expected.to eq([
305
+ "IGNORED: double quoted string containing no variables on line 1",
306
+ " for a good reason",
307
+ ].join("\n")) }
308
+ end
309
+
310
+ context 'ignoring multiple checks on a line' do
311
+ let(:args) { [
312
+ 'spec/fixtures/test/manifests/ignore_multiple_line.pp',
313
+ ] }
314
+
315
+ its(:exitstatus) { is_expected.to eq(0) }
316
+ end
317
+
318
+ context 'ignoring multiple checks in a block' do
319
+ let(:args) { [
320
+ 'spec/fixtures/test/manifests/ignore_multiple_block.pp',
321
+ ] }
322
+
323
+ its(:exitstatus) { is_expected.to eq(0) }
324
+ its(:stdout) { is_expected.to match(/^.*line 6$/) }
325
+ end
326
+ end