rspec-puppet 2.5.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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