rspec-puppet 2.11.0 → 4.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +154 -469
- data/README.md +71 -168
- data/bin/rspec-puppet-init +4 -3
- data/lib/rspec-puppet/adapters.rb +84 -230
- data/lib/rspec-puppet/cache.rb +3 -2
- data/lib/rspec-puppet/consts.rb +16 -14
- data/lib/rspec-puppet/coverage.rb +37 -42
- data/lib/rspec-puppet/errors.rb +6 -6
- data/lib/rspec-puppet/example/class_example_group.rb +3 -1
- data/lib/rspec-puppet/example/define_example_group.rb +3 -1
- data/lib/rspec-puppet/example/function_example_group.rb +42 -57
- data/lib/rspec-puppet/example/host_example_group.rb +3 -1
- data/lib/rspec-puppet/example/provider_example_group.rb +2 -0
- data/lib/rspec-puppet/example/type_alias_example_group.rb +4 -2
- data/lib/rspec-puppet/example/type_example_group.rb +3 -1
- data/lib/rspec-puppet/example.rb +6 -9
- data/lib/rspec-puppet/facter_impl.rb +11 -10
- data/lib/rspec-puppet/matchers/allow_value.rb +10 -10
- data/lib/rspec-puppet/matchers/compile.rb +54 -61
- data/lib/rspec-puppet/matchers/count_generic.rb +18 -18
- data/lib/rspec-puppet/matchers/create_generic.rb +69 -79
- data/lib/rspec-puppet/matchers/dynamic_matchers.rb +15 -4
- data/lib/rspec-puppet/matchers/include_class.rb +5 -4
- data/lib/rspec-puppet/matchers/parameter_matcher.rb +11 -12
- data/lib/rspec-puppet/matchers/raise_error.rb +5 -1
- data/lib/rspec-puppet/matchers/run.rb +41 -42
- data/lib/rspec-puppet/matchers/type_matchers.rb +37 -48
- data/lib/rspec-puppet/matchers.rb +2 -0
- data/lib/rspec-puppet/monkey_patches/win32/registry.rb +7 -5
- data/lib/rspec-puppet/monkey_patches/win32/taskscheduler.rb +3 -1
- data/lib/rspec-puppet/monkey_patches/windows/taskschedulerconstants.rb +208 -205
- data/lib/rspec-puppet/monkey_patches.rb +80 -93
- data/lib/rspec-puppet/rake_task.rb +6 -4
- data/lib/rspec-puppet/raw_string.rb +2 -0
- data/lib/rspec-puppet/sensitive.rb +31 -39
- data/lib/rspec-puppet/setup.rb +45 -56
- data/lib/rspec-puppet/spec_helper.rb +2 -3
- data/lib/rspec-puppet/support.rb +129 -177
- data/lib/rspec-puppet/tasks/release_test.rb +8 -5
- data/lib/rspec-puppet/version.rb +5 -0
- data/lib/rspec-puppet.rb +37 -61
- metadata +18 -15
- data/lib/rspec-puppet/example/application_example_group.rb +0 -19
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rspec-puppet/facter_impl'
|
|
2
4
|
|
|
3
5
|
module RSpec::Puppet
|
|
4
6
|
module Adapters
|
|
5
|
-
|
|
6
7
|
class Base
|
|
7
8
|
# Set up all Puppet settings applicable for this Puppet version as
|
|
8
9
|
# application defaults.
|
|
@@ -11,12 +12,6 @@ module RSpec::Puppet
|
|
|
11
12
|
# executing RSpec context. When a setting is specified both in the global configuration and in
|
|
12
13
|
# the example group, the setting in the example group is preferred.
|
|
13
14
|
#
|
|
14
|
-
# @example Configuring a Puppet setting from a global RSpec configuration value
|
|
15
|
-
# RSpec.configure do |config|
|
|
16
|
-
# config.parser = "future"
|
|
17
|
-
# end
|
|
18
|
-
# # => Puppet[:parser] will be future
|
|
19
|
-
#
|
|
20
15
|
# @example Configuring a Puppet setting from within an RSpec example group
|
|
21
16
|
# RSpec.describe 'my_module::my_class', :type => :class do
|
|
22
17
|
# let(:module_path) { "/Users/luke/modules" }
|
|
@@ -41,98 +36,51 @@ module RSpec::Puppet
|
|
|
41
36
|
# @param example_group [RSpec::Core::ExampleGroup] The RSpec context to use for local settings
|
|
42
37
|
# @return [void]
|
|
43
38
|
def setup_puppet(example_group)
|
|
39
|
+
case RSpec.configuration.facter_implementation.to_sym
|
|
40
|
+
when :rspec
|
|
41
|
+
# Lazily instantiate FacterTestImpl here to optimize memory
|
|
42
|
+
# allocation, as the proc will only be called if FacterImpl is unset
|
|
43
|
+
set_facter_impl(proc { RSpec::Puppet::FacterTestImpl.new })
|
|
44
|
+
when :facter
|
|
45
|
+
set_facter_impl(Facter)
|
|
46
|
+
else
|
|
47
|
+
raise "Unsupported facter_implementation '#{RSpec.configuration.facter_implementation}'"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Puppet.runtime[:facter] = FacterImpl
|
|
51
|
+
|
|
44
52
|
settings = settings_map.map do |puppet_setting, rspec_setting|
|
|
45
53
|
[puppet_setting, get_setting(example_group, rspec_setting)]
|
|
46
54
|
end.flatten
|
|
47
|
-
default_hash = {:
|
|
55
|
+
default_hash = { confdir: '/dev/null', vardir: '/dev/null' }
|
|
48
56
|
if defined?(Puppet::Test::TestHelper) && Puppet::Test::TestHelper.respond_to?(:app_defaults_for_tests, true)
|
|
49
57
|
default_hash.merge!(Puppet::Test::TestHelper.send(:app_defaults_for_tests))
|
|
50
58
|
end
|
|
51
59
|
settings_hash = default_hash.merge(Hash[*settings])
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Puppet.settings.initialize_app_defaults(settings_hash)
|
|
56
|
-
|
|
57
|
-
# Forcefully apply the environmentpath setting instead of relying on
|
|
58
|
-
# the application defaults as Puppet::Test::TestHelper automatically
|
|
59
|
-
# sets this value as well, overriding our application default
|
|
60
|
-
Puppet.settings[:environmentpath] = settings_hash[:environmentpath] if settings_hash.key?(:environmentpath)
|
|
61
|
-
else
|
|
62
|
-
# Set settings the old way for Puppet 2.x, because that's how
|
|
63
|
-
# they're defaulted in that version of Puppet::Test::TestHelper and
|
|
64
|
-
# we won't be able to override them otherwise.
|
|
65
|
-
settings_hash.each do |setting, value|
|
|
66
|
-
Puppet.settings[setting] = value
|
|
60
|
+
if Gem.win_platform?
|
|
61
|
+
settings_hash.each_with_object(settings_hash) do |(k, v), h|
|
|
62
|
+
h[k] = v == '/dev/null' ? 'c:/nul/' : v
|
|
67
63
|
end
|
|
68
64
|
end
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def get_setting(example_group, rspec_setting)
|
|
74
|
-
if example_group.respond_to?(rspec_setting)
|
|
75
|
-
example_group.send(rspec_setting)
|
|
76
|
-
else
|
|
77
|
-
RSpec.configuration.send(rspec_setting)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
66
|
+
Puppet.settings.initialize_app_defaults(settings_hash)
|
|
80
67
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
else
|
|
86
|
-
Puppet::Resource::Catalog.indirection.find(node.name, :use_node => node)
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def current_environment
|
|
91
|
-
Puppet::Node::Environment.new(@environment_name)
|
|
92
|
-
end
|
|
68
|
+
# Forcefully apply the environmentpath setting instead of relying on
|
|
69
|
+
# the application defaults as Puppet::Test::TestHelper automatically
|
|
70
|
+
# sets this value as well, overriding our application default
|
|
71
|
+
Puppet.settings[:environmentpath] = settings_hash[:environmentpath] if settings_hash.key?(:environmentpath)
|
|
93
72
|
|
|
94
|
-
|
|
95
|
-
[
|
|
96
|
-
[:modulepath, :module_path],
|
|
97
|
-
[:config, :config],
|
|
98
|
-
[:confdir, :confdir],
|
|
99
|
-
]
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def modulepath
|
|
103
|
-
Puppet[:modulepath].split(File::PATH_SEPARATOR)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# @return [String, nil] The path to the Puppet manifest if it is present and set, nil otherwise.
|
|
107
|
-
def manifest
|
|
108
|
-
Puppet[:manifest]
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
class Adapter40 < Base
|
|
113
|
-
#
|
|
114
|
-
# @api private
|
|
115
|
-
#
|
|
116
|
-
# Set the FacterImpl constant to the given Facter implementation.
|
|
117
|
-
# The method noops if the constant is already set
|
|
118
|
-
#
|
|
119
|
-
# @param impl [Object]
|
|
120
|
-
def set_facter_impl(impl)
|
|
121
|
-
Object.send(:const_set, :FacterImpl, impl) unless defined? FacterImpl
|
|
122
|
-
end
|
|
73
|
+
@environment_name = example_group.environment
|
|
123
74
|
|
|
124
|
-
|
|
125
|
-
|
|
75
|
+
modulepath = if (rspec_modulepath = RSpec.configuration.module_path)
|
|
76
|
+
rspec_modulepath.split(File::PATH_SEPARATOR)
|
|
77
|
+
else
|
|
78
|
+
Puppet[:environmentpath].split(File::PATH_SEPARATOR).map do |path|
|
|
79
|
+
File.join(path, 'fixtures', 'modules')
|
|
80
|
+
end
|
|
81
|
+
end
|
|
126
82
|
|
|
127
|
-
if
|
|
128
|
-
modulepath = rspec_modulepath.split(File::PATH_SEPARATOR)
|
|
129
|
-
else
|
|
130
|
-
modulepath = Puppet[:environmentpath].split(File::PATH_SEPARATOR).map do |path|
|
|
131
|
-
File.join(path, 'fixtures', 'modules')
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
if rspec_manifest = RSpec.configuration.manifest
|
|
83
|
+
if (rspec_manifest = RSpec.configuration.manifest)
|
|
136
84
|
manifest = rspec_manifest
|
|
137
85
|
else
|
|
138
86
|
manifest_paths = Puppet[:environmentpath].split(File::PATH_SEPARATOR).map do |path|
|
|
@@ -151,29 +99,57 @@ module RSpec::Puppet
|
|
|
151
99
|
|
|
152
100
|
Puppet.push_context(
|
|
153
101
|
{
|
|
154
|
-
:
|
|
155
|
-
:
|
|
156
|
-
:
|
|
102
|
+
environments: loader,
|
|
103
|
+
current_environment: env,
|
|
104
|
+
loaders: Puppet::Pops::Loaders.new(env)
|
|
157
105
|
},
|
|
158
|
-
|
|
106
|
+
'Setup rspec-puppet environments'
|
|
159
107
|
)
|
|
160
108
|
end
|
|
161
109
|
|
|
162
|
-
def
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
])
|
|
110
|
+
def get_setting(example_group, rspec_setting)
|
|
111
|
+
if example_group.respond_to?(rspec_setting)
|
|
112
|
+
example_group.send(rspec_setting)
|
|
113
|
+
else
|
|
114
|
+
RSpec.configuration.send(rspec_setting)
|
|
115
|
+
end
|
|
169
116
|
end
|
|
170
117
|
|
|
171
118
|
def catalog(node, exported)
|
|
172
119
|
node.environment = current_environment
|
|
173
120
|
# Override $::environment to workaround PUP-5835, where Puppet otherwise
|
|
174
121
|
# stores a symbol for the parameter
|
|
175
|
-
|
|
176
|
-
|
|
122
|
+
if node.parameters['environment'] != node.parameters['environment'].to_s
|
|
123
|
+
node.parameters['environment'] = current_environment.name.to_s
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
catalog = if exported
|
|
127
|
+
# Use the compiler directly to skip the filtering done by the indirector
|
|
128
|
+
Puppet::Parser::Compiler.compile(node).filter { |r| !r.exported? }
|
|
129
|
+
else
|
|
130
|
+
Puppet::Resource::Catalog.indirection.find(node.name, use_node: node)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog)
|
|
134
|
+
|
|
135
|
+
catalog
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def current_environment
|
|
139
|
+
Puppet::Node::Environment.new(@environment_name)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def settings_map
|
|
143
|
+
[
|
|
144
|
+
%i[modulepath module_path],
|
|
145
|
+
%i[basemodulepath basemodulepath],
|
|
146
|
+
%i[config config],
|
|
147
|
+
%i[confdir confdir],
|
|
148
|
+
%i[environmentpath environmentpath],
|
|
149
|
+
%i[hiera_config hiera_config],
|
|
150
|
+
%i[strict_variables strict_variables],
|
|
151
|
+
%i[vendormoduledir vendormoduledir]
|
|
152
|
+
]
|
|
177
153
|
end
|
|
178
154
|
|
|
179
155
|
def current_environment
|
|
@@ -184,9 +160,6 @@ module RSpec::Puppet
|
|
|
184
160
|
current_environment.modulepath
|
|
185
161
|
end
|
|
186
162
|
|
|
187
|
-
# Puppet 4.0 specially handles environments that don't have a manifest set, so we check for the no manifest value
|
|
188
|
-
# and return nil when it is set.
|
|
189
|
-
#
|
|
190
163
|
# @return [String, nil] The path to the Puppet manifest if it is present and set, nil otherwise.
|
|
191
164
|
def manifest
|
|
192
165
|
m = current_environment.manifest
|
|
@@ -196,146 +169,27 @@ module RSpec::Puppet
|
|
|
196
169
|
m
|
|
197
170
|
end
|
|
198
171
|
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
class Adapter4X < Adapter40
|
|
202
|
-
def setup_puppet(example_group)
|
|
203
|
-
super
|
|
204
|
-
|
|
205
|
-
set_facter_impl(Facter)
|
|
206
|
-
end
|
|
207
172
|
|
|
208
|
-
def settings_map
|
|
209
|
-
super.concat([
|
|
210
|
-
[:trusted_server_facts, :trusted_server_facts]
|
|
211
|
-
])
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
class Adapter6X < Adapter40
|
|
216
|
-
#
|
|
217
173
|
# @api private
|
|
218
174
|
#
|
|
219
|
-
#
|
|
220
|
-
#
|
|
175
|
+
# Set the FacterImpl constant to the given Facter implementation or noop
|
|
176
|
+
# if the constant is already set. If a proc is given, it will only be
|
|
177
|
+
# called if FacterImpl is not defined.
|
|
221
178
|
#
|
|
222
|
-
# @
|
|
223
|
-
def
|
|
224
|
-
|
|
225
|
-
begin
|
|
226
|
-
Puppet.runtime[:facter]
|
|
227
|
-
@supports_facter_runtime = true
|
|
228
|
-
rescue
|
|
229
|
-
@supports_facter_runtime = false
|
|
230
|
-
end
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
@supports_facter_runtime
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def setup_puppet(example_group)
|
|
237
|
-
case RSpec.configuration.facter_implementation.to_sym
|
|
238
|
-
when :rspec
|
|
239
|
-
if supports_facter_runtime?
|
|
240
|
-
Puppet.runtime[:facter] = proc { RSpec::Puppet::FacterTestImpl.new }
|
|
241
|
-
set_facter_impl(Puppet.runtime[:facter])
|
|
242
|
-
else
|
|
243
|
-
warn "Facter runtime implementations are not supported in Puppet #{Puppet.version}, continuing with facter_implementation 'facter'"
|
|
244
|
-
RSpec.configuration.facter_implementation = 'facter'
|
|
245
|
-
set_facter_impl(Facter)
|
|
246
|
-
end
|
|
247
|
-
when :facter
|
|
248
|
-
set_facter_impl(Facter)
|
|
249
|
-
else
|
|
250
|
-
raise "Unsupported facter_implementation '#{RSpec.configuration.facter_implementation}'"
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
super
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def settings_map
|
|
257
|
-
super.concat([
|
|
258
|
-
[:basemodulepath, :basemodulepath],
|
|
259
|
-
[:vendormoduledir, :vendormoduledir],
|
|
260
|
-
])
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
def catalog(node, _exported)
|
|
264
|
-
super.tap do |c|
|
|
265
|
-
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, c)
|
|
266
|
-
end
|
|
267
|
-
end
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
class Adapter30 < Base
|
|
271
|
-
def settings_map
|
|
272
|
-
super.concat([
|
|
273
|
-
[:manifestdir, :manifest_dir],
|
|
274
|
-
[:manifest, :manifest],
|
|
275
|
-
[:templatedir, :template_dir],
|
|
276
|
-
[:hiera_config, :hiera_config],
|
|
277
|
-
])
|
|
278
|
-
end
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
class Adapter32 < Adapter30
|
|
282
|
-
def settings_map
|
|
283
|
-
super.concat([
|
|
284
|
-
[:parser, :parser],
|
|
285
|
-
])
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
class Adapter33 < Adapter32
|
|
290
|
-
def settings_map
|
|
291
|
-
super.concat([
|
|
292
|
-
[:ordering, :ordering],
|
|
293
|
-
[:stringify_facts, :stringify_facts],
|
|
294
|
-
])
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
class Adapter34 < Adapter33
|
|
299
|
-
def settings_map
|
|
300
|
-
super.concat([
|
|
301
|
-
[:trusted_node_data, :trusted_node_data],
|
|
302
|
-
])
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
class Adapter35 < Adapter34
|
|
307
|
-
def settings_map
|
|
308
|
-
super.concat([
|
|
309
|
-
[:strict_variables, :strict_variables],
|
|
310
|
-
])
|
|
311
|
-
end
|
|
312
|
-
end
|
|
179
|
+
# @param impl [Object, Proc] An object or a proc that implements the Facter API
|
|
180
|
+
def set_facter_impl(impl)
|
|
181
|
+
return if defined?(FacterImpl)
|
|
313
182
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
super.concat([
|
|
317
|
-
[:manifestdir, :manifest_dir],
|
|
318
|
-
[:manifest, :manifest],
|
|
319
|
-
[:templatedir, :template_dir],
|
|
320
|
-
])
|
|
183
|
+
impl = impl.call if impl.is_a?(Proc)
|
|
184
|
+
Object.send(:const_set, :FacterImpl, impl)
|
|
321
185
|
end
|
|
322
186
|
end
|
|
323
187
|
|
|
324
188
|
def self.get
|
|
325
189
|
[
|
|
326
|
-
['
|
|
327
|
-
['4.1', Adapter4X],
|
|
328
|
-
['4.0', Adapter40],
|
|
329
|
-
['3.5', Adapter35],
|
|
330
|
-
['3.4', Adapter34],
|
|
331
|
-
['3.3', Adapter33],
|
|
332
|
-
['3.2', Adapter32],
|
|
333
|
-
['3.0', Adapter30],
|
|
334
|
-
['2.7', Adapter27]
|
|
190
|
+
['7.11', Base]
|
|
335
191
|
].each do |(version, klass)|
|
|
336
|
-
if Puppet::Util::Package.versioncmp(Puppet.version, version) >= 0
|
|
337
|
-
return klass.new
|
|
338
|
-
end
|
|
192
|
+
return klass.new if Puppet::Util::Package.versioncmp(Puppet.version, version) >= 0
|
|
339
193
|
end
|
|
340
194
|
raise "Puppet version #{Puppet.version} is not supported."
|
|
341
195
|
end
|
data/lib/rspec-puppet/cache.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RSpec::Puppet
|
|
2
4
|
class Cache
|
|
3
|
-
|
|
4
5
|
MAX_ENTRIES = 16
|
|
5
6
|
|
|
6
7
|
# @param [Proc] default_proc The default proc to use to fetch objects on cache miss
|
|
@@ -12,7 +13,7 @@ module RSpec::Puppet
|
|
|
12
13
|
|
|
13
14
|
def get(*args, &blk)
|
|
14
15
|
key = Marshal.load(Marshal.dump(args))
|
|
15
|
-
if @cache.
|
|
16
|
+
if @cache.key?(key)
|
|
16
17
|
# Cache hit
|
|
17
18
|
# move that entry last to make it "most recenty used"
|
|
18
19
|
@lra.insert(-1, @lra.delete_at(@lra.index(args)))
|
data/lib/rspec-puppet/consts.rb
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RSpec::Puppet::Consts
|
|
2
4
|
STUBBED_CONSTS = {
|
|
3
|
-
:
|
|
5
|
+
posix: {
|
|
4
6
|
'File::PATH_SEPARATOR' => ':',
|
|
5
7
|
'File::ALT_SEPARATOR' => nil,
|
|
6
|
-
'Pathname::SEPARATOR_PAT' => /#{Regexp.quote('/')}
|
|
8
|
+
'Pathname::SEPARATOR_PAT' => /#{Regexp.quote('/')}/
|
|
7
9
|
},
|
|
8
|
-
:
|
|
10
|
+
windows: {
|
|
9
11
|
'File::PATH_SEPARATOR' => ';',
|
|
10
|
-
'File::ALT_SEPARATOR' =>
|
|
11
|
-
'Pathname::SEPARATOR_PAT' => /[#{Regexp.quote(
|
|
12
|
+
'File::ALT_SEPARATOR' => '\\',
|
|
13
|
+
'Pathname::SEPARATOR_PAT' => /[#{Regexp.quote('\\')}#{Regexp.quote('/')}]/
|
|
12
14
|
}
|
|
13
|
-
}
|
|
15
|
+
}.freeze
|
|
14
16
|
|
|
15
17
|
FEATURES = {
|
|
16
|
-
:
|
|
17
|
-
:
|
|
18
|
-
:
|
|
19
|
-
},
|
|
20
|
-
:windows => {
|
|
21
|
-
:posix => false,
|
|
22
|
-
:microsoft_windows => true,
|
|
18
|
+
posix: {
|
|
19
|
+
posix: true,
|
|
20
|
+
microsoft_windows: false
|
|
23
21
|
},
|
|
24
|
-
|
|
22
|
+
windows: {
|
|
23
|
+
posix: false,
|
|
24
|
+
microsoft_windows: true
|
|
25
|
+
}
|
|
26
|
+
}.freeze
|
|
25
27
|
|
|
26
28
|
def self.stub_consts_for(platform)
|
|
27
29
|
STUBBED_CONSTS[platform].each do |const_name, const_value|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'tmpdir'
|
|
2
4
|
require 'digest'
|
|
3
5
|
require 'json'
|
|
@@ -16,23 +18,22 @@ end
|
|
|
16
18
|
|
|
17
19
|
module RSpec::Puppet
|
|
18
20
|
class Coverage
|
|
19
|
-
|
|
20
21
|
attr_accessor :filters, :filters_regex
|
|
21
22
|
|
|
22
23
|
class << self
|
|
23
24
|
extend Forwardable
|
|
24
25
|
|
|
25
|
-
delegated_methods = [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
delegated_methods = %i[
|
|
27
|
+
instance
|
|
28
|
+
add
|
|
29
|
+
cover!
|
|
30
|
+
report!
|
|
31
|
+
filters
|
|
32
|
+
filters_regex
|
|
33
|
+
add_filter
|
|
34
|
+
add_filter_regex
|
|
35
|
+
add_from_catalog
|
|
36
|
+
results
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
def_delegators(*delegated_methods)
|
|
@@ -112,23 +113,21 @@ module RSpec::Puppet
|
|
|
112
113
|
end
|
|
113
114
|
|
|
114
115
|
def add(resource)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
return unless !exists?(resource) && !filtered?(resource)
|
|
117
|
+
|
|
118
|
+
@collection[resource.to_s] = ResourceWrapper.new(resource)
|
|
118
119
|
end
|
|
119
120
|
|
|
120
121
|
def add_filter(type, title)
|
|
121
122
|
type = capitalize_name(type)
|
|
122
123
|
|
|
123
|
-
if type == 'Class'
|
|
124
|
-
title = capitalize_name(title)
|
|
125
|
-
end
|
|
124
|
+
title = capitalize_name(title) if type == 'Class'
|
|
126
125
|
|
|
127
126
|
@filters << "#{type}[#{title}]"
|
|
128
127
|
end
|
|
129
128
|
|
|
130
129
|
def add_filter_regex(type, pattern)
|
|
131
|
-
raise ArgumentError
|
|
130
|
+
raise ArgumentError, 'pattern argument must be a Regexp' unless pattern.is_a?(Regexp)
|
|
132
131
|
|
|
133
132
|
type = capitalize_name(type)
|
|
134
133
|
|
|
@@ -145,7 +144,7 @@ module RSpec::Puppet
|
|
|
145
144
|
|
|
146
145
|
# match an even number of backslashes before the anchor - this indicates that the anchor was not escaped
|
|
147
146
|
# note the necessity for the negative lookbehind `(?<!)` to assert that there is no backslash before this
|
|
148
|
-
src = if
|
|
147
|
+
src = if /(?<!\\)(\\\\)*(?:\\[zZ]|\$)\z/.match?(src)
|
|
149
148
|
src.gsub(/(?:\\[zZ]|\$)\z/, '')
|
|
150
149
|
else
|
|
151
150
|
# no anchor at the end
|
|
@@ -157,7 +156,9 @@ module RSpec::Puppet
|
|
|
157
156
|
|
|
158
157
|
# add all resources from catalog declared in module test_module
|
|
159
158
|
def add_from_catalog(catalog, test_module)
|
|
160
|
-
coverable_resources = catalog.to_a.reject
|
|
159
|
+
coverable_resources = catalog.to_a.reject do |resource|
|
|
160
|
+
!test_module.nil? && filter_resource?(resource, test_module)
|
|
161
|
+
end
|
|
161
162
|
coverable_resources.each do |resource|
|
|
162
163
|
add(resource)
|
|
163
164
|
end
|
|
@@ -171,9 +172,9 @@ module RSpec::Puppet
|
|
|
171
172
|
end
|
|
172
173
|
|
|
173
174
|
def cover!(resource)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
return unless !filtered?(resource) && (wrapper = find(resource))
|
|
176
|
+
|
|
177
|
+
wrapper.touch!
|
|
177
178
|
end
|
|
178
179
|
|
|
179
180
|
def report!(coverage_desired = nil)
|
|
@@ -213,9 +214,9 @@ module RSpec::Puppet
|
|
|
213
214
|
coverage_desired ||= 0
|
|
214
215
|
|
|
215
216
|
if coverage_desired.is_a?(Numeric) && coverage_desired.to_f <= 100.00 && coverage_desired.to_f >= 0.0
|
|
216
|
-
coverage_test = RSpec.describe(
|
|
217
|
+
coverage_test = RSpec.describe('Code coverage')
|
|
217
218
|
coverage_results = coverage_test.example("must cover at least #{coverage_desired}% of resources") do
|
|
218
|
-
expect(
|
|
219
|
+
expect(coverage_actual.to_f).to be >= coverage_desired.to_f
|
|
219
220
|
end
|
|
220
221
|
coverage_test.run(RSpec.configuration.reporter)
|
|
221
222
|
|
|
@@ -248,8 +249,8 @@ module RSpec::Puppet
|
|
|
248
249
|
report[:touched] = @collection.count { |_, resource| resource.touched? }
|
|
249
250
|
report[:untouched] = report[:total] - report[:touched]
|
|
250
251
|
|
|
251
|
-
coverage = report[:total].to_f
|
|
252
|
-
report[:coverage] =
|
|
252
|
+
coverage = report[:total].to_f.positive? ? ((report[:touched].to_f / report[:total]) * 100) : 100.0
|
|
253
|
+
report[:coverage] = '%5.2f' % coverage
|
|
253
254
|
|
|
254
255
|
report[:resources] = Hash[*@collection.map do |name, wrapper|
|
|
255
256
|
[name, wrapper.to_hash]
|
|
@@ -258,10 +259,10 @@ module RSpec::Puppet
|
|
|
258
259
|
text = [
|
|
259
260
|
"Total resources: #{report[:total]}",
|
|
260
261
|
"Touched resources: #{report[:touched]}",
|
|
261
|
-
"Resource coverage: #{report[:coverage]}%"
|
|
262
|
+
"Resource coverage: #{report[:coverage]}%"
|
|
262
263
|
]
|
|
263
264
|
|
|
264
|
-
if report[:untouched]
|
|
265
|
+
if (report[:untouched]).positive?
|
|
265
266
|
text += ['', 'Untouched resources:']
|
|
266
267
|
untouched_resources = report[:resources].reject { |_, r| r[:touched] }
|
|
267
268
|
text += untouched_resources.map { |name, _| " #{name}" }.sort
|
|
@@ -288,25 +289,19 @@ module RSpec::Puppet
|
|
|
288
289
|
# @param test_module [String] The name of the module under test
|
|
289
290
|
# @return [true, false]
|
|
290
291
|
def filter_resource?(resource, test_module)
|
|
291
|
-
if filtered?(resource)
|
|
292
|
-
return true
|
|
293
|
-
end
|
|
292
|
+
return true if filtered?(resource)
|
|
294
293
|
|
|
295
294
|
if resource.type == 'Class'
|
|
296
295
|
module_name = resource.title.split('::').first.downcase
|
|
297
|
-
if module_name != test_module
|
|
298
|
-
return true
|
|
299
|
-
end
|
|
296
|
+
return true if module_name != test_module
|
|
300
297
|
end
|
|
301
298
|
|
|
302
299
|
if resource.file
|
|
303
300
|
paths = module_paths(test_module)
|
|
304
|
-
unless paths.any? { |path| resource.file.include?(path) }
|
|
305
|
-
return true
|
|
306
|
-
end
|
|
301
|
+
return true unless paths.any? { |path| resource.file.include?(path) }
|
|
307
302
|
end
|
|
308
303
|
|
|
309
|
-
|
|
304
|
+
false
|
|
310
305
|
end
|
|
311
306
|
|
|
312
307
|
# Find all paths that may contain testable resources for a module.
|
|
@@ -330,7 +325,7 @@ module RSpec::Puppet
|
|
|
330
325
|
end
|
|
331
326
|
|
|
332
327
|
def capitalize_name(name)
|
|
333
|
-
name.split('::').map
|
|
328
|
+
name.split('::').map(&:capitalize).join('::')
|
|
334
329
|
end
|
|
335
330
|
|
|
336
331
|
class ResourceWrapper
|
|
@@ -346,7 +341,7 @@ module RSpec::Puppet
|
|
|
346
341
|
|
|
347
342
|
def to_hash
|
|
348
343
|
{
|
|
349
|
-
:
|
|
344
|
+
touched: touched?
|
|
350
345
|
}
|
|
351
346
|
end
|
|
352
347
|
|
data/lib/rspec-puppet/errors.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RSpec::Puppet
|
|
2
4
|
module Errors
|
|
3
5
|
class MatchError < StandardError
|
|
@@ -11,18 +13,16 @@ module RSpec::Puppet
|
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def message
|
|
14
|
-
if @param.to_s == 'content'
|
|
16
|
+
if (@param.to_s == 'content') && expected.is_a?(String)
|
|
15
17
|
if negative == true
|
|
16
18
|
"#{param} not set to supplied string"
|
|
17
19
|
else
|
|
18
20
|
"#{param} set to supplied string"
|
|
19
21
|
end
|
|
22
|
+
elsif negative == true
|
|
23
|
+
"#{param} not set to #{expected.inspect} but it is set to #{actual.inspect}"
|
|
20
24
|
else
|
|
21
|
-
|
|
22
|
-
"#{param} not set to #{expected.inspect} but it is set to #{actual.inspect}"
|
|
23
|
-
else
|
|
24
|
-
"#{param} set to #{expected.inspect} but it is set to #{actual.inspect}"
|
|
25
|
-
end
|
|
25
|
+
"#{param} set to #{expected.inspect} but it is set to #{actual.inspect}"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module RSpec::Puppet
|
|
2
4
|
module ClassExampleGroup
|
|
3
5
|
include RSpec::Puppet::ManifestMatchers
|
|
@@ -8,7 +10,7 @@ module RSpec::Puppet
|
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def exported_resources
|
|
11
|
-
|
|
13
|
+
-> { load_catalogue(:class, true) }
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def rspec_puppet_cleanup
|