rspec-puppet 2.5.0 → 2.6.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.
@@ -14,9 +14,9 @@ module RSpec::Puppet
14
14
  end
15
15
 
16
16
  # This method is used by the `run` matcher to trigger the function execution, and provides a uniform interface across all puppet versions.
17
- def execute(*args)
17
+ def execute(*args, &block)
18
18
  Puppet.override(@overrides, "rspec-test scope") do
19
- @func.call(@overrides[:global_scope], *args)
19
+ @func.call(@overrides[:global_scope], *freeze_arg(args), &block)
20
20
  end
21
21
  end
22
22
 
@@ -25,6 +25,24 @@ module RSpec::Puppet
25
25
  RSpec.deprecate("subject.call", :replacement => "is_expected.to run.with().and_raise_error(), or execute()")
26
26
  execute(*args)
27
27
  end
28
+
29
+ private
30
+
31
+ # Facts, keywords, single-quoted strings etc. are usually frozen in Puppet manifests, so freeze arguments to ensure functions are tested
32
+ # under worst-case conditions.
33
+ def freeze_arg(arg)
34
+ case arg
35
+ when Array
36
+ arg.each { |a| freeze_arg(a) }
37
+ arg.freeze
38
+ when Hash
39
+ arg.each { |k,v| freeze_arg(k); freeze_arg(v) }
40
+ arg.freeze
41
+ when String
42
+ arg.freeze
43
+ end
44
+ arg
45
+ end
28
46
  end
29
47
 
30
48
  class V3FunctionWrapper
@@ -61,18 +79,16 @@ module RSpec::Puppet
61
79
  @subject ||= find_function
62
80
  end
63
81
 
64
- def find_function
65
- function_name = self.class.top_level_description.downcase
66
-
82
+ def find_function(function_name = self.class.top_level_description)
67
83
  with_vardir do
68
84
  env = adapter.current_environment
69
85
 
70
86
  if Puppet.version.to_f >= 4.0
71
87
  context_overrides = compiler.context_overrides
72
88
  func = nil
89
+ loaders = Puppet.lookup(:loaders)
73
90
  Puppet.override(context_overrides, "rspec-test scope") do
74
- loader = Puppet::Pops::Loaders.new(env)
75
- func = V4FunctionWrapper.new(function_name, loader.private_environment_loader.load(:function, function_name), context_overrides)
91
+ func = V4FunctionWrapper.new(function_name, loaders.private_environment_loader.load(:function, function_name), context_overrides)
76
92
  @scope = context_overrides[:global_scope]
77
93
  end
78
94
 
@@ -86,7 +102,11 @@ module RSpec::Puppet
86
102
  end
87
103
  end
88
104
  end
89
-
105
+ def call_function(function_name, *args)
106
+ # function = find_function(function_name)
107
+ # function.execute(*args)
108
+ scope.call_function(function_name, args)
109
+ end
90
110
  def scope
91
111
  @scope ||= build_scope(compiler, nodename(:function))
92
112
  end
@@ -112,22 +132,47 @@ module RSpec::Puppet
112
132
  def build_compiler
113
133
  node_name = nodename(:function)
114
134
  fact_values = facts_hash(node_name)
135
+ trusted_values = trusted_facts_hash(node_name)
136
+
137
+ # Allow different Hiera configurations:
138
+ HieraPuppet.instance_variable_set('@hiera', nil) if defined? HieraPuppet
115
139
 
116
140
  # if we specify a pre_condition, we should ensure that we compile that
117
141
  # code into a catalog that is accessible from the scope where the
118
142
  # function is called
119
143
  Puppet[:code] = pre_cond
120
144
 
145
+ node_facts = Puppet::Node::Facts.new(node_name, fact_values.dup)
146
+
121
147
  node_options = {
122
148
  :parameters => fact_values,
149
+ :facts => node_facts
123
150
  }
124
151
 
125
152
  stub_facts! fact_values
126
153
 
127
154
  node = build_node(node_name, node_options)
128
155
 
156
+ if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0
157
+ Puppet.push_context(
158
+ {
159
+ :trusted_information => Puppet::Context::TrustedInformation.new('remote', node_name, trusted_values)
160
+ },
161
+ "Context for spec trusted hash"
162
+ )
163
+ end
164
+
129
165
  compiler = Puppet::Parser::Compiler.new(node)
130
166
  compiler.compile
167
+ if Puppet::Util::Package.versioncmp(Puppet.version, '4.0.0') >= 0
168
+ loaders = Puppet::Pops::Loaders.new(adapter.current_environment)
169
+ Puppet.push_context(
170
+ {
171
+ :loaders => loaders,
172
+ :global_scope => compiler.context_overrides[:global_scope]
173
+ },
174
+ "set globals")
175
+ end
131
176
  compiler
132
177
  end
133
178
 
@@ -0,0 +1,14 @@
1
+ module RSpec::Puppet
2
+ module TypeAliasExampleGroup
3
+ include RSpec::Puppet::TypeAliasMatchers
4
+ include RSpec::Puppet::Support
5
+
6
+ def catalogue(test_value)
7
+ load_catalogue(:type_alias, false, :test_value => test_value)
8
+ end
9
+
10
+ def subject
11
+ lambda { |test_value| catalogue(test_value) }
12
+ end
13
+ end
14
+ end
@@ -4,46 +4,29 @@ require 'rspec-puppet/example/class_example_group'
4
4
  require 'rspec-puppet/example/function_example_group'
5
5
  require 'rspec-puppet/example/host_example_group'
6
6
  require 'rspec-puppet/example/type_example_group'
7
+ require 'rspec-puppet/example/type_alias_example_group'
7
8
  require 'rspec-puppet/example/provider_example_group'
8
9
  require 'rspec-puppet/example/application_example_group'
9
10
 
10
11
  RSpec::configure do |c|
11
12
 
12
- def c.escaped_path(*parts)
13
- Regexp.compile(parts.join('[\\\/]'))
13
+ def c.rspec_puppet_include(group, type, file_path)
14
+ escaped_file_path = Regexp.compile(file_path.join('[\\\/]'))
15
+ if RSpec::Version::STRING < '3'
16
+ self.include group, :type => type, :example_group => { :file_path => escaped_file_path }, :spec_type => type
17
+ else
18
+ self.include group, :type => type, :file_path => lambda { |file_path, metadata| metadata[:type].nil? && escaped_file_path =~ file_path }
19
+ end
14
20
  end
15
21
 
16
- if RSpec::Version::STRING < '3'
17
- c.include RSpec::Puppet::DefineExampleGroup, :type => :define, :example_group => {
18
- :file_path => c.escaped_path(%w[spec defines])
19
- }
20
- c.include RSpec::Puppet::ClassExampleGroup, :type => :class, :example_group => {
21
- :file_path => c.escaped_path(%w[spec classes])
22
- }
23
- c.include RSpec::Puppet::FunctionExampleGroup, :type => :puppet_function, :example_group => {
24
- :file_path => c.escaped_path(%w[spec functions])
25
- }
26
- c.include RSpec::Puppet::HostExampleGroup, :type => :host, :example_group => {
27
- :file_path => c.escaped_path(%w[spec hosts])
28
- }
29
- c.include RSpec::Puppet::TypeExampleGroup, :type => :type, :example_group => {
30
- :file_path => c.escaped_path(%w[spec types])
31
- }
32
- c.include RSpec::Puppet::ProviderExampleGroup, :type => :provider, :example_group => {
33
- :file_path => c.escaped_path(%w[spec providers])
34
- }
35
- c.include RSpec::Puppet::ApplicationExampleGroup, :type => :application, :example_group => {
36
- :file_path => c.escaped_path(%w[spec applications])
37
- }
38
- else
39
- c.include RSpec::Puppet::DefineExampleGroup, :type => :define, :file_path => c.escaped_path(%w[spec defines])
40
- c.include RSpec::Puppet::ClassExampleGroup, :type => :class, :file_path => c.escaped_path(%w[spec classes])
41
- c.include RSpec::Puppet::FunctionExampleGroup, :type => :puppet_function, :file_path => c.escaped_path(%w[spec functions])
42
- c.include RSpec::Puppet::HostExampleGroup, :type => :host, :file_path => c.escaped_path(%w[spec hosts])
43
- c.include RSpec::Puppet::TypeExampleGroup, :type => :type, :file_path => c.escaped_path(%w[spec types])
44
- c.include RSpec::Puppet::ProviderExampleGroup, :type => :provider, :file_path => c.escaped_path(%w[spec providers])
45
- c.include RSpec::Puppet::ApplicationExampleGroup, :type => :application, :file_path => c.escaped_path(%w[spec applications])
46
- end
22
+ c.rspec_puppet_include RSpec::Puppet::DefineExampleGroup, :define, %w[spec defines]
23
+ c.rspec_puppet_include RSpec::Puppet::ClassExampleGroup, :class, %w[spec classes]
24
+ c.rspec_puppet_include RSpec::Puppet::FunctionExampleGroup, :puppet_function, %w[spec functions]
25
+ c.rspec_puppet_include RSpec::Puppet::HostExampleGroup, :host, %w[spec hosts]
26
+ c.rspec_puppet_include RSpec::Puppet::TypeExampleGroup, :type, %w[spec types]
27
+ c.rspec_puppet_include RSpec::Puppet::TypeAliasExampleGroup, :type_alias, %w[spec type_aliases]
28
+ c.rspec_puppet_include RSpec::Puppet::ProviderExampleGroup, :provider, %w[spec providers]
29
+ c.rspec_puppet_include RSpec::Puppet::ApplicationExampleGroup, :application, %w[spec applications]
47
30
 
48
31
  # Hook for each example group type to remove any caches or instance variables, since they will remain
49
32
  # and cause a memory leak. Can't be assigned per type by :file_path, so check for its presence.
@@ -0,0 +1,45 @@
1
+ module RSpec::Puppet
2
+ module TypeAliasMatchers
3
+ class AllowValue
4
+ def initialize(values)
5
+ @values = values
6
+ @error_msgs = []
7
+ end
8
+
9
+ def matches?(catalogue)
10
+ matches = @values.map do |test_value|
11
+ begin
12
+ catalogue.call(test_value)
13
+ true
14
+ rescue Puppet::Error => e
15
+ @error_msgs << e.message
16
+ false
17
+ end
18
+ end
19
+ matches.all?
20
+ end
21
+
22
+ def description
23
+ if @values.length == 1
24
+ "match value #{@values.first.inspect}"
25
+ else
26
+ "match values #{@values.map(&:inspect).join(', ')}"
27
+ end
28
+ end
29
+
30
+ def failure_message
31
+ "expected that the type alias would " + description + " but it raised the #{@error_msgs.length == 1 ? 'error' : 'errors'} #{@error_msgs.join(', ')}"
32
+ end
33
+
34
+ def failure_message_when_negated
35
+ "expected that the type alias would not " + description + " but it does"
36
+ end
37
+ end
38
+
39
+ def allow_value(*values)
40
+ RSpec::Puppet::TypeAliasMatchers::AllowValue.new(values)
41
+ end
42
+
43
+ alias_method :allow_values, :allow_value
44
+ end
45
+ end
@@ -108,6 +108,10 @@ module RSpec::Puppet
108
108
  if vertex[:alias]
109
109
  res_hash["#{vertex.type.to_s}[#{vertex[:alias]}]"] = 1
110
110
  end
111
+
112
+ if vertex.uniqueness_key != [vertex.title]
113
+ res_hash["#{vertex.type.to_s}[#{vertex.uniqueness_key.first}]"] = 1
114
+ end
111
115
  end
112
116
  end
113
117
  res_hash
@@ -134,6 +138,7 @@ module RSpec::Puppet
134
138
  end
135
139
 
136
140
  def cycles_found?
141
+ Puppet::Type.suppress_provider
137
142
  cat = @catalogue.to_ral.relationship_graph
138
143
  cat.write_graph(:resources)
139
144
  if cat.respond_to? :find_cycles_in_graph
@@ -141,6 +146,8 @@ module RSpec::Puppet
141
146
  else
142
147
  find_cycles_legacy(cat)
143
148
  end
149
+ Puppet::Type.unsuppress_provider
150
+
144
151
  !@cycles.empty?
145
152
  end
146
153
 
@@ -1,4 +1,6 @@
1
+ require 'set'
1
2
  require 'rspec-puppet/matchers/parameter_matcher'
3
+
2
4
  module RSpec::Puppet
3
5
  module ManifestMatchers
4
6
  class CreateGeneric
@@ -79,7 +81,7 @@ module RSpec::Puppet
79
81
 
80
82
  def matches?(catalogue)
81
83
  ret = true
82
- @catalogue = catalogue.call
84
+ @catalogue = catalogue.is_a?(Puppet::Resource::Catalog) ? catalogue : catalogue.call
83
85
  resource = @catalogue.resource(@referenced_type, @title)
84
86
 
85
87
  if resource.nil?
@@ -87,6 +89,17 @@ module RSpec::Puppet
87
89
  else
88
90
  RSpec::Puppet::Coverage.cover!(resource)
89
91
  rsrc_hsh = resource.to_hash
92
+
93
+ if resource.builtin_type?
94
+ namevar = resource.resource_type.key_attributes.first.to_s
95
+ else
96
+ namevar = 'name'
97
+ end
98
+
99
+ unless @expected_params.any? { |param| param.first.to_s == namevar }
100
+ rsrc_hsh.delete(namevar.to_sym) if rsrc_hsh.has_key?(namevar.to_sym)
101
+ end
102
+
90
103
  if @expected_params_count
91
104
  unless rsrc_hsh.size == @expected_params_count
92
105
  ret = false
@@ -201,7 +214,7 @@ module RSpec::Puppet
201
214
 
202
215
  def check_befores(catalogue, resource)
203
216
  @befores.each do |ref|
204
- unless precedes?(resource, catalogue.resource(ref))
217
+ unless precedes?(resource, canonicalize_resource(ref))
205
218
  @errors << BeforeRelationshipError.new(resource.to_ref, ref)
206
219
  end
207
220
  end
@@ -209,7 +222,7 @@ module RSpec::Puppet
209
222
 
210
223
  def check_requires(catalogue, resource)
211
224
  @requires.each do |ref|
212
- unless precedes?(catalogue.resource(ref), resource)
225
+ unless precedes?(canonicalize_resource(ref), resource)
213
226
  @errors << RequireRelationshipError.new(resource.to_ref, ref)
214
227
  end
215
228
  end
@@ -217,7 +230,7 @@ module RSpec::Puppet
217
230
 
218
231
  def check_notifies(catalogue, resource)
219
232
  @notifies.each do |ref|
220
- unless notifies?(resource, catalogue.resource(ref))
233
+ unless notifies?(resource, canonicalize_resource(ref))
221
234
  @errors << NotifyRelationshipError.new(resource.to_ref, ref)
222
235
  end
223
236
  end
@@ -225,7 +238,7 @@ module RSpec::Puppet
225
238
 
226
239
  def check_subscribes(catalogue, resource)
227
240
  @subscribes.each do |ref|
228
- unless notifies?(catalogue.resource(ref), resource)
241
+ unless notifies?(canonicalize_resource(ref), resource)
229
242
  @errors << SubscribeRelationshipError.new(resource.to_ref, ref)
230
243
  end
231
244
  end
@@ -240,34 +253,62 @@ module RSpec::Puppet
240
253
  end
241
254
 
242
255
  def canonicalize_resource(resource)
243
- resource_from_ref(resource_ref(resource))
256
+ res = resource_from_ref(resource_ref(resource))
257
+ if res.nil?
258
+ resource = Struct.new(:type, :title).new(*@catalogue.title_key_for_ref(resource)) if resource.is_a?(String)
259
+ res = @catalogue.resource_keys.select { |type, name|
260
+ type == resource.type
261
+ }.map { |type, name|
262
+ @catalogue.resource(type, name)
263
+ }.compact.find { |cat_res|
264
+ cat_res.builtin_type? && cat_res.uniqueness_key.first == resource.title
265
+ }
266
+ end
267
+ res
244
268
  end
245
269
 
246
270
  def canonicalize_resource_ref(ref)
247
271
  resource_ref(resource_from_ref(ref))
248
272
  end
249
273
 
250
- def relationship_refs(resource, type)
274
+ def relationship_refs(resource, type, visited = Set.new)
251
275
  resource = canonicalize_resource(resource)
252
- results = []
276
+ results = Set.new
253
277
  return results unless resource
278
+
279
+ # guard to prevent infinite recursion
280
+ if visited.include?(resource.object_id)
281
+ return [canonicalize_resource_ref(resource)]
282
+ else
283
+ visited << resource.object_id
284
+ end
285
+
254
286
  Array[resource[type]].flatten.compact.each do |r|
255
287
  results << canonicalize_resource_ref(r)
256
- results << relationship_refs(r, type)
288
+ results << relationship_refs(r, type, visited)
289
+
290
+ res = canonicalize_resource(r)
291
+ if res && res.builtin_type?
292
+ results << res.to_ref
293
+ results << "#{res.type.to_s.capitalize}[#{res.uniqueness_key.first}]"
294
+ end
257
295
  end
258
296
 
297
+ Puppet::Type.suppress_provider
259
298
  # Add autorequires if any
260
299
  if type == :require and resource.resource_type.respond_to? :eachautorequire
261
300
  resource.resource_type.eachautorequire do |t, b|
262
301
  Array(resource.to_ral.instance_eval(&b)).each do |dep|
263
302
  res = "#{t.to_s.capitalize}[#{dep}]"
264
- if r = relationship_refs(res, type)
303
+ if r = relationship_refs(res, type, visited)
265
304
  results << res
266
305
  results << r
267
306
  end
268
307
  end
269
308
  end
270
309
  end
310
+ Puppet::Type.unsuppress_provider
311
+
271
312
  results.flatten
272
313
  end
273
314
 
@@ -280,8 +321,8 @@ module RSpec::Puppet
280
321
 
281
322
  self_or_upstream(first).each do |u|
282
323
  self_or_upstream(second).each do |v|
283
- before_refs = relationship_refs(u, :before)
284
- require_refs = relationship_refs(v, :require)
324
+ before_refs = relationship_refs(u, :before) + relationship_refs(u, :notify)
325
+ require_refs = relationship_refs(v, :require) + relationship_refs(u, :subscribe)
285
326
 
286
327
  if before_refs.include?(v.to_ref) || require_refs.include?(u.to_ref) || (before_refs & require_refs).any?
287
328
  return true
@@ -320,7 +361,7 @@ module RSpec::Puppet
320
361
 
321
362
  if value.nil? then
322
363
  unless resource[param].nil?
323
- @errors << "#{param} undefined"
364
+ @errors << "#{param} undefined but it is set to #{resource[param].inspect}"
324
365
  end
325
366
  else
326
367
  m = ParameterMatcher.new(param, value, type)
@@ -30,7 +30,7 @@ module RSpec::Puppet
30
30
  # Puppet flattens an array with a single value into just the value and
31
31
  # this can cause confusion when testing as people expect when you put
32
32
  # an array in, you'll get an array out.
33
- actual = [*actual] if expected.is_a?(Array)
33
+ actual = [actual] if expected.is_a?(Array) && !actual.is_a?(Array)
34
34
 
35
35
  retval = check(expected, actual)
36
36
 
@@ -55,7 +55,7 @@ module RSpec::Puppet
55
55
  #
56
56
  # @return [true, false] If the resource matched
57
57
  def check(expected, actual)
58
- return false if actual.nil? && !expected.nil?
58
+ return false if !expected.is_a?(Proc) && actual.nil? && !expected.nil?
59
59
  case expected
60
60
  when Proc
61
61
  check_proc(expected, actual)
@@ -7,7 +7,7 @@ module RSpec::Puppet
7
7
  @has_returned = false
8
8
  begin
9
9
  # `*nil` does not evaluate to "no params" on ruby 1.8 :-(
10
- @actual_return = @params.nil? ? @func_obj.execute : @func_obj.execute(*@params)
10
+ @actual_return = @params.nil? ? @func_obj.execute(&@block) : @func_obj.execute(*@params, &@block)
11
11
  @has_returned = true
12
12
  rescue Exception => e
13
13
  @actual_error = e
@@ -52,6 +52,11 @@ module RSpec::Puppet
52
52
  self
53
53
  end
54
54
 
55
+ def with_lambda(&block)
56
+ @block = block
57
+ self
58
+ end
59
+
55
60
  def and_return(value)
56
61
  @has_expected_return = true
57
62
  @expected_return = value
@@ -5,3 +5,4 @@ require 'rspec-puppet/matchers/run'
5
5
  require 'rspec-puppet/matchers/count_generic'
6
6
  require 'rspec-puppet/matchers/dynamic_matchers'
7
7
  require 'rspec-puppet/matchers/type_matchers'
8
+ require 'rspec-puppet/matchers/allow_value'
@@ -0,0 +1,162 @@
1
+ require 'pathname'
2
+
3
+ module Puppet
4
+ # Allow rspec-puppet to prevent Puppet::Type from automatically picking
5
+ # a provider for a resource. We need to do this because in order to fully
6
+ # resolve the graph edges, we have to convert the Puppet::Resource objects
7
+ # into Puppet::Type objects so that their autorequires are evaluated. We need
8
+ # to prevent provider code from being called during this process as it's very
9
+ # platform specific.
10
+ class Type
11
+ old_set_default = instance_method(:set_default)
12
+
13
+ define_method(:set_default) do |attr|
14
+ old_posix = nil
15
+ old_microsoft_windows = nil
16
+
17
+ if attr == :provider
18
+ old_posix = Puppet.features.posix?
19
+ old_microsoft_windows = Puppet.features.microsoft_windows?
20
+
21
+ if Puppet::Util::Platform.pretend_windows?
22
+ Puppet.features.add(:posix) { false }
23
+ Puppet.features.add(:microsoft_windows) { true }
24
+ else
25
+ Puppet.features.add(:posix) { true }
26
+ Puppet.features.add(:microsoft_windows) { false }
27
+ end
28
+ end
29
+
30
+ retval = old_set_default.bind(self).call(attr)
31
+
32
+ unless old_posix.nil?
33
+ Puppet.features.add(:posix) { old_posix }
34
+ end
35
+ unless old_microsoft_windows.nil?
36
+ Puppet.features.add(:microsoft_windows) { old_microsoft_windows }
37
+ end
38
+
39
+ retval
40
+ end
41
+
42
+ def self.suppress_provider?
43
+ @suppress_provider ||= false
44
+ end
45
+
46
+ def self.suppress_provider
47
+ @suppress_provider = true
48
+ end
49
+
50
+ def self.unsuppress_provider
51
+ @suppress_provider = false
52
+ end
53
+ end
54
+
55
+ # If Puppet::Node::Environment has a validate_dirs instance method (i.e.
56
+ # Puppet < 3.x), wrap the method to check if rspec-puppet is pretending to be
57
+ # running under windows. The original method uses Puppet::Util.absolute_path?
58
+ # (which in turn calls Puppet::Util::Platform.windows?) to validate the path
59
+ # to the manifests on disk during compilation, so we have to temporarily
60
+ # disable the pretending when running it.
61
+ class Node::Environment
62
+ if instance_methods.include?("validate_dirs")
63
+ old_validate_dirs = instance_method(:validate_dirs)
64
+
65
+ define_method(:validate_dirs) do |dirs|
66
+ pretending = Puppet::Util::Platform.pretend_platform
67
+
68
+ if pretending
69
+ Puppet::Util::Platform.pretend_to_be nil
70
+ end
71
+
72
+ output = old_validate_dirs.bind(self).call(dirs)
73
+
74
+ Puppet::Util::Platform.pretend_to_be pretending
75
+
76
+ output
77
+ end
78
+ end
79
+ end
80
+
81
+ module Util
82
+ # Allow rspec-puppet to pretend to be different platforms.
83
+ module Platform
84
+ def windows?
85
+ pretend_platform.nil? ? (actual_platform == :windows) : pretend_windows?
86
+ end
87
+ module_function :windows?
88
+
89
+ def actual_platform
90
+ @actual_platform ||= !!File::ALT_SEPARATOR ? :windows : :posix
91
+ end
92
+ module_function :actual_platform
93
+
94
+ def pretend_windows?
95
+ pretend_platform == :windows
96
+ end
97
+ module_function :pretend_windows?
98
+
99
+ def pretend_to_be(platform)
100
+ # Ensure that we cache the real platform before pretending to be
101
+ # a different one
102
+ actual_platform
103
+
104
+ @pretend_platform = platform
105
+ end
106
+ module_function :pretend_to_be
107
+
108
+ def pretend_platform
109
+ @pretend_platform ||= nil
110
+ end
111
+ module_function :pretend_platform
112
+ end
113
+ end
114
+ end
115
+
116
+ class Pathname
117
+ def rspec_puppet_basename(path)
118
+ raise ArgumentError, 'pathname stubbing not enabled' unless RSpec.configuration.enable_pathname_stubbing
119
+
120
+ if path =~ /\A[a-zA-Z]:(#{SEPARATOR_PAT}.*)\z/
121
+ path = path[2..-1]
122
+ end
123
+ path.split(SEPARATOR_PAT).last || path[/(#{SEPARATOR_PAT})/, 1] || path
124
+ end
125
+
126
+ if instance_methods.include?("chop_basename")
127
+ old_chop_basename = instance_method(:chop_basename)
128
+
129
+ define_method(:chop_basename) do |path|
130
+ if RSpec.configuration.enable_pathname_stubbing
131
+ base = rspec_puppet_basename(path)
132
+ if /\A#{SEPARATOR_PAT}?\z/o =~ base
133
+ return nil
134
+ else
135
+ return path[0, path.rindex(base)], base
136
+ end
137
+ else
138
+ old_chop_basename.bind(self).call(path)
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ # Prevent the File type from munging paths (which uses File.expand_path to
145
+ # normalise paths, which does very bad things to *nix paths on Windows.
146
+ Puppet::Type.type(:file).paramclass(:path).munge { |value| value }
147
+
148
+ # Prevent the Exec type from validating the user. This parameter isn't
149
+ # supported under Windows at all and only under *nix when the current user is
150
+ # root.
151
+ Puppet::Type.type(:exec).paramclass(:user).validate { |value| true }
152
+
153
+ # Prevent Puppet from requiring 'puppet/util/windows' if we're pretending to be
154
+ # windows, otherwise it will require other libraries that probably won't be
155
+ # available on non-windows hosts.
156
+ module Kernel
157
+ alias :old_require :require
158
+ def require(path)
159
+ return if path == 'puppet/util/windows' && Puppet::Util::Platform.pretend_windows?
160
+ old_require(path)
161
+ end
162
+ end