kissifer-hash-persistent 0.0.0 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/spec/counter_spec.rb DELETED
@@ -1,61 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe "HashPersistent::Counter" do
4
- context "(instantiation)" do
5
- it "should expect to persist to a HashPersistent::Store and a string-like key" do
6
- HashPersistent::Counter.new(HashPersistent::Store.new({}, ""), "key")
7
- end
8
-
9
- it "should reject an incorrect store type" do
10
- lambda {HashPersistent::Counter.new(1, "key")}.should raise_error(ArgumentError)
11
- end
12
-
13
- it "should reject a non-string-like key" do
14
- lambda {HashPersistent::Counter.new(HashPersistent::Store.new({}, ""), Dummy_NoStringRep.new)}.should raise_error(ArgumentError)
15
- end
16
-
17
- it "should reject an empty string key" do
18
- lambda {HashPersistent::Counter.new(HashPersistent::Store.new({}, ""), "")}.should raise_error(ArgumentError)
19
- end
20
-
21
- it "should add an count object to the store" do
22
- store = HashPersistent::Store.new({}, "")
23
- HashPersistent::Counter.new(store, "counter_name")
24
- store.find("counter_name").count.should == 0
25
- end
26
-
27
- it "should not change the count object in the store if already present" do
28
- store = HashPersistent::Store.new({}, "")
29
- counter_1 = HashPersistent::Counter.new(store, "counter_name")
30
- counter_1.next.should == 0
31
- counter_1.next.should == 1
32
- counter_1.next.should == 2
33
-
34
- counter_2 = HashPersistent::Counter.new(store, "counter_name")
35
- store.find("counter_name").count.should == 3
36
- end
37
- end
38
-
39
- context "(generating unique ids)" do
40
- it "should increment the count value in the store when a new id is requested" do
41
- store = HashPersistent::Store.new({}, "")
42
- counter = HashPersistent::Counter.new(store, "counter_name")
43
- counter.next
44
- store.find("counter_name").count.should == 1
45
- counter.next
46
- store.find("counter_name").count.should == 2
47
- end
48
-
49
- it "should return the count held in the store when a new id is requested" do
50
- store = HashPersistent::Store.new({}, "")
51
- counter = HashPersistent::Counter.new(store, "counter_name")
52
- counter.next.should == 0
53
- counter.next.should == 1
54
- counter.next.should == 2
55
- end
56
- end
57
-
58
- context "(concurrent access)" do
59
- it "should correctly protect against use by mutliple threads/processes"
60
- end
61
- end
@@ -1,103 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe "HashPersistent::ExtendedStore" do
4
- context "(instantiation)" do
5
- it "should initialise its store attribute" do
6
- store = HashPersistent::Store.new(Hash.new, "prefix::")
7
- extended_store = HashPersistent::ExtendedStore.new(store)
8
- extended_store.store.should == store
9
- end
10
- end
11
-
12
- context "(in default configuration)" do
13
- it "should delegate the find method to its store" do
14
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
15
- extended_store.store.should_receive(:find).with("a_key")
16
- extended_store.find("a_key")
17
- end
18
-
19
- it "should delegate the save method to its store" do
20
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
21
- object = OpenStruct.new
22
- object.key = "a_key"
23
- extended_store.store.should_receive(:save).with(object)
24
- extended_store.save(object)
25
- end
26
-
27
- it "should delegate the delete method to its store" do
28
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
29
- object = OpenStruct.new
30
- object.key = "a_key"
31
- extended_store.store.should_receive(:delete).with(object)
32
- extended_store.delete(object)
33
- end
34
-
35
- it "should delegate the create method to its store" do
36
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
37
- extended_store.store.should_receive(:create).with("key", OpenStruct)
38
- extended_store.create("key", OpenStruct)
39
- end
40
-
41
- it "should delegate the find_or_create method to its store" do
42
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
43
- extended_store.store.should_receive(:find_or_create).with("key", OpenStruct)
44
- extended_store.find_or_create("key", OpenStruct)
45
- end
46
- end
47
-
48
- context "(singleton keys)" do
49
- it "should allow a singleton key pattern to be specified" do
50
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
51
- extended_store.singleton_key("foo", OpenStruct)
52
-
53
- HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, "")) do |store|
54
- store.singleton_key "foo", OpenStruct
55
- end
56
- end
57
-
58
- it "should reject a pattern that cannot be matched against a string" do
59
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
60
- lambda{extended_store.singleton_key(1, OpenStruct)}.should raise_error
61
- end
62
-
63
- it "should not redirect find for keys that do not match the singleton pattern" do
64
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
65
- extended_store.singleton_key("foo", OpenStruct)
66
-
67
- extended_store.store.should_receive(:find).with("bar")
68
- extended_store.store.should_not_receive(:find_or_create)
69
-
70
- extended_store.find("bar")
71
- end
72
-
73
- it "should redirect find to find_or_create for keys that match the singleton pattern" do
74
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
75
- extended_store.singleton_key("foo", OpenStruct, "arg1", "arg2")
76
-
77
- extended_store.store.should_receive(:find_or_create).with("food", OpenStruct, "arg1", "arg2")
78
- extended_store.store.should_not_receive(:find)
79
-
80
- extended_store.find("food")
81
- end
82
-
83
- it "should allow multiple patterns to be specified" do
84
- extended_store = HashPersistent::ExtendedStore.new(HashPersistent::Store.new({}, ""))
85
- extended_store.singleton_key("foo", OpenStruct, "arg1", "arg2")
86
- extended_store.singleton_key("bar", Object, "arg3", "arg4")
87
-
88
- extended_store.store.should_receive(:find_or_create).with("food", OpenStruct, "arg1", "arg2")
89
- extended_store.find("food")
90
-
91
- extended_store.store.should_receive(:find_or_create).with("barney", Object, "arg3", "arg4")
92
- extended_store.find("barney")
93
- end
94
- end
95
-
96
- context "(proxy stores)" do
97
- it "should be clever"
98
- end
99
-
100
- context "(watching objects)" do
101
- it "should be clever"
102
- end
103
- end
@@ -1,48 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- class ResourceFoo
4
- include HashPersistent::Resource
5
- end
6
-
7
-
8
- describe "A class that includes HashPersistent::Resource" do
9
- it "should acquire a store attribute" do
10
- resource = ResourceFoo.new
11
- resource.store = "foo"
12
- resource.store.should == "foo"
13
- end
14
-
15
- it "should acquire a key attribute" do
16
- resource = ResourceFoo.new
17
- resource.key = "foo"
18
- resource.key.should == "foo"
19
- end
20
-
21
- it "should be savable to its store" do
22
- resource = ResourceFoo.new
23
- mock_store = "dummy"
24
- resource.store = mock_store
25
-
26
- mock_store.should_receive(:save).with(resource)
27
- resource.save
28
- end
29
-
30
- it "should be deletable from its store" do
31
- resource = ResourceFoo.new
32
- mock_store = "dummy"
33
- resource.store = mock_store
34
-
35
- mock_store.should_receive(:delete).with(resource)
36
- resource.delete
37
- end
38
-
39
- it "should be movable from one store to another" do
40
- resource = ResourceFoo.new
41
- mock_store = "dummy" # We use only one so that we can use rspec to check the order of the messages...
42
- resource.store = mock_store
43
-
44
- mock_store.should_receive(:delete).with(resource).ordered
45
- mock_store.should_receive(:save).with(resource).ordered
46
- resource.move(mock_store)
47
- end
48
- end
data/spec/store_spec.rb DELETED
@@ -1,370 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- class ClassWithKey
4
- attr_accessor :key, :var
5
- def initialize(key, var)
6
- @key = key
7
- @var = var
8
- end
9
-
10
- def ==(other)
11
- (other.class == ClassWithKey) && (key == other.key) && (var == other.var)
12
- end
13
- end
14
-
15
- class ClassWithKeyAndStore
16
- attr_accessor :key, :store, :var
17
-
18
- def initialize(key = nil)
19
- @key = key
20
- end
21
- end
22
-
23
- describe "HashPersistent::Store" do
24
- context "(instantiation)" do
25
- it "should expect to persist to a hash-like key_value_store, with a string-like key_prefix" do
26
- HashPersistent::Store.new({}, "_prefix")
27
- end
28
-
29
- it "should reject a non-hash-like key_value_store" do
30
- lambda {HashPersistent::Store.new(1, "_prefix")}.should raise_error(ArgumentError)
31
- end
32
-
33
- it "should reject a non-string-like key_prefix" do
34
- lambda {HashPersistent::Store.new({}, Dummy_NoStringRep.new)}.should raise_error(ArgumentError)
35
- end
36
-
37
- it "should maintain a key_value_store attribute" do
38
- a_hash = {}
39
- HashPersistent::Store.new(a_hash, "").key_value_store.should == a_hash
40
- end
41
-
42
- it "should maintain a key_prefix attribute" do
43
- HashPersistent::Store.new({}, "foo_bar").key_prefix.should == "foo_bar"
44
- end
45
- end
46
-
47
- context "(saving)" do
48
- it "should refuse to save an object that does not provide a non-nil key" do
49
- lambda{HashPersistent::Store.new({}, "").save(1)}.should raise_error
50
- object = ClassWithKey.new(nil, "foo")
51
- lambda{HashPersistent::Store.new({}, "").save(object)}.should raise_error
52
- end
53
-
54
- it "should add the object, referenced by its prefixed key, to the store" do
55
- store = HashPersistent::Store.new({}, "prefix::")
56
- object = ClassWithKey.new("foo", "bar")
57
- store.save(object).key_value_store["prefix::foo"].should == object
58
- end
59
-
60
- it "should overwrite an object with same prefixed key in the store" do
61
- store = HashPersistent::Store.new({}, "prefix::")
62
- object_1 = ClassWithKey.new("foo", "bar")
63
- object_2 = ClassWithKey.new("foo", "baz")
64
- store.save(object_1).save(object_2).key_value_store["prefix::foo"].should == object_2
65
- end
66
- end
67
-
68
- context "(deleting)" do
69
- it "should refuse to delete an object that does not provide a non-nil key" do
70
- lambda{HashPersistent::Store.new({}, "").delete(1)}.should raise_error
71
- object = ClassWithKey.new(nil, "foo")
72
- lambda{HashPersistent::Store.new({}, "").delete(object)}.should raise_error
73
- end
74
-
75
- it "should delete a pair from the store based on the object's prefixed key" do
76
- store = HashPersistent::Store.new({}, "prefix::")
77
- object = ClassWithKey.new("foo", "bar")
78
- store.save(object).delete(object).key_value_store["prefix::foo"].should be_nil
79
- end
80
-
81
- it "should not complain if the prefixed key does not exist in the store" do
82
- store = HashPersistent::Store.new({}, "prefix::")
83
- object = ClassWithKey.new("foo", "bar")
84
- lambda{store.delete(object)}.should_not raise_error
85
- end
86
- end
87
-
88
- context "(finding)" do
89
- it "should retrieve an object that has the correct key" do
90
- store = HashPersistent::Store.new({}, "prefix::")
91
- object = ClassWithKey.new("foo", "bar")
92
- store.save(object).find("foo").should == object
93
- end
94
-
95
- it "should return nil if no object is found with the correct key" do
96
- store = HashPersistent::Store.new({}, "prefix::")
97
- object = ClassWithKey.new("foo", "bar")
98
- store.find("foo").should be_nil
99
- store.save(object).delete(object).find("foo").should be_nil
100
- end
101
- end
102
-
103
- context "(creating)" do
104
- it "should create objects on request" do
105
- new_object = ClassWithKeyAndStore.new
106
- ClassWithKeyAndStore.should_receive(:new).with("arg1", "arg2").and_return(new_object)
107
- object = HashPersistent::Store.new({}, "prefix::").create("a_key", ClassWithKeyAndStore, "arg1", "arg2")
108
- object.should == new_object
109
- end
110
-
111
- it "should set the key attribute of created objects" do
112
- block = lambda{"foo"}
113
- object = HashPersistent::Store.new({}, "prefix::").create("a_key", ClassWithKeyAndStore)
114
- object.key.should == "a_key"
115
- end
116
-
117
- it "should be able to create and save when the requested key is not found" do
118
- store = HashPersistent::Store.new({}, "")
119
- store.find_or_create("a_key", OpenStruct, {:foo => "bar"})
120
- store.find("a_key").should_not be_nil
121
- store.find("a_key").foo.should == "bar"
122
- end
123
-
124
- it "should not create or modify when the requested key is found" do
125
- store = HashPersistent::Store.new({}, "")
126
- store.save(store.create("a_key", OpenStruct, {:foo => "bar"}))
127
-
128
- store.find_or_create("a_key", OpenStruct, {:foo => "baz", :fred => "barney"})
129
-
130
- store.find("a_key").should_not be_nil
131
- store.find("a_key").fred.should be_nil
132
- store.find("a_key").foo.should == "bar"
133
- end
134
- end
135
-
136
- context "(isolation of objects in in-memory stores)" do
137
- it "should return a copy of the object found in the store" do
138
- store = HashPersistent::Store.new({}, "")
139
- object = ClassWithKey.new("foo", "bar")
140
- store.save(object).find("foo").should_not equal(store.key_value_store["foo"])
141
- end
142
-
143
- it "should save a copy of the object being saved" do
144
- store = HashPersistent::Store.new({}, "")
145
- object = ClassWithKey.new("foo", "bar")
146
- store.save(object)
147
- store.key_value_store["foo"].should_not equal(object)
148
- end
149
- end
150
-
151
- context "(handling objects that expose a store attribute)" do
152
- it "should set the store attribute of a created object" do
153
- store = HashPersistent::Store.new({}, "prefix::")
154
- store.create("key", ClassWithKeyAndStore).store.should == store
155
- end
156
-
157
- it "should set the store attribute of a saved object" do
158
- object = ClassWithKeyAndStore.new("foo")
159
- store = HashPersistent::Store.new({}, "")
160
- store.save(object)
161
- object.store.should == store
162
- end
163
-
164
- it "should not save the store attribute into the store" do
165
- object = ClassWithKeyAndStore.new("foo")
166
- object.store = "faa"
167
-
168
- store = HashPersistent::Store.new({}, "")
169
- store.save(object)
170
-
171
- store.key_value_store["foo"].store.should be_nil
172
- end
173
-
174
- it "should set the store attribute of a found object" do
175
- object = ClassWithKeyAndStore.new("foo")
176
- object.store = "faa"
177
-
178
- store = HashPersistent::Store.new({}, "")
179
- store.save(object).find("foo").store.should == store
180
- end
181
-
182
- it "leave the in-store object's store attribute nil after finding/returning the object" do
183
- object = ClassWithKeyAndStore.new("foo")
184
- object.store = "faa"
185
-
186
- store = HashPersistent::Store.new({}, "")
187
- store.save(object).find("foo")
188
- store.key_value_store["foo"].store.should be_nil
189
- end
190
-
191
- it "set the object's store attribute after deleting the object" do
192
- store = HashPersistent::Store.new({}, "")
193
- object = ClassWithKeyAndStore.new("foo")
194
-
195
- store.save(object)
196
- object.store = nil
197
- store.delete(object)
198
- object.store.should == store
199
- end
200
- end
201
-
202
- context "(use of restricted Hash API)" do
203
- it "should not require Hash methods that are not implemented in Moneta"
204
- end
205
-
206
- context "(caching)" do
207
- it "should accept a HashPersistent::Store cache" do
208
- cache = HashPersistent::Store.new({}, "")
209
- store = HashPersistent::Store.new({}, "") do |the_store|
210
- the_store.cached_to = cache
211
- end
212
- store.cached_to.should == cache
213
- end
214
-
215
- # TODO: can relax this?
216
- # We'd like to reproduce some nice behaviours in the cache (like unsetting object.store on saving)
217
- it "should reject a cache of the wrong type" do
218
- store = HashPersistent::Store.new({}, "")
219
- lambda{store.cached_to = {}}.should raise_error(ArgumentError)
220
- end
221
-
222
- it "should allow the cache to be unset using nil" do
223
- store = HashPersistent::Store.new({}, "")
224
- store.cached_to = nil
225
- store.cached_to.should == nil
226
- end
227
-
228
- context "if supplied a cache" do
229
- it "should also save an object to the cache when saving" do
230
- cache = HashPersistent::Store.new({}, "")
231
- store = HashPersistent::Store.new({}, "")
232
- store.cached_to = cache
233
-
234
- object = ClassWithKeyAndStore.new("foo")
235
- cache.should_receive(:save) do |the_save_object|
236
- the_save_object.key.should == "foo"
237
- end
238
- store.save(object)
239
- end
240
-
241
- it "should also delete an object from the cache when deleting" do
242
- cache = HashPersistent::Store.new({}, "")
243
- store = HashPersistent::Store.new({}, "")
244
- store.cached_to = cache
245
-
246
- object = ClassWithKeyAndStore.new("foo")
247
- store.save(object)
248
-
249
- cache.should_receive(:delete) do |the_delete_object|
250
- the_delete_object.key.should == "foo"
251
- end
252
- store.delete(object)
253
- end
254
-
255
- it "should save an object to the cache if it is not present on find()" do
256
- cache = HashPersistent::Store.new({}, "")
257
- store = HashPersistent::Store.new({}, "")
258
-
259
- object = ClassWithKeyAndStore.new("foo")
260
- store.save(object)
261
-
262
- # We're making an assumption here that no data is copied to the cache when we do this
263
- store.cached_to = cache
264
-
265
- cache.should_receive(:save) do |the_save_object|
266
- the_save_object.key.should == "foo"
267
- end
268
- store.find("foo")
269
- end
270
-
271
- it "should return the object from the cache if it is present on find()" do
272
- cache = HashPersistent::Store.new({}, "")
273
- store = HashPersistent::Store.new({}, "")
274
- store.cached_to = cache
275
-
276
- object = ClassWithKeyAndStore.new("foo")
277
- object.var = "bar"
278
- store.save(object)
279
-
280
- object.var = "baz"
281
- cache.save(object)
282
-
283
- store.find("foo").var.should == "baz"
284
- end
285
-
286
- it "should not hit the store if the object is present in the cache on find()" do
287
- cache = HashPersistent::Store.new({}, "")
288
- store = HashPersistent::Store.new({}, "")
289
- store.cached_to = cache
290
-
291
- object = ClassWithKeyAndStore.new("foo")
292
- store.save(object)
293
-
294
- # We assume that Fixnum is missing methods required in find(), but we verify this assumption below
295
- class HashPersistent::Store
296
- def hack_key_value_store
297
- @key_value_store = 1
298
- end
299
- end
300
-
301
- store.hack_key_value_store
302
-
303
- lambda{store.find("foo")}.should_not raise_error
304
-
305
- store.cached_to = nil
306
- lambda{store.find("foo")}.should raise_error
307
-
308
- class HashPersistent::Store
309
- undef hack_key_value_store
310
- end
311
- end
312
-
313
- it "should correctly set the object's store attribute when saving" do
314
- cache = HashPersistent::Store.new({}, "")
315
- store = HashPersistent::Store.new({}, "")
316
- store.cached_to = cache
317
-
318
- object = ClassWithKeyAndStore.new("foo")
319
- store.save(object)
320
- object.store.should == store
321
- end
322
-
323
- it "should correctly set the object's store attribute when deleting" do
324
- cache = HashPersistent::Store.new({}, "")
325
- store = HashPersistent::Store.new({}, "")
326
- store.cached_to = cache
327
-
328
- object = ClassWithKeyAndStore.new("foo")
329
-
330
- store.save(object)
331
- object.store = nil
332
-
333
- store.delete(object)
334
- object.store.should == store
335
- end
336
-
337
- it "should correctly set the object's store attribute when finding/caching" do
338
- cache = HashPersistent::Store.new({}, "")
339
- store = HashPersistent::Store.new({}, "")
340
-
341
- object = ClassWithKeyAndStore.new("foo")
342
- store.save(object)
343
-
344
- store.cached_to = cache
345
- found = store.find("foo")
346
-
347
- found.store.should == store
348
- end
349
-
350
- it "should correctly set the object's store attribute when finding from the cache" do
351
- cache = HashPersistent::Store.new({}, "")
352
- store = HashPersistent::Store.new({}, "")
353
- store.cached_to = cache
354
-
355
- object = ClassWithKeyAndStore.new("foo")
356
- store.save(object)
357
-
358
- store.find("foo").store.should == store
359
- end
360
- end
361
- end
362
-
363
- context "(consistency of store, watched store and cache after errors occur)" do
364
- it "should do something both boring and predictable"
365
- end
366
-
367
- context "(concurrent access)" do
368
- it "should use locks and such to handle access from multiple threads/processes"
369
- end
370
- end