~ubuntu-branches/ubuntu/oneiric/puppet/oneiric-security

« back to all changes in this revision

Viewing changes to spec/unit/indirector/indirection.rb

  • Committer: Bazaar Package Importer
  • Author(s): Micah Anderson
  • Date: 2008-07-26 15:43:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20080726154345-1fmgo76b4l72ulvc
ImportĀ upstreamĀ versionĀ 0.24.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env ruby
 
2
 
 
3
require File.dirname(__FILE__) + '/../../spec_helper'
 
4
 
 
5
require 'puppet/indirector/indirection'
 
6
 
 
7
describe "Indirection Delegator", :shared => true do
 
8
    it "should create a request object with the appropriate method name and all of the passed arguments" do
 
9
        request = stub 'request', :node => nil
 
10
 
 
11
        @indirection.expects(:request).with(@method, "mystuff", :one => :two).returns request
 
12
 
 
13
        @terminus.stubs(@method)
 
14
 
 
15
        @indirection.send(@method, "mystuff", :one => :two)
 
16
    end
 
17
 
 
18
    it "should let the :select_terminus method choose the terminus using the created request if the :select_terminus method is available" do
 
19
        # Define the method, so our respond_to? hook matches.
 
20
        class << @indirection
 
21
            def select_terminus(request)
 
22
            end
 
23
        end
 
24
 
 
25
        request = stub 'request', :key => "me", :options => {}
 
26
 
 
27
        @indirection.stubs(:request).returns request
 
28
 
 
29
        @indirection.expects(:select_terminus).with(request).returns :test_terminus
 
30
 
 
31
        @indirection.stubs(:check_authorization)
 
32
        @terminus.expects(@method)
 
33
 
 
34
        @indirection.send(@method, "me")
 
35
    end
 
36
 
 
37
    it "should choose the terminus returned by the :terminus_class method if no :select_terminus method is available" do
 
38
        @indirection.expects(:terminus_class).returns :test_terminus
 
39
 
 
40
        @terminus.expects(@method)
 
41
 
 
42
        @indirection.send(@method, "me")
 
43
    end
 
44
 
 
45
    it "should let the appropriate terminus perform the lookup" do
 
46
        @terminus.expects(@method).with { |r| r.is_a?(Puppet::Indirector::Request) }
 
47
        @indirection.send(@method, "me")
 
48
    end
 
49
end
 
50
 
 
51
describe "Delegation Authorizer", :shared => true do
 
52
    before do
 
53
        # So the :respond_to? turns out correctly.
 
54
        class << @terminus
 
55
            def authorized?
 
56
            end
 
57
        end
 
58
    end
 
59
 
 
60
    it "should not check authorization if a node name is not provided" do
 
61
        @terminus.expects(:authorized?).never
 
62
        @terminus.stubs(@method)
 
63
 
 
64
        # The quotes are necessary here, else it looks like a block.
 
65
        @request.stubs(:options).returns({})
 
66
        @indirection.send(@method, "/my/key")
 
67
    end
 
68
 
 
69
    it "should pass the request to the terminus's authorization method" do
 
70
        @terminus.expects(:authorized?).with { |r| r.is_a?(Puppet::Indirector::Request) }.returns(true)
 
71
        @terminus.stubs(@method)
 
72
 
 
73
        @indirection.send(@method, "/my/key", :node => "mynode")
 
74
    end
 
75
 
 
76
    it "should fail if authorization returns false" do
 
77
        @terminus.expects(:authorized?).returns(false)
 
78
        @terminus.stubs(@method)
 
79
        proc { @indirection.send(@method, "/my/key", :node => "mynode") }.should raise_error(ArgumentError)
 
80
    end
 
81
 
 
82
    it "should continue if authorization returns true" do
 
83
        @terminus.expects(:authorized?).returns(true)
 
84
        @terminus.stubs(@method)
 
85
        @indirection.send(@method, "/my/key", :node => "mynode")
 
86
    end
 
87
end
 
88
 
 
89
describe Puppet::Indirector::Indirection do
 
90
    describe "when initializing" do
 
91
        # (LAK) I've no idea how to test this, really.
 
92
        it "should store a reference to itself before it consumes its options" do
 
93
            proc { @indirection = Puppet::Indirector::Indirection.new(Object.new, :testingness, :not_valid_option) }.should raise_error
 
94
            Puppet::Indirector::Indirection.instance(:testingness).should be_instance_of(Puppet::Indirector::Indirection)
 
95
            Puppet::Indirector::Indirection.instance(:testingness).delete
 
96
        end
 
97
 
 
98
        it "should keep a reference to the indirecting model" do
 
99
            model = mock 'model'
 
100
            @indirection = Puppet::Indirector::Indirection.new(model, :myind)
 
101
            @indirection.model.should equal(model)
 
102
        end
 
103
 
 
104
        it "should set the name" do
 
105
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind)
 
106
            @indirection.name.should == :myind
 
107
        end
 
108
 
 
109
        it "should require indirections to have unique names" do
 
110
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
111
            proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError)
 
112
        end
 
113
 
 
114
        it "should extend itself with any specified module" do
 
115
            mod = Module.new
 
116
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test, :extend => mod)
 
117
            @indirection.metaclass.included_modules.should include(mod)
 
118
        end
 
119
 
 
120
        after do
 
121
            @indirection.delete if defined? @indirection
 
122
        end
 
123
    end
 
124
 
 
125
    describe "when an instance" do
 
126
        before :each do
 
127
            @terminus_class = mock 'terminus_class'
 
128
            @terminus = mock 'terminus'
 
129
            @terminus_class.stubs(:new).returns(@terminus)
 
130
            @cache = mock 'cache'
 
131
            @cache_class = mock 'cache_class'
 
132
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
 
133
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
 
134
 
 
135
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
136
            @indirection.terminus_class = :test_terminus
 
137
 
 
138
            @instance = stub 'instance', :expiration => nil, :expiration= => nil, :name => "whatever"
 
139
            @name = :mything
 
140
 
 
141
            #@request = stub 'instance', :key => "/my/key", :instance => @instance, :options => {}
 
142
            @request = mock 'instance'
 
143
        end
 
144
 
 
145
        it "should allow setting the ttl" do
 
146
            @indirection.ttl = 300
 
147
            @indirection.ttl.should == 300
 
148
        end
 
149
 
 
150
        it "should default to the :runinterval setting, converted to an integer, for its ttl" do
 
151
            Puppet.settings.expects(:value).returns "1800"
 
152
            @indirection.ttl.should == 1800
 
153
        end
 
154
 
 
155
        it "should calculate the current expiration by adding the TTL to the current time" do
 
156
            @indirection.stubs(:ttl).returns(100)
 
157
            now = Time.now
 
158
            Time.stubs(:now).returns now
 
159
            @indirection.expiration.should == (Time.now + 100)
 
160
        end
 
161
 
 
162
        it "should have a method for creating an indirection request instance" do
 
163
            @indirection.should respond_to(:request)
 
164
        end
 
165
 
 
166
        describe "creates a request" do
 
167
            it "should create it with its name as the request's indirection name" do
 
168
                Puppet::Indirector::Request.expects(:new).with { |name, *other| @indirection.name == name }
 
169
                @indirection.request(:funtest, "yayness")
 
170
            end
 
171
 
 
172
            it "should require a method and key" do
 
173
                Puppet::Indirector::Request.expects(:new).with { |name, method, key, *other| method == :funtest and key == "yayness" }
 
174
                @indirection.request(:funtest, "yayness")
 
175
            end
 
176
 
 
177
            it "should support optional arguments" do
 
178
                Puppet::Indirector::Request.expects(:new).with { |name, method, key, other| other == {:one => :two} }
 
179
                @indirection.request(:funtest, "yayness", :one => :two)
 
180
            end
 
181
 
 
182
            it "should default to the arguments being nil" do
 
183
                Puppet::Indirector::Request.expects(:new).with { |name, method, key, args| args.nil? }
 
184
                @indirection.request(:funtest, "yayness")
 
185
            end
 
186
 
 
187
            it "should return the request" do
 
188
                request = mock 'request'
 
189
                Puppet::Indirector::Request.expects(:new).returns request
 
190
                @indirection.request(:funtest, "yayness").should equal(request)
 
191
            end
 
192
        end
 
193
      
 
194
        describe "and looking for a model instance" do
 
195
            before { @method = :find }
 
196
 
 
197
            it_should_behave_like "Indirection Delegator"
 
198
            it_should_behave_like "Delegation Authorizer"
 
199
 
 
200
            it "should return the results of the delegation" do
 
201
                @terminus.expects(:find).returns(@instance)
 
202
                @indirection.find("me").should equal(@instance)
 
203
            end
 
204
 
 
205
            it "should set the expiration date on any instances without one set" do
 
206
                @terminus.stubs(:find).returns(@instance)
 
207
 
 
208
                @indirection.expects(:expiration).returns :yay
 
209
 
 
210
                @instance.expects(:expiration).returns(nil)
 
211
                @instance.expects(:expiration=).with(:yay)
 
212
 
 
213
                @indirection.find("/my/key")
 
214
            end
 
215
 
 
216
            it "should not override an already-set expiration date on returned instances" do
 
217
                @terminus.stubs(:find).returns(@instance)
 
218
 
 
219
                @indirection.expects(:expiration).never
 
220
 
 
221
                @instance.expects(:expiration).returns(:yay)
 
222
                @instance.expects(:expiration=).never
 
223
 
 
224
                @indirection.find("/my/key")
 
225
            end
 
226
 
 
227
            describe "when caching is enabled" do
 
228
                before do
 
229
                    @indirection.cache_class = :cache_terminus
 
230
                    @cache_class.expects(:new).returns(@cache)
 
231
 
 
232
                    @instance.stubs(:expired?).returns false
 
233
                end
 
234
 
 
235
                it "should first look in the cache for an instance" do
 
236
                    @terminus.stubs(:find).never
 
237
                    @cache.expects(:find).returns @instance
 
238
 
 
239
                    @indirection.find("/my/key")
 
240
                end
 
241
 
 
242
                it "should use a request to look in the cache for cached objects" do
 
243
                    @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns @instance
 
244
 
 
245
                    @cache.stubs(:save)
 
246
 
 
247
                    @indirection.find("/my/key")
 
248
                end
 
249
 
 
250
                it "should return the cached object if it is not expired" do
 
251
                    @instance.stubs(:expired?).returns false
 
252
 
 
253
                    @cache.stubs(:find).returns @instance
 
254
                    @indirection.find("/my/key").should equal(@instance)
 
255
                end
 
256
 
 
257
                it "should send a debug log if it is using the cached object" do
 
258
                    Puppet.expects(:debug)
 
259
                    @cache.stubs(:find).returns @instance
 
260
 
 
261
                    @indirection.find("/my/key")
 
262
                end
 
263
 
 
264
                it "should not return the cached object if it is expired" do
 
265
                    @instance.stubs(:expired?).returns true
 
266
 
 
267
                    @cache.stubs(:find).returns @instance
 
268
                    @terminus.stubs(:find).returns nil
 
269
                    @indirection.find("/my/key").should be_nil
 
270
                end
 
271
 
 
272
                it "should send an info log if it is using the cached object" do
 
273
                    Puppet.expects(:info)
 
274
                    @instance.stubs(:expired?).returns true
 
275
 
 
276
                    @cache.stubs(:find).returns @instance
 
277
                    @terminus.stubs(:find).returns nil
 
278
                    @indirection.find("/my/key")
 
279
                end
 
280
 
 
281
                it "should cache any objects not retrieved from the cache" do
 
282
                    @cache.expects(:find).returns nil
 
283
 
 
284
                    @terminus.expects(:find).returns(@instance)
 
285
                    @cache.expects(:save)
 
286
 
 
287
                    @indirection.find("/my/key")
 
288
                end
 
289
 
 
290
                it "should use a request to look in the cache for cached objects" do
 
291
                    @cache.expects(:find).with { |r| r.method == :find and r.key == "/my/key" }.returns nil
 
292
 
 
293
                    @terminus.stubs(:find).returns(@instance)
 
294
                    @cache.stubs(:save)
 
295
 
 
296
                    @indirection.find("/my/key")
 
297
                end
 
298
 
 
299
                it "should cache the instance using a request with the instance set to the cached object" do
 
300
                    @cache.stubs(:find).returns nil
 
301
 
 
302
                    @terminus.stubs(:find).returns(@instance)
 
303
 
 
304
                    @cache.expects(:save).with { |r| r.method == :save and r.instance == @instance }
 
305
 
 
306
                    @indirection.find("/my/key")
 
307
                end
 
308
 
 
309
                it "should send an info log that the object is being cached" do
 
310
                    @cache.stubs(:find).returns nil
 
311
 
 
312
                    @terminus.stubs(:find).returns(@instance)
 
313
                    @cache.stubs(:save)
 
314
 
 
315
                    Puppet.expects(:info)
 
316
 
 
317
                    @indirection.find("/my/key")
 
318
                end
 
319
            end
 
320
        end
 
321
 
 
322
        describe "and storing a model instance" do
 
323
            before { @method = :save }
 
324
 
 
325
            it_should_behave_like "Indirection Delegator"
 
326
            it_should_behave_like "Delegation Authorizer"
 
327
 
 
328
            it "should return nil" do
 
329
                @terminus.stubs(:save)
 
330
                @indirection.save(@instance).should be_nil
 
331
            end
 
332
 
 
333
            describe "when caching is enabled" do
 
334
                before do
 
335
                    @indirection.cache_class = :cache_terminus
 
336
                    @cache_class.expects(:new).returns(@cache)
 
337
 
 
338
                    @instance.stubs(:expired?).returns false
 
339
                end
 
340
 
 
341
                it "should use a request to save the object to the cache" do
 
342
                    request = stub 'request', :instance => @instance, :node => nil
 
343
 
 
344
                    @indirection.expects(:request).returns request
 
345
 
 
346
                    @cache.expects(:save).with(request)
 
347
                    @terminus.stubs(:save)
 
348
                    @indirection.save(@instance)
 
349
                end
 
350
            end
 
351
        end
 
352
        
 
353
        describe "and removing a model instance" do
 
354
            before { @method = :destroy }
 
355
 
 
356
            it_should_behave_like "Indirection Delegator"
 
357
            it_should_behave_like "Delegation Authorizer"
 
358
 
 
359
            it "should return the result of removing the instance" do
 
360
                @terminus.stubs(:destroy).returns "yayness"
 
361
                @indirection.destroy("/my/key").should == "yayness"
 
362
            end
 
363
 
 
364
            describe "when caching is enabled" do
 
365
                before do
 
366
                    @indirection.cache_class = :cache_terminus
 
367
                    @cache_class.expects(:new).returns(@cache)
 
368
 
 
369
                    @instance.stubs(:expired?).returns false
 
370
                end
 
371
 
 
372
                it "should use a request instance to search in and remove objects from the cache" do
 
373
                    destroy = stub 'destroy_request', :key => "/my/key", :node => nil
 
374
                    find = stub 'destroy_request', :key => "/my/key", :node => nil
 
375
 
 
376
                    @indirection.expects(:request).with(:destroy, "/my/key").returns destroy
 
377
                    @indirection.expects(:request).with(:find, "/my/key").returns find
 
378
 
 
379
                    cached = mock 'cache'
 
380
 
 
381
                    @cache.expects(:find).with(find).returns cached
 
382
                    @cache.expects(:destroy).with(destroy)
 
383
 
 
384
                    @terminus.stubs(:destroy)
 
385
 
 
386
                    @indirection.destroy("/my/key")
 
387
                end
 
388
            end
 
389
        end
 
390
 
 
391
        describe "and searching for multiple model instances" do
 
392
            before { @method = :search }
 
393
 
 
394
            it_should_behave_like "Indirection Delegator"
 
395
            it_should_behave_like "Delegation Authorizer"
 
396
 
 
397
            it "should set the expiration date on any instances without one set" do
 
398
                @terminus.stubs(:search).returns([@instance])
 
399
 
 
400
                @indirection.expects(:expiration).returns :yay
 
401
 
 
402
                @instance.expects(:expiration).returns(nil)
 
403
                @instance.expects(:expiration=).with(:yay)
 
404
 
 
405
                @indirection.search("/my/key")
 
406
            end
 
407
 
 
408
            it "should not override an already-set expiration date on returned instances" do
 
409
                @terminus.stubs(:search).returns([@instance])
 
410
 
 
411
                @indirection.expects(:expiration).never
 
412
 
 
413
                @instance.expects(:expiration).returns(:yay)
 
414
                @instance.expects(:expiration=).never
 
415
 
 
416
                @indirection.search("/my/key")
 
417
            end
 
418
 
 
419
            it "should return the results of searching in the terminus" do
 
420
                @terminus.expects(:search).returns([@instance])
 
421
                @indirection.search("/my/key").should == [@instance]
 
422
            end
 
423
        end
 
424
 
 
425
        describe "and expiring a model instance" do
 
426
            describe "when caching is not enabled" do
 
427
                it "should do nothing" do
 
428
                    @cache_class.expects(:new).never
 
429
 
 
430
                    @indirection.expire("/my/key")
 
431
                end
 
432
            end
 
433
 
 
434
            describe "when caching is enabled" do
 
435
                before do
 
436
                    @indirection.cache_class = :cache_terminus
 
437
                    @cache_class.expects(:new).returns(@cache)
 
438
 
 
439
                    @instance.stubs(:expired?).returns false
 
440
 
 
441
                    @cached = stub 'cached', :expiration= => nil, :name => "/my/key"
 
442
                end
 
443
 
 
444
                it "should use a request to find within the cache" do
 
445
                    @cache.expects(:find).with { |r| r.is_a?(Puppet::Indirector::Request) and r.method == :find }
 
446
                    @indirection.expire("/my/key")
 
447
                end
 
448
 
 
449
                it "should do nothing if no such instance is cached" do
 
450
                    @cache.expects(:find).returns nil
 
451
 
 
452
                    @indirection.expire("/my/key")
 
453
                end
 
454
 
 
455
                it "should log that it is expiring any found instance" do
 
456
                    @cache.expects(:find).returns @cached
 
457
                    @cache.stubs(:save)
 
458
 
 
459
                    Puppet.expects(:info)
 
460
 
 
461
                    @indirection.expire("/my/key")
 
462
                end
 
463
 
 
464
                it "should set the cached instance's expiration to a time in the past" do
 
465
                    @cache.expects(:find).returns @cached
 
466
                    @cache.stubs(:save)
 
467
 
 
468
                    @cached.expects(:expiration=).with { |t| t < Time.now }
 
469
 
 
470
                    @indirection.expire("/my/key")
 
471
                end
 
472
 
 
473
                it "should save the now expired instance back into the cache" do
 
474
                    @cache.expects(:find).returns @cached
 
475
 
 
476
                    @cached.expects(:expiration=).with { |t| t < Time.now }
 
477
 
 
478
                    @cache.expects(:save)
 
479
 
 
480
                    @indirection.expire("/my/key")
 
481
                end
 
482
 
 
483
                it "should use a request to save the expired resource to the cache" do
 
484
                    @cache.expects(:find).returns @cached
 
485
 
 
486
                    @cached.expects(:expiration=).with { |t| t < Time.now }
 
487
 
 
488
                    @cache.expects(:save).with { |r| r.is_a?(Puppet::Indirector::Request) and r.instance == @cached and r.method == :save }.returns(@cached)
 
489
 
 
490
                    @indirection.expire("/my/key")
 
491
                end
 
492
            end
 
493
        end
 
494
 
 
495
        after :each do
 
496
            @indirection.delete
 
497
            Puppet::Indirector::Indirection.clear_cache
 
498
        end
 
499
    end
 
500
 
 
501
 
 
502
    describe "when managing indirection instances" do
 
503
        it "should allow an indirection to be retrieved by name" do
 
504
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
505
            Puppet::Indirector::Indirection.instance(:test).should equal(@indirection)
 
506
        end
 
507
        
 
508
        it "should return nil when the named indirection has not been created" do
 
509
            Puppet::Indirector::Indirection.instance(:test).should be_nil
 
510
        end
 
511
 
 
512
        it "should allow an indirection's model to be retrieved by name" do
 
513
            mock_model = mock('model')
 
514
            @indirection = Puppet::Indirector::Indirection.new(mock_model, :test)
 
515
            Puppet::Indirector::Indirection.model(:test).should equal(mock_model)
 
516
        end
 
517
        
 
518
        it "should return nil when no model matches the requested name" do
 
519
            Puppet::Indirector::Indirection.model(:test).should be_nil
 
520
        end
 
521
 
 
522
        after do
 
523
            @indirection.delete if defined? @indirection
 
524
        end
 
525
    end
 
526
 
 
527
    describe "when routing to the correct the terminus class" do
 
528
        before do
 
529
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
530
            @terminus = mock 'terminus'
 
531
            @terminus_class = stub 'terminus class', :new => @terminus
 
532
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :default).returns(@terminus_class)
 
533
        end
 
534
 
 
535
        it "should fail if no terminus class can be picked" do
 
536
            proc { @indirection.terminus_class }.should raise_error(Puppet::DevError)
 
537
        end
 
538
 
 
539
        it "should choose the default terminus class if one is specified" do
 
540
            @indirection.terminus_class = :default
 
541
            @indirection.terminus_class.should equal(:default)
 
542
        end
 
543
 
 
544
        it "should use the provided Puppet setting if told to do so" do
 
545
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :my_terminus).returns(mock("terminus_class2"))
 
546
            Puppet.settings.expects(:value).with(:my_setting).returns("my_terminus")
 
547
            @indirection.terminus_setting = :my_setting
 
548
            @indirection.terminus_class.should equal(:my_terminus)
 
549
        end
 
550
 
 
551
        it "should fail if the provided terminus class is not valid" do
 
552
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :nosuchclass).returns(nil)
 
553
            proc { @indirection.terminus_class = :nosuchclass }.should raise_error(ArgumentError)
 
554
        end
 
555
 
 
556
        after do
 
557
            @indirection.delete if defined? @indirection
 
558
        end
 
559
    end
 
560
 
 
561
    describe "when specifying the terminus class to use" do
 
562
        before do
 
563
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
564
            @terminus = mock 'terminus'
 
565
            @terminus_class = stub 'terminus class', :new => @terminus
 
566
        end
 
567
 
 
568
        it "should allow specification of a terminus type" do
 
569
            @indirection.should respond_to(:terminus_class=)
 
570
        end
 
571
 
 
572
        it "should fail to redirect if no terminus type has been specified" do
 
573
            proc { @indirection.find("blah") }.should raise_error(Puppet::DevError)
 
574
        end
 
575
 
 
576
        it "should fail when the terminus class name is an empty string" do
 
577
            proc { @indirection.terminus_class = "" }.should raise_error(ArgumentError)
 
578
        end
 
579
 
 
580
        it "should fail when the terminus class name is nil" do
 
581
            proc { @indirection.terminus_class = nil }.should raise_error(ArgumentError)
 
582
        end
 
583
 
 
584
        it "should fail when the specified terminus class cannot be found" do
 
585
            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
 
586
            proc { @indirection.terminus_class = :foo }.should raise_error(ArgumentError)
 
587
        end
 
588
 
 
589
        it "should select the specified terminus class if a terminus class name is provided" do
 
590
            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(@terminus_class)
 
591
            @indirection.terminus(:foo).should equal(@terminus)
 
592
        end
 
593
 
 
594
        it "should use the configured terminus class if no terminus name is specified" do
 
595
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
 
596
            @indirection.terminus_class = :foo
 
597
            @indirection.terminus().should equal(@terminus)
 
598
        end
 
599
 
 
600
        after do
 
601
            @indirection.delete if defined? @indirection
 
602
        end
 
603
    end
 
604
 
 
605
    describe "when managing terminus instances" do
 
606
        before do
 
607
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
608
            @terminus = mock 'terminus'
 
609
            @terminus_class = mock 'terminus class'
 
610
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
 
611
        end
 
612
 
 
613
        it "should create an instance of the chosen terminus class" do
 
614
            @terminus_class.stubs(:new).returns(@terminus)
 
615
            @indirection.terminus(:foo).should equal(@terminus)
 
616
        end
 
617
 
 
618
        it "should allow the clearance of cached terminus instances" do
 
619
            terminus1 = mock 'terminus1'
 
620
            terminus2 = mock 'terminus2'
 
621
            @terminus_class.stubs(:new).returns(terminus1, terminus2, ArgumentError)
 
622
            @indirection.terminus(:foo).should equal(terminus1)
 
623
            @indirection.class.clear_cache
 
624
            @indirection.terminus(:foo).should equal(terminus2)
 
625
        end
 
626
 
 
627
        # Make sure it caches the terminus.
 
628
        it "should return the same terminus instance each time for a given name" do
 
629
            @terminus_class.stubs(:new).returns(@terminus)
 
630
            @indirection.terminus(:foo).should equal(@terminus)
 
631
            @indirection.terminus(:foo).should equal(@terminus)
 
632
        end
 
633
 
 
634
        it "should not create a terminus instance until one is actually needed" do
 
635
            Puppet::Indirector.expects(:terminus).never
 
636
            indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest)
 
637
        end
 
638
 
 
639
        after do
 
640
            @indirection.delete
 
641
            Puppet::Indirector::Indirection.clear_cache
 
642
        end
 
643
    end
 
644
 
 
645
    describe "when deciding whether to cache" do
 
646
        before do
 
647
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
648
            @terminus = mock 'terminus'
 
649
            @terminus_class = mock 'terminus class'
 
650
            @terminus_class.stubs(:new).returns(@terminus)
 
651
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class)
 
652
            @indirection.terminus_class = :foo
 
653
        end
 
654
 
 
655
        it "should provide a method for setting the cache terminus class" do
 
656
            @indirection.should respond_to(:cache_class=)
 
657
        end
 
658
 
 
659
        it "should fail to cache if no cache type has been specified" do
 
660
            proc { @indirection.cache }.should raise_error(Puppet::DevError)
 
661
        end
 
662
 
 
663
        it "should fail to set the cache class when the cache class name is an empty string" do
 
664
            proc { @indirection.cache_class = "" }.should raise_error(ArgumentError)
 
665
        end
 
666
 
 
667
        it "should fail to set the cache class when the cache class name is nil" do
 
668
            proc { @indirection.cache_class = nil }.should raise_error(ArgumentError)
 
669
        end
 
670
 
 
671
        it "should fail to set the cache class when the specified cache class cannot be found" do
 
672
            Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil)
 
673
            proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError)
 
674
        end
 
675
 
 
676
        after do
 
677
            @indirection.delete
 
678
            Puppet::Indirector::Indirection.clear_cache
 
679
        end
 
680
    end
 
681
 
 
682
    describe "when using a cache" do
 
683
        before :each do
 
684
            Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus")
 
685
            @terminus_class = mock 'terminus_class'
 
686
            @terminus = mock 'terminus'
 
687
            @terminus_class.stubs(:new).returns(@terminus)
 
688
            @cache = mock 'cache'
 
689
            @cache_class = mock 'cache_class'
 
690
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class)
 
691
            Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class)
 
692
            @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test)
 
693
            @indirection.terminus_class = :test_terminus
 
694
        end
 
695
 
 
696
        describe "and managing the cache terminus" do
 
697
            it "should not create a cache terminus at initialization" do
 
698
                # This is weird, because all of the code is in the setup.  If we got
 
699
                # new() called on the cache class, we'd get an exception here.
 
700
            end
 
701
 
 
702
            it "should reuse the cache terminus" do
 
703
                @cache_class.expects(:new).returns(@cache)
 
704
                Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus")
 
705
                @indirection.cache_class = :cache_terminus
 
706
                @indirection.cache.should equal(@cache)
 
707
                @indirection.cache.should equal(@cache)
 
708
            end
 
709
 
 
710
            it "should remove the cache terminus when all other terminus instances are cleared" do
 
711
                cache2 = mock 'cache2'
 
712
                @cache_class.stubs(:new).returns(@cache, cache2)
 
713
                @indirection.cache_class = :cache_terminus
 
714
                @indirection.cache.should equal(@cache)
 
715
                @indirection.clear_cache
 
716
                @indirection.cache.should equal(cache2)
 
717
            end
 
718
        end
 
719
 
 
720
        describe "and saving" do
 
721
        end
 
722
        
 
723
        describe "and finding" do
 
724
        end
 
725
        
 
726
        after :each do
 
727
            @indirection.delete
 
728
            Puppet::Indirector::Indirection.clear_cache
 
729
        end
 
730
    end
 
731
end