superfeedr-em-redis 0.2.2

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,647 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper.rb")
2
+ require 'logger'
3
+
4
+ EM.describe EM::Protocols::Redis do
5
+ default_timeout 1
6
+
7
+ before do
8
+ @r = EM::Protocols::Redis.connect :db => 14
9
+ @r.flushdb
10
+ @r['foo'] = 'bar'
11
+ end
12
+
13
+
14
+ should "be able to provide a logger" do
15
+ log = StringIO.new
16
+ r = EM::Protocols::Redis.connect :db => 14, :logger => Logger.new(log)
17
+ r.ping do
18
+ log.string.should.include "ping"
19
+ done
20
+ end
21
+ end
22
+
23
+ it "should be able to PING" do
24
+ @r.ping { |r| r.should == 'PONG'; done }
25
+ end
26
+
27
+ it "should be able to GET a key" do
28
+ @r.get('foo') { |r| r.should == 'bar'; done }
29
+ end
30
+
31
+ it "should be able to SET a key" do
32
+ @r['foo'] = 'nik'
33
+ @r.get('foo') { |r| r.should == 'nik'; done }
34
+ end
35
+
36
+ it "should properly handle trailing newline characters" do
37
+ @r['foo'] = "bar\n"
38
+ @r.get('foo') { |r| r.should == "bar\n"; done }
39
+ end
40
+
41
+ it "should store and retrieve all possible characters at the beginning and the end of a string" do
42
+ (0..255).each do |char_idx|
43
+ string = "#{char_idx.chr}---#{char_idx.chr}"
44
+ @r['foo'] = string
45
+ @r.get('foo') { |r| r.should == string }
46
+ end
47
+ @r.ping { done }
48
+ end
49
+
50
+ it "should be able to SET a key with an expiry" do
51
+ timeout(3)
52
+
53
+ @r.set('foo', 'bar', 1)
54
+ @r.get('foo') { |r| r.should == 'bar' }
55
+ EM.add_timer(2) do
56
+ @r.get('foo') { |r| r.should == nil }
57
+ @r.ping { done }
58
+ end
59
+ end
60
+
61
+ it "should be able to return a TTL for a key" do
62
+ @r.set('foo', 'bar', 1)
63
+ @r.ttl('foo') { |r| r.should == 1; done }
64
+ end
65
+
66
+ it "should be able to SETNX" do
67
+ @r['foo'] = 'nik'
68
+ @r.get('foo') { |r| r.should == 'nik' }
69
+ @r.setnx 'foo', 'bar'
70
+ @r.get('foo') { |r| r.should == 'nik' }
71
+
72
+ @r.ping { done }
73
+ end
74
+ #
75
+ it "should be able to GETSET" do
76
+ @r.getset('foo', 'baz') { |r| r.should == 'bar' }
77
+ @r.get('foo') { |r| r.should == 'baz'; done }
78
+ end
79
+ #
80
+ it "should be able to INCR a key" do
81
+ @r.del('counter')
82
+ @r.incr('counter') { |r| r.should == 1 }
83
+ @r.incr('counter') { |r| r.should == 2 }
84
+ @r.incr('counter') { |r| r.should == 3 }
85
+
86
+ @r.ping { done }
87
+ end
88
+ #
89
+ it "should be able to INCRBY a key" do
90
+ @r.del('counter')
91
+ @r.incrby('counter', 1) { |r| r.should == 1 }
92
+ @r.incrby('counter', 2) { |r| r.should == 3 }
93
+ @r.incrby('counter', 3) { |r| r.should == 6 }
94
+
95
+ @r.ping { done }
96
+ end
97
+ #
98
+ it "should be able to DECR a key" do
99
+ @r.del('counter')
100
+ @r.incr('counter') { |r| r.should == 1 }
101
+ @r.incr('counter') { |r| r.should == 2 }
102
+ @r.incr('counter') { |r| r.should == 3 }
103
+ @r.decr('counter') { |r| r.should == 2 }
104
+ @r.decr('counter', 2) { |r| r.should == 0; done }
105
+ end
106
+ #
107
+ it "should be able to RANDKEY" do
108
+ @r.randkey { |r| r.should.not == nil; done }
109
+ end
110
+ #
111
+ it "should be able to RENAME a key" do
112
+ @r.del 'foo'
113
+ @r.del 'bar'
114
+ @r['foo'] = 'hi'
115
+ @r.rename 'foo', 'bar'
116
+ @r.get('bar') { |r| r.should == 'hi' ; done }
117
+ end
118
+ #
119
+ it "should be able to RENAMENX a key" do
120
+ @r.del 'foo'
121
+ @r.del 'bar'
122
+ @r['foo'] = 'hi'
123
+ @r['bar'] = 'ohai'
124
+ @r.renamenx 'foo', 'bar'
125
+ @r.get('bar') { |r| r.should == 'ohai' ; done }
126
+ end
127
+ #
128
+ it "should be able to get DBSIZE of the database" do
129
+ dbsize_without_foo, dbsize_with_foo = nil
130
+ @r.delete 'foo'
131
+ @r.dbsize { |r| dbsize_without_foo = r }
132
+ @r['foo'] = 0
133
+ @r.dbsize { |r| dbsize_with_foo = r }
134
+
135
+ @r.ping do
136
+ dbsize_with_foo.should == dbsize_without_foo + 1
137
+ done
138
+ end
139
+ end
140
+ #
141
+ it "should be able to EXPIRE a key" do
142
+ timeout(3)
143
+
144
+ @r['foo'] = 'bar'
145
+ @r.expire 'foo', 1
146
+ @r.get('foo') { |r| r.should == "bar" }
147
+ EM.add_timer(2) do
148
+ @r.get('foo') { |r| r.should == nil }
149
+ @r.ping { done }
150
+ end
151
+ end
152
+ #
153
+ it "should be able to EXISTS" do
154
+ @r['foo'] = 'nik'
155
+ @r.exists('foo') { |r| r.should == true }
156
+ @r.del 'foo'
157
+ @r.exists('foo') { |r| r.should == false ; done }
158
+ end
159
+ #
160
+ it "should be able to KEYS" do
161
+ @r.keys("f*") { |keys| keys.each { |key| @r.del key } }
162
+ @r['f'] = 'nik'
163
+ @r['fo'] = 'nak'
164
+ @r['foo'] = 'qux'
165
+ @r.keys("f*") { |r| r.sort.should == ['f', 'fo', 'foo'].sort }
166
+
167
+ @r.ping { done }
168
+ end
169
+ #
170
+ it "should be able to return a random key (RANDOMKEY)" do
171
+ 3.times do |i|
172
+ @r.randomkey do |r|
173
+ @r.exists(r) do |e|
174
+ e.should == true
175
+ done if i == 2
176
+ end
177
+ end
178
+ end
179
+ end
180
+ #
181
+ it "should be able to check the TYPE of a key" do
182
+ @r['foo'] = 'nik'
183
+ @r.type('foo') { |r| r.should == "string" }
184
+ @r.del 'foo'
185
+ @r.type('foo') { |r| r.should == "none" ; done }
186
+ end
187
+ #
188
+ it "should be able to push to the head of a list (LPUSH)" do
189
+ @r.lpush "list", 'hello'
190
+ @r.lpush "list", 42
191
+ @r.type('list') { |r| r.should == "list" }
192
+ @r.llen('list') { |r| r.should == 2 }
193
+ @r.lpop('list') { |r| r.should == '42'; done }
194
+ end
195
+ #
196
+ it "should be able to push to the tail of a list (RPUSH)" do
197
+ @r.rpush "list", 'hello'
198
+ @r.type('list') { |r| r.should == "list" }
199
+ @r.llen('list') { |r| r.should == 1 ; done }
200
+ end
201
+ #
202
+ it "should be able to pop the tail of a list (RPOP)" do
203
+ @r.rpush "list", 'hello'
204
+ @r.rpush"list", 'goodbye'
205
+ @r.type('list') { |r| r.should == "list" }
206
+ @r.llen('list') { |r| r.should == 2 }
207
+ @r.rpop('list') { |r| r.should == 'goodbye'; done }
208
+ end
209
+ #
210
+ it "should be able to pop the head of a list (LPOP)" do
211
+ @r.rpush "list", 'hello'
212
+ @r.rpush "list", 'goodbye'
213
+ @r.type('list') { |r| r.should == "list" }
214
+ @r.llen('list') { |r| r.should == 2 }
215
+ @r.lpop('list') { |r| r.should == 'hello'; done }
216
+ end
217
+ #
218
+ it "should be able to get the length of a list (LLEN)" do
219
+ @r.rpush "list", 'hello'
220
+ @r.rpush "list", 'goodbye'
221
+ @r.type('list') { |r| r.should == "list" }
222
+ @r.llen('list') { |r| r.should == 2 ; done }
223
+ end
224
+ #
225
+ it "should be able to get a range of values from a list (LRANGE)" do
226
+ @r.rpush "list", 'hello'
227
+ @r.rpush "list", 'goodbye'
228
+ @r.rpush "list", '1'
229
+ @r.rpush "list", '2'
230
+ @r.rpush "list", '3'
231
+ @r.type('list') { |r| r.should == "list" }
232
+ @r.llen('list') { |r| r.should == 5 }
233
+ @r.lrange('list', 2, -1) { |r| r.should == ['1', '2', '3']; done }
234
+ end
235
+ #
236
+ it "should be able to trim a list (LTRIM)" do
237
+ @r.rpush "list", 'hello'
238
+ @r.rpush "list", 'goodbye'
239
+ @r.rpush "list", '1'
240
+ @r.rpush "list", '2'
241
+ @r.rpush "list", '3'
242
+ @r.type('list') { |r| r.should == "list" }
243
+ @r.llen('list') { |r| r.should == 5 }
244
+ @r.ltrim 'list', 0, 1
245
+ @r.llen('list') { |r| r.should == 2 }
246
+ @r.lrange('list', 0, -1) { |r| r.should == ['hello', 'goodbye']; done }
247
+ end
248
+ #
249
+ it "should be able to get a value by indexing into a list (LINDEX)" do
250
+ @r.rpush "list", 'hello'
251
+ @r.rpush "list", 'goodbye'
252
+ @r.type('list') { |r| r.should == "list" }
253
+ @r.llen('list') { |r| r.should == 2 }
254
+ @r.lindex('list', 1) { |r| r.should == 'goodbye'; done }
255
+ end
256
+ #
257
+ it "should be able to set a value by indexing into a list (LSET)" do
258
+ @r.rpush "list", 'hello'
259
+ @r.rpush "list", 'hello'
260
+ @r.type('list') { |r| r.should == "list" }
261
+ @r.llen('list') { |r| r.should == 2 }
262
+ @r.lset('list', 1, 'goodbye') { |r| r.should == 'OK' }
263
+ @r.lindex('list', 1) { |r| r.should == 'goodbye'; done }
264
+ end
265
+ #
266
+ it "should be able to remove values from a list (LREM)" do
267
+ @r.rpush "list", 'hello'
268
+ @r.rpush "list", 'goodbye'
269
+ @r.type('list') { |r| r.should == "list" }
270
+ @r.llen('list') { |r| r.should == 2 }
271
+ @r.lrem('list', 1, 'hello') { |r| r.should == 1 }
272
+ @r.lrange('list', 0, -1) { |r| r.should == ['goodbye']; done }
273
+ end
274
+
275
+ it "should be able to pop values from a list and push them onto a temp list(RPOPLPUSH)" do
276
+ @r.rpush "list", 'one'
277
+ @r.rpush "list", 'two'
278
+ @r.rpush "list", 'three'
279
+ @r.type('list') { |r| r.should == "list" }
280
+ @r.llen('list') { |r| r.should == 3 }
281
+ @r.lrange('list', 0, -1) { |r| r.should == ['one', 'two', 'three'] }
282
+ @r.lrange('tmp', 0, -1) { |r| r.should == [] }
283
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'three' }
284
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['three'] }
285
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'two' }
286
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['two', 'three'] }
287
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'one' }
288
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['one', 'two', 'three']; done }
289
+ end
290
+ #
291
+ it "should be able add members to a set (SADD)" do
292
+ @r.sadd "set", 'key1'
293
+ @r.sadd "set", 'key2'
294
+ @r.type('set') { |r| r.should == "set" }
295
+ @r.scard('set') { |r| r.should == 2 }
296
+ @r.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort; done }
297
+ end
298
+ #
299
+ it "should be able delete members to a set (SREM)" do
300
+ @r.sadd "set", 'key1'
301
+ @r.sadd "set", 'key2'
302
+ @r.type('set') { |r| r.should == "set" }
303
+ @r.scard('set') { |r| r.should == 2 }
304
+ @r.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort }
305
+ @r.srem('set', 'key1')
306
+ @r.scard('set') { |r| r.should == 1 }
307
+ @r.smembers('set') { |r| r.should == ['key2']; done }
308
+ end
309
+ #
310
+ it "should be able to return and remove random key from set (SPOP)" do
311
+ @r.sadd "set_pop", "key1"
312
+ @r.sadd "set_pop", "key2"
313
+ @r.spop("set_pop") { |r| r.should.not == nil }
314
+ @r.scard("set_pop") { |r| r.should == 1; done }
315
+ end
316
+ #
317
+ it "should be able to return random key without delete the key from a set (SRANDMEMBER)" do
318
+ @r.sadd "set_srandmember", "key1"
319
+ @r.sadd "set_srandmember", "key2"
320
+ @r.srandmember("set_srandmember") { |r| r.should.not == nil }
321
+ @r.scard("set_srandmember") { |r| r.should == 2; done }
322
+ end
323
+ #
324
+ it "should be able count the members of a set (SCARD)" do
325
+ @r.sadd "set", 'key1'
326
+ @r.sadd "set", 'key2'
327
+ @r.type('set') { |r| r.should == "set" }
328
+ @r.scard('set') { |r| r.should == 2; done }
329
+ end
330
+ #
331
+ it "should be able test for set membership (SISMEMBER)" do
332
+ @r.sadd "set", 'key1'
333
+ @r.sadd "set", 'key2'
334
+ @r.type('set') { |r| r.should == "set" }
335
+ @r.scard('set') { |r| r.should == 2 }
336
+ @r.sismember('set', 'key1') { |r| r.should == true }
337
+ @r.sismember('set', 'key2') { |r| r.should == true }
338
+ @r.sismember('set', 'notthere') { |r| r.should == false; done }
339
+ end
340
+ #
341
+ it "should be able to do set intersection (SINTER)" do
342
+ @r.sadd "set", 'key1'
343
+ @r.sadd "set", 'key2'
344
+ @r.sadd "set2", 'key2'
345
+ @r.sinter('set', 'set2') { |r| r.should == ['key2']; done }
346
+ end
347
+ #
348
+ it "should be able to do set intersection and store the results in a key (SINTERSTORE)" do
349
+ @r.sadd "set", 'key1'
350
+ @r.sadd "set", 'key2'
351
+ @r.sadd "set2", 'key2'
352
+ @r.sinterstore('newone', 'set', 'set2') { |r| r.should == 1 }
353
+ @r.smembers('newone') { |r| r.should == ['key2']; done }
354
+ end
355
+ #
356
+ it "should be able to do set union (SUNION)" do
357
+ @r.sadd "set", 'key1'
358
+ @r.sadd "set", 'key2'
359
+ @r.sadd "set2", 'key2'
360
+ @r.sadd "set2", 'key3'
361
+ @r.sunion('set', 'set2') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
362
+ end
363
+ #
364
+ it "should be able to do set union and store the results in a key (SUNIONSTORE)" do
365
+ @r.sadd "set", 'key1'
366
+ @r.sadd "set", 'key2'
367
+ @r.sadd "set2", 'key2'
368
+ @r.sadd "set2", 'key3'
369
+ @r.sunionstore('newone', 'set', 'set2') { |r| r.should == 3 }
370
+ @r.smembers('newone') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
371
+ end
372
+ #
373
+ it "should be able to do set difference (SDIFF)" do
374
+ @r.sadd "set", 'a'
375
+ @r.sadd "set", 'b'
376
+ @r.sadd "set2", 'b'
377
+ @r.sadd "set2", 'c'
378
+ @r.sdiff('set', 'set2') { |r| r.should == ['a']; done }
379
+ end
380
+ #
381
+ it "should be able to do set difference and store the results in a key (SDIFFSTORE)" do
382
+ @r.sadd "set", 'a'
383
+ @r.sadd "set", 'b'
384
+ @r.sadd "set2", 'b'
385
+ @r.sadd "set2", 'c'
386
+ @r.sdiffstore('newone', 'set', 'set2')
387
+ @r.smembers('newone') { |r| r.should == ['a']; done }
388
+ end
389
+ #
390
+ it "should be able move elements from one set to another (SMOVE)" do
391
+ @r.sadd 'set1', 'a'
392
+ @r.sadd 'set1', 'b'
393
+ @r.sadd 'set2', 'x'
394
+ @r.smove('set1', 'set2', 'a') { |r| r.should == true }
395
+ @r.sismember('set2', 'a') { |r| r.should == true }
396
+ @r.delete('set1') { done }
397
+ end
398
+ #
399
+ it "should be able to do crazy SORT queries" do
400
+ # The 'Dogs' is capitialized on purpose
401
+ @r['dog_1'] = 'louie'
402
+ @r.rpush 'Dogs', 1
403
+ @r['dog_2'] = 'lucy'
404
+ @r.rpush 'Dogs', 2
405
+ @r['dog_3'] = 'max'
406
+ @r.rpush 'Dogs', 3
407
+ @r['dog_4'] = 'taj'
408
+ @r.rpush 'Dogs', 4
409
+ @r.sort('Dogs', :get => 'dog_*', :limit => [0,1]) { |r| r.should == ['louie'] }
410
+ @r.sort('Dogs', :get => 'dog_*', :limit => [0,1], :order => 'desc alpha') { |r| r.should == ['taj'] }
411
+ @r.ping { done }
412
+ end
413
+
414
+ it "should be able to handle array of :get using SORT" do
415
+ @r['dog:1:name'] = 'louie'
416
+ @r['dog:1:breed'] = 'mutt'
417
+ @r.rpush 'dogs', 1
418
+ @r['dog:2:name'] = 'lucy'
419
+ @r['dog:2:breed'] = 'poodle'
420
+ @r.rpush 'dogs', 2
421
+ @r['dog:3:name'] = 'max'
422
+ @r['dog:3:breed'] = 'hound'
423
+ @r.rpush 'dogs', 3
424
+ @r['dog:4:name'] = 'taj'
425
+ @r['dog:4:breed'] = 'terrier'
426
+ @r.rpush 'dogs', 4
427
+ @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1]) { |r| r.should == ['louie', 'mutt'] }
428
+ @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1], :order => 'desc alpha') { |r| r.should == ['taj', 'terrier'] }
429
+ @r.ping { done }
430
+ end
431
+ #
432
+ it "should be able count the members of a zset" do
433
+ @r.set_add "set", 'key1'
434
+ @r.set_add "set", 'key2'
435
+ @r.zset_add 'zset', 1, 'set'
436
+ @r.zset_count('zset') { |r| r.should == 1 }
437
+ @r.delete('set')
438
+ @r.delete('zset') { done }
439
+ end
440
+ #
441
+ it "should be able add members to a zset" do
442
+ @r.set_add "set", 'key1'
443
+ @r.set_add "set", 'key2'
444
+ @r.zset_add 'zset', 1, 'set'
445
+ @r.zset_range('zset', 0, 1) { |r| r.should == ['set'] }
446
+ @r.zset_count('zset') { |r| r.should == 1 }
447
+ @r.delete('set')
448
+ @r.delete('zset') { done }
449
+ end
450
+ #
451
+ it "should be able delete members to a zset" do
452
+ @r.set_add "set", 'key1'
453
+ @r.set_add "set", 'key2'
454
+ @r.type?('set') { |r| r.should == "set" }
455
+ @r.set_add "set2", 'key3'
456
+ @r.set_add "set2", 'key4'
457
+ @r.type?('set2') { |r| r.should == "set" }
458
+ @r.zset_add 'zset', 1, 'set'
459
+ @r.zset_count('zset') { |r| r.should == 1 }
460
+ @r.zset_add 'zset', 2, 'set2'
461
+ @r.zset_count('zset') { |r| r.should == 2 }
462
+ @r.zset_delete 'zset', 'set'
463
+ @r.zset_count('zset') { |r| r.should == 1 }
464
+ @r.delete('set')
465
+ @r.delete('set2')
466
+ @r.delete('zset') { done }
467
+ end
468
+ #
469
+ it "should be able to get a range of values from a zset" do
470
+ @r.set_add "set", 'key1'
471
+ @r.set_add "set", 'key2'
472
+ @r.set_add "set2", 'key3'
473
+ @r.set_add "set2", 'key4'
474
+ @r.set_add "set3", 'key1'
475
+ @r.type?('set') { |r| r.should == 'set' }
476
+ @r.type?('set2') { |r| r.should == 'set' }
477
+ @r.type?('set3') { |r| r.should == 'set' }
478
+ @r.zset_add 'zset', 1, 'set'
479
+ @r.zset_add 'zset', 2, 'set2'
480
+ @r.zset_add 'zset', 3, 'set3'
481
+ @r.zset_count('zset') { |r| r.should == 3 }
482
+ @r.zset_range('zset', 0, 3) { |r| r.should == ['set', 'set2', 'set3'] }
483
+ @r.delete('set')
484
+ @r.delete('set2')
485
+ @r.delete('set3')
486
+ @r.delete('zset') { done }
487
+ end
488
+ #
489
+ it "should be able to get a reverse range of values from a zset" do
490
+ @r.set_add "set", 'key1'
491
+ @r.set_add "set", 'key2'
492
+ @r.set_add "set2", 'key3'
493
+ @r.set_add "set2", 'key4'
494
+ @r.set_add "set3", 'key1'
495
+ @r.type?('set') { |r| r.should == 'set' }
496
+ @r.type?('set2') { |r| r.should == 'set' }
497
+ @r.type?('set3') { |r| r.should == 'set' }
498
+ @r.zset_add 'zset', 1, 'set'
499
+ @r.zset_add 'zset', 2, 'set2'
500
+ @r.zset_add 'zset', 3, 'set3'
501
+ @r.zset_count('zset') { |r| r.should == 3 }
502
+ @r.zset_reverse_range('zset', 0, 3) { |r| r.should == ['set3', 'set2', 'set'] }
503
+ @r.delete('set')
504
+ @r.delete('set2')
505
+ @r.delete('set3')
506
+ @r.delete('zset') { done }
507
+ end
508
+ #
509
+ it "should be able to get a range by score of values from a zset" do
510
+ @r.set_add "set", 'key1'
511
+ @r.set_add "set", 'key2'
512
+ @r.set_add "set2", 'key3'
513
+ @r.set_add "set2", 'key4'
514
+ @r.set_add "set3", 'key1'
515
+ @r.set_add "set4", 'key4'
516
+ @r.zset_add 'zset', 1, 'set'
517
+ @r.zset_add 'zset', 2, 'set2'
518
+ @r.zset_add 'zset', 3, 'set3'
519
+ @r.zset_add 'zset', 4, 'set4'
520
+ @r.zset_count('zset') { |r| r.should == 4 }
521
+ @r.zset_range_by_score('zset', 2, 3) { |r| r.should == ['set2', 'set3'] }
522
+ @r.delete('set')
523
+ @r.delete('set2')
524
+ @r.delete('set3')
525
+ @r.delete('set4')
526
+ @r.delete('zset') { done }
527
+ end
528
+ #
529
+ it "should be able to get a score for a specific value in a zset (ZSCORE)" do
530
+ @r.zset_add "zset", 23, "value"
531
+ @r.zset_score("zset", "value") { |r| r.should == "23" }
532
+
533
+ @r.zset_score("zset", "value2") { |r| r.should == nil }
534
+ @r.zset_score("unknown_zset", "value") { |r| r.should == nil }
535
+
536
+ @r.delete("zset") { done }
537
+ end
538
+ #
539
+ it "should be able to increment a range score of a zset (ZINCRBY)" do
540
+ # create a new zset
541
+ @r.zset_increment_by "hackers", 1965, "Yukihiro Matsumoto"
542
+ @r.zset_score("hackers", "Yukihiro Matsumoto") { |r| r.should == "1965" }
543
+
544
+ # add a new element
545
+ @r.zset_increment_by "hackers", 1912, "Alan Turing"
546
+ @r.zset_score("hackers", "Alan Turing") { |r| r.should == "1912" }
547
+
548
+ # update the score
549
+ @r.zset_increment_by "hackers", 100, "Alan Turing" # yeah, we are making Turing a bit younger
550
+ @r.zset_score("hackers", "Alan Turing") { |r| r.should == "2012" }
551
+
552
+ # attempt to update a key that's not a zset
553
+ @r["i_am_not_a_zet"] = "value"
554
+ # should raise error
555
+ @r.on_error { true.should == true }
556
+ @r.zset_incr_by("i_am_not_a_zet", 23, "element") { false.should == true }
557
+
558
+ @r.delete("hackers")
559
+ @r.delete("i_am_not_a_zet") { done }
560
+ end
561
+ #
562
+ it "should provide info (INFO)" do
563
+ @r.info do |r|
564
+ [:last_save_time, :redis_version, :total_connections_received, :connected_clients, :total_commands_processed, :connected_slaves, :uptime_in_seconds, :used_memory, :uptime_in_days, :changes_since_last_save].each do |x|
565
+ r.keys.include?(x).should == true
566
+ end
567
+ done
568
+ end
569
+ end
570
+ #
571
+ it "should be able to flush the database (FLUSHDB)" do
572
+ @r['key1'] = 'keyone'
573
+ @r['key2'] = 'keytwo'
574
+ @r.keys('*') { |r| r.sort.should == ['foo', 'key1', 'key2'].sort } #foo from before
575
+ @r.flushdb
576
+ @r.keys('*') { |r| r.should == []; done }
577
+ end
578
+ #
579
+ it "should be able to SELECT database" do
580
+ @r.select(15)
581
+ @r.get('foo') { |r| r.should == nil; done }
582
+ end
583
+ #
584
+ it "should be able to provide the last save time (LASTSAVE)" do
585
+ @r.lastsave do |savetime|
586
+ Time.at(savetime).class.should == Time
587
+ Time.at(savetime).should <= Time.now
588
+ done
589
+ end
590
+ end
591
+
592
+ it "should be able to MGET keys" do
593
+ @r['foo'] = 1000
594
+ @r['bar'] = 2000
595
+ @r.mget('foo', 'bar') { |r| r.should == ['1000', '2000'] }
596
+ @r.mget('foo', 'bar', 'baz') { |r| r.should == ['1000', '2000', nil] }
597
+ @r.ping { done }
598
+ end
599
+
600
+ it "should be able to mapped MGET keys" do
601
+ @r['foo'] = 1000
602
+ @r['bar'] = 2000
603
+ @r.mapped_mget('foo', 'bar') { |r| r.should == { 'foo' => '1000', 'bar' => '2000'} }
604
+ @r.mapped_mget('foo', 'baz', 'bar') { |r| r.should == { 'foo' => '1000', 'bar' => '2000'} }
605
+ @r.ping { done }
606
+ end
607
+
608
+ it "should be able to MSET values" do
609
+ @r.mset :key1 => "value1", :key2 => "value2"
610
+ @r.get('key1') { |r| r.should == "value1" }
611
+ @r.get('key2') { |r| r.should == "value2"; done }
612
+ end
613
+
614
+ it "should be able to MSETNX values" do
615
+ @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
616
+ @r.mget('keynx1', 'keynx2') { |r| r.should == ["valuenx1", "valuenx2"] }
617
+
618
+ @r["keynx1"] = "value1"
619
+ @r["keynx2"] = "value2"
620
+ @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
621
+ @r.mget('keynx1', 'keynx2') { |r| r.should == ["value1", "value2"]; done }
622
+ end
623
+
624
+ it "should bgsave" do
625
+ @r.bgsave do |r|
626
+ ['OK', 'Background saving started'].include?(r).should == true
627
+ done
628
+ end
629
+ end
630
+
631
+ it "should be able to ECHO" do
632
+ @r.echo("message in a bottle\n") { |r| r.should == "message in a bottle\n"; done }
633
+ end
634
+
635
+ # Tests are disabled due uncatchable exceptions. We should use on_error callback,
636
+ # intead of raising exceptions in random places.
637
+ #
638
+ # it "should raise error when invoke MONITOR" do
639
+ # # lambda { @r.monitor }.should.raise
640
+ # done
641
+ # end
642
+ #
643
+ # it "should raise error when invoke SYNC" do
644
+ # # lambda { @r.sync }.should.raise
645
+ # done
646
+ # end
647
+ end