superfeedr-em-redis 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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