blob: 2e43b4e20dfeeabb6d113399542ac3cb97ceb4ff (
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
|
#!/usr/bin/env rspec
require 'spec_helper'
require 'puppet/util/cacher'
class ExpirerTest
include Puppet::Util::Cacher::Expirer
end
class CacheTest
@@init_count = 0
include Puppet::Util::Cacher
cached_attr(:instance_cache) { Time.now }
end
describe Puppet::Util::Cacher::Expirer do
before do
@expirer = ExpirerTest.new
end
it "should be able to test whether a timestamp is expired" do
@expirer.should respond_to(:dependent_data_expired?)
end
it "should be able to expire all values" do
@expirer.should respond_to(:expire)
end
it "should consider any value to be valid if it has never been expired" do
@expirer.should_not be_dependent_data_expired(Time.now)
end
it "should consider any value created after expiration to be expired" do
@expirer.expire
@expirer.should be_dependent_data_expired(Time.now - 1)
end
end
describe Puppet::Util::Cacher do
it "should be extended with the Expirer module" do
Puppet::Util::Cacher.singleton_class.ancestors.should be_include(Puppet::Util::Cacher::Expirer)
end
it "should support defining cached attributes" do
CacheTest.methods.should be_include("cached_attr")
end
it "should default to the Cacher module as its expirer" do
CacheTest.new.expirer.should equal(Puppet::Util::Cacher)
end
describe "when using cached attributes" do
before do
@expirer = ExpirerTest.new
@object = CacheTest.new
@object.stubs(:expirer).returns @expirer
end
it "should create a getter for the cached attribute" do
@object.should respond_to(:instance_cache)
end
it "should return a value calculated from the provided block" do
time = Time.now
Time.stubs(:now).returns time
@object.instance_cache.should equal(time)
end
it "should return the cached value from the getter every time if the value is not expired" do
@object.instance_cache.should equal(@object.instance_cache)
end
it "should regenerate and return a new value using the provided block if the value has been expired" do
value = @object.instance_cache
@expirer.expire
@object.instance_cache.should_not equal(value)
end
it "should be able to trigger expiration on its expirer" do
@expirer.expects(:expire)
@object.expire
end
it "should do nothing when asked to expire when no expirer is available" do
cacher = CacheTest.new
class << cacher
def expirer
nil
end
end
lambda { cacher.expire }.should_not raise_error
end
it "should be able to cache false values" do
@object.expects(:init_instance_cache).returns false
@object.instance_cache.should be_false
@object.instance_cache.should be_false
end
it "should cache values again after expiration" do
@object.instance_cache
@expirer.expire
@object.instance_cache.should equal(@object.instance_cache)
end
it "should always consider a value expired if it has no expirer" do
@object.stubs(:expirer).returns nil
@object.instance_cache.should_not equal(@object.instance_cache)
end
it "should allow writing of the attribute" do
@object.should respond_to(:instance_cache=)
end
it "should correctly configure timestamps for expiration when the cached attribute is written to" do
@object.instance_cache = "foo"
@expirer.expire
@object.instance_cache.should_not == "foo"
end
it "should allow specification of a ttl for cached attributes" do
klass = Class.new do
include Puppet::Util::Cacher
end
klass.cached_attr(:myattr, :ttl => 5) { Time.now }
klass.attr_ttl(:myattr).should == 5
end
it "should allow specification of a ttl as a string" do
klass = Class.new do
include Puppet::Util::Cacher
end
klass.cached_attr(:myattr, :ttl => "5") { Time.now }
klass.attr_ttl(:myattr).should == 5
end
it "should fail helpfully if the ttl cannot be converted to an integer" do
klass = Class.new do
include Puppet::Util::Cacher
end
lambda { klass.cached_attr(:myattr, :ttl => "yep") { Time.now } }.should raise_error(ArgumentError)
end
it "should not check for a ttl expiration if the class does not support that method" do
klass = Class.new do
extend Puppet::Util::Cacher
end
klass.singleton_class.cached_attr(:myattr) { "eh" }
klass.myattr
end
it "should automatically expire cached attributes whose ttl has expired, even if no expirer is present" do
klass = Class.new do
def self.to_s
"CacheTestClass"
end
include Puppet::Util::Cacher
attr_accessor :value
end
klass.cached_attr(:myattr, :ttl => 5) { self.value += 1; self.value }
now = Time.now
later = Time.now + 15
instance = klass.new
instance.value = 0
instance.myattr.should == 1
Time.expects(:now).returns later
# This call should get the new Time value, which should expire the old value
instance.myattr.should == 2
end
end
end
|