redis-objects 1.5.1 → 2.0.0.alpha

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.
@@ -0,0 +1,419 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ require 'redis/objects'
4
+ Redis::Objects.redis = REDIS_HANDLE
5
+
6
+ require 'securerandom'
7
+
8
+ require "stringio"
9
+
10
+ def capture_stderr
11
+ # The output stream must be an IO-like object. In this case we capture it in
12
+ # an in-memory IO object so we can return the string value. You can assign any
13
+ # IO object here.
14
+ previous_stderr, $stderr = $stderr, StringIO.new
15
+ yield
16
+ $stderr.string
17
+ ensure
18
+ # Restore the previous value of stderr (typically equal to STDERR).
19
+ $stderr = previous_stderr
20
+ end
21
+
22
+ describe 'Legacy redis key prefix naming compatibility' do
23
+ it 'verifies single level classes work the same' do
24
+ class SingleLevelOne
25
+ include Redis::Objects
26
+
27
+ def id
28
+ 1
29
+ end
30
+ end
31
+
32
+ obj = SingleLevelOne.new
33
+ obj.class.redis_prefix.should == 'single_level_one'
34
+ end
35
+
36
+ it 'verifies single level classes obey the legacy naming flag' do
37
+ class SingleLevelTwo
38
+ include Redis::Objects
39
+ self.redis_legacy_naming = true
40
+
41
+ def id
42
+ 1
43
+ end
44
+ end
45
+
46
+ obj = SingleLevelTwo.new
47
+ obj.class.redis_prefix.should == 'single_level_two'
48
+ end
49
+
50
+ it 'verifies nested classes do NOT work the same' do
51
+ module Nested
52
+ class NamingOne
53
+ include Redis::Objects
54
+ self.redis_silence_warnings = true
55
+
56
+ def id
57
+ 1
58
+ end
59
+ end
60
+ end
61
+
62
+ obj = Nested::NamingOne.new
63
+ obj.class.redis_prefix.should == 'nested__naming_one'
64
+ end
65
+
66
+ it 'verifies the legacy naming flag is respected' do
67
+ module Nested
68
+ class NamingTwo
69
+ include Redis::Objects
70
+ self.redis_legacy_naming = true
71
+ self.redis_silence_warnings = true
72
+
73
+ def id
74
+ 1
75
+ end
76
+ end
77
+ end
78
+
79
+ Nested::NamingTwo.redis_legacy_naming.should == true
80
+ obj = Nested::NamingTwo.new
81
+ obj.class.redis_prefix.should == 'naming_two'
82
+ end
83
+
84
+ it 'verifies that multiple levels respect __ vs _' do
85
+ module NestedLevel
86
+ module Further
87
+ class NamingThree
88
+ include Redis::Objects
89
+ self.redis_silence_warnings = true
90
+
91
+ def id
92
+ 1
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ obj = NestedLevel::Further::NamingThree.new
99
+ obj.class.redis_prefix.should == 'nested_level__further__naming_three'
100
+ end
101
+
102
+ it 'verifies that multiple levels respect the legacy naming' do
103
+ module NestedLevel
104
+ module Further
105
+ class NamingFour
106
+ include Redis::Objects
107
+ self.redis_legacy_naming = true
108
+
109
+ def id
110
+ 1
111
+ end
112
+
113
+ redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31)
114
+ value :redis_value, :redis => redis_handle
115
+ end
116
+ end
117
+ end
118
+
119
+ NestedLevel::Further::NamingFour.redis_legacy_naming.should == true
120
+ obj = NestedLevel::Further::NamingFour.new
121
+ obj.class.redis_prefix.should == 'naming_four'
122
+ val = SecureRandom.hex(10)
123
+ obj.redis_value = val
124
+ obj.redis_value.should == val
125
+ obj.redis_value.key.should == 'naming_four:1:redis_value'
126
+ end
127
+
128
+ it 'verifies that multiple levels do not conflict 1' do
129
+ module NestedLevel
130
+ module Further
131
+ class NamingFive
132
+ include Redis::Objects
133
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
134
+ self.redis_silence_warnings = true
135
+
136
+ def id
137
+ 1
138
+ end
139
+
140
+ value :redis_value
141
+ end
142
+ end
143
+ end
144
+
145
+ obj = NestedLevel::Further::NamingFive.new
146
+ obj.class.redis_prefix.should == 'nested_level__further__naming_five'
147
+ val = SecureRandom.hex(10)
148
+ obj.redis_value = val
149
+ obj.redis_value.should == val
150
+ obj.redis_value.key.should == 'nested_level__further__naming_five:1:redis_value'
151
+ obj.redis_value.redis.should == obj.redis
152
+ obj.redis.get('nested_level__further__naming_five:1:redis_value').should == val
153
+ end
154
+
155
+ it 'verifies that multiple levels do not conflict 2' do
156
+ module Nested
157
+ module LevelFurtherNaming
158
+ class Five
159
+ include Redis::Objects
160
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
161
+ self.redis_silence_warnings = true
162
+
163
+ def id
164
+ 1
165
+ end
166
+
167
+ value :redis_value
168
+ end
169
+ end
170
+ end
171
+
172
+ obj = Nested::LevelFurtherNaming::Five.new
173
+ obj.class.redis_prefix.should == 'nested__level_further_naming__five'
174
+ val = SecureRandom.hex(10)
175
+ obj.redis_value = val
176
+ obj.redis_value.should == val
177
+ obj.redis_value.key.should == 'nested__level_further_naming__five:1:redis_value'
178
+ obj.redis.get('nested__level_further_naming__five:1:redis_value').should == val
179
+ end
180
+
181
+ it 'verifies that multiple levels do not conflict 3' do
182
+ module Nested
183
+ module LevelFurther
184
+ class NamingFive
185
+ include Redis::Objects
186
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
187
+ self.redis_silence_warnings = true
188
+
189
+ def id
190
+ 1
191
+ end
192
+
193
+ value :redis_value
194
+ end
195
+ end
196
+ end
197
+
198
+ obj = Nested::LevelFurther::NamingFive.new
199
+ obj.class.redis_prefix.should == 'nested__level_further__naming_five'
200
+ val = SecureRandom.hex(10)
201
+ obj.redis_value = val
202
+ obj.redis_value.should == val
203
+ obj.redis_value.key.should == 'nested__level_further__naming_five:1:redis_value'
204
+ obj.redis.get('nested__level_further__naming_five:1:redis_value').should == val
205
+ end
206
+
207
+ it 'handles dynamically created classes correctly' do
208
+ module Nested
209
+ class LevelSix
210
+ include Redis::Objects
211
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
212
+ self.redis_silence_warnings = true
213
+
214
+ def id
215
+ 1
216
+ end
217
+
218
+ value :redis_value
219
+ end
220
+ end
221
+
222
+ obj = Nested::LevelSix.new
223
+ obj.class.redis_prefix.should == 'nested__level_six'
224
+ val = SecureRandom.hex(10)
225
+ obj.redis_value = val
226
+ obj.redis_value.should == val
227
+ obj.redis_value.key.should == 'nested__level_six:1:redis_value'
228
+ obj.redis.get('nested__level_six:1:redis_value').should == val
229
+
230
+ DynamicClass = Class.new(Nested::LevelSix)
231
+ DynamicClass.value :redis_value2
232
+ obj2 = DynamicClass.new
233
+ DynamicClass.redis_prefix.should == 'dynamic_class'
234
+ obj2.redis_value.should.be.kind_of(Redis::Value)
235
+ obj2.redis_value2.should.be.kind_of(Redis::Value)
236
+ obj2.redis_value.key.should == 'dynamic_class:1:redis_value'
237
+ obj2.redis_value2.key.should == 'dynamic_class:1:redis_value2'
238
+
239
+ end
240
+
241
+ it 'handles dynamically created classes correctly in legacy mode' do
242
+ module Nested
243
+ class LevelSeven
244
+ include Redis::Objects
245
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
246
+ self.redis_legacy_naming = true
247
+
248
+ def id
249
+ 1
250
+ end
251
+
252
+ value :redis_value
253
+ end
254
+ end
255
+
256
+ obj = Nested::LevelSeven.new
257
+ obj.class.redis_prefix.should == 'level_seven'
258
+ val = SecureRandom.hex(10)
259
+ obj.redis_value = val
260
+ obj.redis_value.should == val
261
+ obj.redis_value.key.should == 'level_seven:1:redis_value'
262
+ obj.redis.get('level_seven:1:redis_value').should == val
263
+
264
+ DynamicClass2 = Class.new(Nested::LevelSeven)
265
+ DynamicClass2.value :redis_value2
266
+ obj2 = DynamicClass2.new
267
+ DynamicClass2.redis_prefix.should == 'dynamic_class2'
268
+ obj2.redis_value.should.be.kind_of(Redis::Value)
269
+ obj2.redis_value2.should.be.kind_of(Redis::Value)
270
+ obj2.redis_value.key.should == 'dynamic_class2:1:redis_value'
271
+ obj2.redis_value2.key.should == 'dynamic_class2:1:redis_value2'
272
+ end
273
+
274
+ it 'prints a warning message if the key name changes' do
275
+ module Nested
276
+ class LevelNine
277
+ include Redis::Objects
278
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
279
+
280
+ def id
281
+ 1
282
+ end
283
+
284
+ value :redis_value
285
+ end
286
+ end
287
+
288
+ captured_output = capture_stderr do
289
+ # Does not output anything directly.
290
+ obj = Nested::LevelNine.new
291
+ val = SecureRandom.hex(10)
292
+ obj.redis_value = val
293
+ obj.redis_value.should == val
294
+ end
295
+
296
+ captured_output.should =~ /Warning:/i
297
+ end
298
+
299
+ it 'supports a method to migrate legacy key names' do
300
+ module Nested
301
+ class Legacy
302
+ include Redis::Objects
303
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
304
+ self.redis_legacy_naming = true
305
+
306
+ # override this for testing - need two classes as if we imagine an old and new one
307
+ # also use the legacy flat prefix that ignores the nested class name
308
+ self.redis_prefix = 'modern'
309
+
310
+ def initialize(id)
311
+ @id = id
312
+ end
313
+ def id
314
+ @id
315
+ end
316
+
317
+ value :redis_value
318
+ counter :redis_counter
319
+ hash_key :redis_hash
320
+ list :redis_list
321
+ set :redis_set
322
+ sorted_set :redis_sorted_set
323
+
324
+ # global class counters
325
+ value :global_value, :global => true
326
+ counter :global_counter, :global => true
327
+ hash_key :global_hash_key, :global => true
328
+ list :global_list, :global => true
329
+ set :global_set, :global => true
330
+ sorted_set :global_sorted_set, :global => true
331
+
332
+ #callable as key
333
+ value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
334
+ end
335
+ end
336
+
337
+ module Nested
338
+ class Modern
339
+ include Redis::Objects
340
+ self.redis = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
341
+
342
+ def initialize(id)
343
+ @id = id
344
+ end
345
+ def id
346
+ @id
347
+ end
348
+
349
+ value :redis_value
350
+ counter :redis_counter
351
+ hash_key :redis_hash
352
+ list :redis_list
353
+ set :redis_set
354
+ sorted_set :redis_sorted_set
355
+
356
+ # global class counters
357
+ value :global_value, :global => true
358
+ counter :global_counter, :global => true
359
+ hash_key :global_hash_key, :global => true
360
+ list :global_list, :global => true
361
+ set :global_set, :global => true
362
+ sorted_set :global_sorted_set, :global => true
363
+
364
+ #callable as key
365
+ value :global_proc_value, :global => true, :key => Proc.new { |roster| "#{roster.name}:#{Time.now.strftime('%Y-%m-%dT%H')}:daily" }
366
+ end
367
+ end
368
+
369
+ # Iterate over them
370
+ Nested::Modern.redis_objects.length.should == 13
371
+ Nested::Modern.redis_objects.length.should == Nested::Legacy.redis_objects.length.should
372
+ Nested::Legacy.redis_prefix.should == 'modern'
373
+ Nested::Modern.redis_prefix.should == 'nested__modern'
374
+
375
+ # Create a whole bunch of keys using the legacy names
376
+ 30.times do |i|
377
+ # warn i.inspect
378
+ obj = Nested::Legacy.new(i)
379
+ obj.redis_value = i
380
+ obj.redis_value.to_i.should == i
381
+ obj.redis_counter.increment
382
+ obj.redis_hash[:key] = i
383
+ obj.redis_list << i
384
+ obj.redis_set << i
385
+ obj.redis_sorted_set[i] = i
386
+ end
387
+
388
+ obj = Nested::Legacy.new(99)
389
+ obj.global_value = 42
390
+ obj.global_counter.increment
391
+ obj.global_counter.increment
392
+ obj.global_counter.increment
393
+ obj.global_hash_key[:key] = 'value'
394
+ obj.global_set << 'a' << 'b'
395
+ obj.global_sorted_set[:key] = 2.2
396
+
397
+ Nested::Modern.migrate_redis_legacy_keys
398
+
399
+ # Try to access the keys through modern names now
400
+ 30.times do |i|
401
+ # warn i.inspect
402
+ obj = Nested::Modern.new(i)
403
+ obj.redis_value.to_i.should == i
404
+ obj.redis_counter.to_i.should == 1
405
+ obj.redis_hash[:key].to_i.should == i
406
+ obj.redis_list[0].to_i.should == i
407
+ obj.redis_set.include?(i).should == true
408
+ obj.redis_sorted_set[i].should == i
409
+ end
410
+
411
+ obj = Nested::Modern.new(99)
412
+ obj.global_value.to_i.should == 42
413
+ obj.global_counter.to_i.should == 3
414
+ obj.global_hash_key[:key].should == 'value'
415
+ obj.global_set.should.include?('a').should == true
416
+ obj.global_set.should.include?('b').should == true
417
+ obj.global_sorted_set[:key].should == 2.2
418
+ end
419
+ end
@@ -5,6 +5,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
5
5
 
6
6
  require 'redis/objects'
7
7
  require 'connection_pool'
8
+ Redis::Objects.redis = REDIS_HANDLE
8
9
 
9
10
  BAD_REDIS = "totally bad bogus redis handle"
10
11
 
@@ -33,8 +34,8 @@ describe 'Connection tests' do
33
34
  obj.redis_value.value.should == nil
34
35
 
35
36
  obj.default_redis_value.clear
36
- obj.redis_value.value = 'foo'
37
- obj.redis_value.value.should == 'foo'
37
+ obj.redis_value.value = 'bar'
38
+ obj.redis_value.value.should == 'bar'
38
39
  obj.default_redis_value.value.should == nil
39
40
 
40
41
  obj.redis_value.clear
@@ -95,13 +96,13 @@ describe 'Connection tests' do
95
96
  end
96
97
 
97
98
  it "should support local handles with a vanilla redis connection" do
98
- Redis.current = nil # reset from other tests
99
+ # Redis.current = nil # reset from other tests
99
100
  Redis::Objects.redis = nil
100
101
  @redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
101
102
 
102
103
  # Redis.current is lazily auto-populated to touch 6379
103
104
  # This why we choose the weird 9212 port to avoid
104
- Redis.current.inspect.should == Redis.new.inspect
105
+ # Redis.current.inspect.should == Redis.new.inspect
105
106
  Redis::Objects.redis.inspect.should == Redis.new.inspect
106
107
 
107
108
  v = Redis::Value.new('conn/value', @redis_handle)
@@ -140,13 +141,13 @@ describe 'Connection tests' do
140
141
  end
141
142
 
142
143
  it "should support local handles with a connection_pool" do
143
- Redis.current = nil # reset from other tests
144
+ # Redis.current = nil # reset from other tests
144
145
  Redis::Objects.redis = nil
145
146
  @redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
146
147
 
147
148
  # Redis.current is lazily auto-populated to touch 6379
148
149
  # This why we choose the weird 9212 port to avoid
149
- Redis.current.inspect.should == Redis.new.inspect
150
+ # Redis.current.inspect.should == Redis.new.inspect
150
151
  Redis::Objects.redis.inspect.should == Redis.new.inspect
151
152
 
152
153
  v = Redis::Value.new('conn/value', @redis_handle)
@@ -184,24 +185,19 @@ describe 'Connection tests' do
184
185
  c.decr(1)
185
186
  end
186
187
 
187
- it "should support Redis.current" do
188
- Redis.current = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
189
-
190
- Redis::Value.new('conn/value').should == 'yay'
191
- Redis::HashKey.new('conn/hash').keys.should == ['k']
192
- Redis::List.new('conn/list').sort.should == ['3', '4', '5']
193
- Redis::Set.new('conn/set').sort.should == ['5', '6', '7']
194
- Redis::SortedSet.new('conn/zset').should == ['d', 'b', 'a', 'c']
195
- Redis::Counter.new('conn/counter').should == 2
188
+ it "should properly support fallback handle variables" do
189
+ # Redis.current is lazily auto-populated to touch 6379
190
+ # This why we choose the weird 9212 port to avoid
191
+ old_redis = $redis
192
+ $redis = BAD_REDIS
193
+ Redis::Objects.redis.should == BAD_REDIS
194
+ $redis = old_redis
196
195
  end
197
196
 
198
197
  it "should support Redis::Objects.redis= with a connection_pool" do
198
+ # reset redis
199
199
  @redis_handle = ConnectionPool.new { Redis.new(:host => REDIS_HOST, :port => REDIS_PORT) }
200
-
201
- # Redis.current is lazily auto-populated to touch 6379
202
- # This why we choose the weird 9212 port to avoid
203
- Redis.current = BAD_REDIS
204
- Redis::Objects.redis.should == BAD_REDIS
200
+ Redis::Objects.redis = @redis_handle
205
201
 
206
202
  # This set of tests sucks, it fucks up the per-data-type handles
207
203
  # because Redis.current is then set to a BS value, and the lazy
@@ -229,13 +225,8 @@ describe 'Connection tests' do
229
225
 
230
226
  it "should support Redis::Objects.redis= with a vanilla redis connection" do
231
227
  # reset redis
232
- Redis::Objects.redis = nil
233
228
  @redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
234
-
235
- # Redis.current is lazily auto-populated to touch 6379
236
- # This why we choose the weird 9212 port to avoid
237
- Redis.current = BAD_REDIS
238
- Redis::Objects.redis.should == BAD_REDIS
229
+ Redis::Objects.redis = @redis_handle
239
230
 
240
231
  # This set of tests sucks, it fucks up the per-data-type handles
241
232
  # because Redis.current is then set to a BS value, and the lazy
@@ -260,7 +251,7 @@ describe 'Connection tests' do
260
251
  Redis::Counter.new('conn/counter').should == 2
261
252
 
262
253
  # Fix for future tests
263
- Redis.current = @redis_handle
254
+ # Redis.current = @redis_handle
264
255
  end
265
256
 
266
257
  it "should support pipelined changes" do
@@ -2,6 +2,7 @@
2
2
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
 
4
4
  require 'redis/objects'
5
+ Redis::Objects.redis = REDIS_HANDLE
5
6
 
6
7
  class CustomSerializer
7
8
  class << self