summaryrefslogtreecommitdiffstats
path: root/test/ral/types/property.rb
blob: 11975da096f14c75757a599c7caecb55fa332102 (plain)
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