1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
|
#!/usr/bin/env ruby
$:.unshift("../../lib") if __FILE__ =~ /\.rb$/
require 'puppettest'
class TestProperty < Test::Unit::TestCase
include PuppetTest
def newinst(property, resource = nil)
inst = nil
unless resource
resource = "fakeresource"
resource.meta_def(:pathbuilder) do [self.to_s] end
resource.meta_def(:provider) do nil end
resource.meta_def(:fakeproperty) do '' end
end
assert_nothing_raised {
newinst = property.new(:resource => resource)
def newinst.retrieve(); return @fakeprovidervalue; end;
return newinst
}
end
def newproperty(name = :fakeproperty)
property = Class.new(Puppet::Property) do
@name = name
end
Object.const_set("FakeProperty", property)
property.initvars
cleanup do
Object.send(:remove_const, "FakeProperty")
end
return property
end
def newmodel(name)
# Create an object that responds to myproperty as an attr
provklass = Class.new { attr_accessor name
def pathbuilder
["provklass"]
end
}
prov = provklass.new
klass = Class.new { attr_accessor :provider, :path
def pathbuilder
["instklass"]
end
}
klassinst = klass.new
klassinst.path = "instpath"
klassinst.provider = prov
return prov, klassinst
end
# Make sure we correctly look up names.
def test_value_name
property = newproperty()
property.newvalue(:one)
property.newvalue(/\d+/)
name = nil
["one", :one].each do |value|
assert_nothing_raised do
name = property.value_name(value)
end
assert_equal(:one, name)
end
["42"].each do |value|
assert_nothing_raised do
name = property.value_name(value)
end
assert_equal(/\d+/, name)
end
# these values should not have a name
["two", :three, ''].each do |value|
assert_nothing_raised do
name = property.value_name(value)
end
assert_nil(name)
end
end
# Test that we correctly look up options for values.
def test_value_option
property = newproperty()
options = {
:one => {:event => :yay, :call => :before},
/\d+/ => {:event => :fun, :call => :instead}
}
property.newvalue(:one, options[:one])
property.newvalue(/\d+/, options[/\d+/])
options.each do |name, opts|
opts.each do |param, value|
assert_equal(value, property.value_option(name, param))
end
end
end
def test_newvalue
property = newproperty()
# These are bogus because they don't define events. :/
assert_nothing_raised {
property.newvalue(:one) do
@fakeprovidervalue = 1
end
}
assert_nothing_raised {
property.newvalue("two") do
@fakeprovidervalue = 2
end
}
# Make sure we default to using the block instead
assert_equal(:instead, property.value_option(:one, :call),
":call was not set to :instead when a block was provided")
inst = newinst(property)
assert_nothing_raised {
inst.should = "one"
}
assert_equal(:one, inst.should)
ret = nil
assert_nothing_raised { inst.set_one }
assert_equal(1, inst.retrieve)
assert_nothing_raised {
inst.should = :two
}
assert_equal(:two, inst.should)
assert_nothing_raised { inst.set_two }
assert_equal(2, inst.retrieve)
end
def test_newpropertyvaluewithregexes
property = newproperty()
assert_nothing_raised {
property.newvalue(/^\w+$/) do
return :regex_matched
end
}
inst = newinst(property)
assert_nothing_raised {
inst.should = "yayness"
}
assert_equal("yayness", inst.should)
assert_nothing_raised {
inst.sync
}
assert_equal("yayness".upcase, inst.retrieve)
end
def test_newvalue_event_option
property = newproperty()
assert_nothing_raised do
property.newvalue(:myvalue, :event => :fake_valued) do
end
property.newvalue(:other, :event => "fake_other") do
end
end
inst = newinst(property)
assert_nothing_raised {
inst.should = :myvalue
}
ret = nil
assert_nothing_raised {
ret = inst.sync
}
assert_equal(:fake_valued, ret,
"Event did not get returned correctly")
assert_nothing_raised {
inst.should = :other
}
assert_nothing_raised {
ret = inst.sync
}
assert_equal(:fake_other, ret,
"Event did not get returned correctly")
end
# We want to support values with no blocks, either regexes or strings.
# If there's no block provided, then we should call the provider mechanism
# like we would normally.
def test_newvalue_with_no_block
property = newproperty(:myproperty)
assert_nothing_raised {
property.newvalue(:value, :event => :matched_value)
}
assert_nothing_raised {
property.newvalue(/^\d+$/, :event => :matched_number)
}
assert_equal(:none, property.value_option(:value, :call),
":call was not set to none when no block is provided")
prov, klassinst = newmodel(:myproperty)
inst = newinst(property, klassinst)
# Now make sure we can set the values, they get validated as normal,
# and they set the values on the resource rather than trying to call
# a method
{:value => :matched_value, "27" => :matched_number}.each do |value, event|
assert_nothing_raised do
inst.should = value
end
ret = nil
assert_nothing_raised do
ret = inst.sync
end
assert_equal(event, ret, "Did not return correct event for %s" % value)
assert_equal(value, prov.myproperty, "%s was not set right" % value)
end
# And make sure we still fail validations
assert_raise(ArgumentError) do
inst.should = "invalid"
end
end
def test_tags
obj = "yay"
metaobj = class << obj; self; end
metaobj.send(:attr_accessor, :tags)
tags = [:some, :tags, :for, :testing]
obj.tags = tags
propertyklass = newproperty
inst = nil
assert_nothing_raised do
inst = propertyklass.new(:resource => obj)
end
assert_nothing_raised do
assert_equal(tags + [inst.name], inst.tags)
end
end
def test_failure
s = Struct.new(:line, :file, :path, :pathbuilder, :name)
p = s.new(1, "yay", "rah", "struct", "name")
myprovider = Class.new(Puppet::Provider)
def p.provider; nil; end;
myproperty = Class.new(Puppet::Property) do
@name = 'name'
end
myproperty.initvars
myproperty.newvalue :mkfailure do
raise "It's all broken"
end
property = myproperty.new(:resource => p)
assert_raise(Puppet::Error) do
property.set(:mkfailure)
end
end
# Make sure 'set' behaves correctly WRT to call order. This tests that the
# :call value is handled correctly in all cases.
def test_set
property = newproperty(:myproperty)
$setting = []
newval = proc do |name, call|
options = {}
if call
options[:call] = name
block = proc { $setting << name }
end
assert_nothing_raised("Could not create %s value" % name) {
if block
property.newvalue(name, options, &block)
else
property.newvalue(name, options)
end
}
end
newval.call(:none, false)
# Create a value with no block; it should default to :none
newval.call(:before, true)
# One with a block but after
newval.call(:after, true)
# One with an explicit instead
newval.call(:instead, true)
# And one with an implicit instead
assert_nothing_raised do
property.newvalue(:implicit) do
$setting << :implicit
end
end
# Now create a provider
prov, model = newmodel(:myproperty)
inst = newinst(property, model)
# Mark when we're called
prov.meta_def(:myproperty=) do |value| $setting << :provider end
# Now run through the list and make sure everything is correct
{:before => [:before, :provider],
:after => [:provider, :after],
:instead => [:instead],
:none => [:provider],
:implicit => [:implicit]
}.each do |name, result|
inst.set(name)
assert_equal(result, $setting, "%s was not handled right" % name)
$setting.clear
end
end
# Make sure we can specify that we want to use the whole array, rather
# than just individual values.
def test_array_handling
property = newproperty(:arraytests)
prov, model = newmodel(:array_testing)
inst = newinst(property, model)
# Make sure it defaults to first
assert_equal(:first, property.array_matching, "Property did not default to matching first value in an array")
assert(! inst.match_all?, "match_all? returned true when array_matching is :first")
vals = %w{one two three}
inst.should = vals
# Make sure we only get the first value back
assert_equal("one", inst.should, "Returned wrong value when array_matching == first")
# And make sure any of these values is considered in sync
vals.each do |value|
assert(inst.insync?(value), "#{value} was not considered in sync when array_matching == first")
end
# Now change it to all
property.array_matching = :all
assert_equal(:all, property.array_matching, "Property did not change value of array_matching")
assert(inst.match_all?, "match_all? returned false when array_matching is :all")
# Make sure we only get the first value back
assert_equal(vals, inst.should, "Returned wrong value when array_matching == all")
# And make sure any of these values is considered in sync
%w{one two three}.each do |value|
assert(! inst.insync?(value), "individual value #{value} was considered in sync when array_matching == all")
end
assert(inst.insync?(vals), "value array was not considered in sync when array_matching == all")
end
end
|