gilmour-em-hiredis 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,931 @@
1
+ require 'spec_helper'
2
+
3
+ describe EventMachine::Hiredis, "commands" do
4
+ it "pings" do
5
+ connect do |redis|
6
+ redis.ping { |r| r.should == 'PONG'; done }
7
+ end
8
+ end
9
+
10
+ it "SETs and GETs a key" do
11
+ connect do |redis|
12
+ redis.set('foo', 'nik')
13
+ redis.get('foo') { |r| r.should == 'nik'; done }
14
+ end
15
+ end
16
+
17
+ it "handles trailing newline characters" do
18
+ connect do |redis|
19
+ redis.set('foo', "bar\n")
20
+ redis.get('foo') { |r| r.should == "bar\n"; done }
21
+ end
22
+ end
23
+
24
+ it "stores and retrieves all possible characters at the beginning and the end of a string" do
25
+ connect do |redis|
26
+ (0..255).each do |char_idx|
27
+ string = "#{char_idx.chr}---#{char_idx.chr}"
28
+ if RUBY_VERSION > "1.9"
29
+ string.force_encoding("UTF-8")
30
+ end
31
+ redis.set('foo', string)
32
+ redis.get('foo') { |r| r.should == string }
33
+ end
34
+ redis.ping { done }
35
+ end
36
+ end
37
+
38
+ it "SETs a key with an expiry" do
39
+ connect do |redis|
40
+ timeout(3)
41
+
42
+ redis.setex('foo', 1, 'bar')
43
+ redis.get('foo') { |r| r.should == 'bar' }
44
+ EventMachine.add_timer(2) do
45
+ redis.get('foo') { |r| r.should == nil }
46
+ redis.ping { done }
47
+ end
48
+ end
49
+ end
50
+
51
+ it "gets TTL for a key" do
52
+ connect do |redis|
53
+ redis.setex('foo', 1, 'bar')
54
+ redis.ttl('foo') { |r| r.should == 1; done }
55
+ end
56
+ end
57
+
58
+ it "can SETNX" do
59
+ connect do |redis|
60
+ redis.set('foo', 'nik')
61
+ redis.get('foo') { |r| r.should == 'nik' }
62
+ redis.setnx 'foo', 'bar'
63
+ redis.get('foo') { |r| r.should == 'nik' }
64
+
65
+ redis.ping { done }
66
+ end
67
+ end
68
+
69
+ it "can GETSET" do
70
+ connect do |redis|
71
+ redis.set('foo', 'bar')
72
+ redis.getset('foo', 'baz') { |r| r.should == 'bar' }
73
+ redis.get('foo') { |r| r.should == 'baz'; done }
74
+ end
75
+ end
76
+
77
+ it "can INCR a key" do
78
+ connect do |redis|
79
+ redis.del('counter')
80
+ redis.incr('counter') { |r| r.should == 1 }
81
+ redis.incr('counter') { |r| r.should == 2 }
82
+ redis.incr('counter') { |r| r.should == 3 }
83
+
84
+ redis.ping { done }
85
+ end
86
+ end
87
+
88
+ it "can INCRBY a key" do
89
+ connect do |redis|
90
+ redis.del('counter')
91
+ redis.incrby('counter', 1) { |r| r.should == 1 }
92
+ redis.incrby('counter', 2) { |r| r.should == 3 }
93
+ redis.incrby('counter', 3) { |r| r.should == 6 }
94
+
95
+ redis.ping { done }
96
+ end
97
+ end
98
+
99
+ it "can DECR a key" do
100
+ connect do |redis|
101
+ redis.del('counter')
102
+ redis.incr('counter') { |r| r.should == 1 }
103
+ redis.incr('counter') { |r| r.should == 2 }
104
+ redis.incr('counter') { |r| r.should == 3 }
105
+ redis.decr('counter') { |r| r.should == 2 }
106
+ redis.decrby('counter', 2) { |r| r.should == 0; done }
107
+ end
108
+ end
109
+
110
+ it "can RANDOMKEY" do
111
+ connect do |redis|
112
+ redis.set('foo', 'bar')
113
+ redis.randomkey { |r| r.should_not == nil; done }
114
+ end
115
+ end
116
+
117
+ it "can RENAME a key" do
118
+ connect do |redis|
119
+ redis.del 'foo'
120
+ redis.del 'bar'
121
+ redis.set('foo', 'hi')
122
+ redis.rename 'foo', 'bar'
123
+ redis.get('bar') { |r| r.should == 'hi' ; done }
124
+ end
125
+ end
126
+
127
+ it "can RENAMENX a key" do
128
+ connect do |redis|
129
+ redis.del 'foo'
130
+ redis.del 'bar'
131
+ redis.set('foo', 'hi')
132
+ redis.set('bar', 'ohai')
133
+ redis.renamenx 'foo', 'bar'
134
+ redis.get('bar') { |r| r.should == 'ohai' ; done }
135
+ end
136
+ end
137
+
138
+ it "can get DBSIZE of the database" do
139
+ connect do |redis|
140
+ redis.set('foo1', 'bar')
141
+ redis.set('foo2', 'baz')
142
+ redis.set('foo3', 'bat')
143
+ redis.dbsize do |r|
144
+ r.should == 3
145
+ done
146
+ end
147
+ end
148
+ end
149
+
150
+ it "can EXPIRE a key" do
151
+ connect do |redis|
152
+ timeout(3)
153
+
154
+ redis.set('foo', 'bar')
155
+ redis.expire 'foo', 1
156
+ redis.get('foo') { |r| r.should == "bar" }
157
+ EventMachine.add_timer(2) do
158
+ redis.get('foo') { |r| r.should == nil }
159
+ redis.ping { done }
160
+ end
161
+ end
162
+ end
163
+
164
+
165
+ it "can check if a key EXISTS" do
166
+ connect do |redis|
167
+ redis.set 'foo', 'nik'
168
+ redis.exists('foo') { |r| r.should == 1 }
169
+ redis.del 'foo'
170
+ redis.exists('foo') { |r| r.should == 0 ; done }
171
+ end
172
+ end
173
+
174
+ it "can list KEYS" do
175
+ connect do |redis|
176
+ redis.keys("f*") { |keys| keys.each { |key| @r.del key } }
177
+ redis.set('f', 'nik')
178
+ redis.set('fo', 'nak')
179
+ redis.set('foo', 'qux')
180
+ redis.keys("f*") { |r| r.sort.should == ['f', 'fo', 'foo'].sort }
181
+
182
+ redis.ping { done }
183
+ end
184
+ end
185
+
186
+ it "returns a random key (RANDOMKEY)" do
187
+ connect do |redis|
188
+ redis.set("foo", "bar")
189
+ redis.randomkey do |r|
190
+ redis.exists(r) do |e|
191
+ e.should == 1
192
+ done
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ it "should be able to check the TYPE of a key" do
199
+ connect do |redis|
200
+ redis.set('foo', 'nik')
201
+ redis.type('foo') { |r| r.should == "string" }
202
+ redis.del 'foo'
203
+ redis.type('foo') { |r| r.should == "none" ; done }
204
+ end
205
+ end
206
+
207
+ it "pushes to the head of a list (LPUSH)" do
208
+ connect do |redis|
209
+ redis.lpush "list", 'hello'
210
+ redis.lpush "list", 42
211
+ redis.type('list') { |r| r.should == "list" }
212
+ redis.llen('list') { |r| r.should == 2 }
213
+ redis.lpop('list') { |r| r.should == '42'; done }
214
+ end
215
+ end
216
+
217
+ it "pushes to the tail of a list (RPUSH)" do
218
+ connect do |redis|
219
+ redis.rpush "list", 'hello'
220
+ redis.type('list') { |r| r.should == "list" }
221
+ redis.llen('list') { |r| r.should == 1 ; done }
222
+ end
223
+ end
224
+
225
+ it "pops the tail of a list (RPOP)" do
226
+ connect do |redis|
227
+ redis.rpush "list", 'hello'
228
+ redis.rpush"list", 'goodbye'
229
+ redis.type('list') { |r| r.should == "list" }
230
+ redis.llen('list') { |r| r.should == 2 }
231
+ redis.rpop('list') { |r| r.should == 'goodbye'; done }
232
+ end
233
+ end
234
+
235
+ it "pop the head of a list (LPOP)" do
236
+ connect do |redis|
237
+ redis.rpush "list", 'hello'
238
+ redis.rpush "list", 'goodbye'
239
+ redis.type('list') { |r| r.should == "list" }
240
+ redis.llen('list') { |r| r.should == 2 }
241
+ redis.lpop('list') { |r| r.should == 'hello'; done }
242
+ end
243
+ end
244
+
245
+ it "gets the length of a list (LLEN)" do
246
+ connect do |redis|
247
+ redis.rpush "list", 'hello'
248
+ redis.rpush "list", 'goodbye'
249
+ redis.type('list') { |r| r.should == "list" }
250
+ redis.llen('list') { |r| r.should == 2 ; done }
251
+ end
252
+ end
253
+
254
+ it "gets a range of values from a list (LRANGE)" do
255
+ connect do |redis|
256
+ redis.rpush "list", 'hello'
257
+ redis.rpush "list", 'goodbye'
258
+ redis.rpush "list", '1'
259
+ redis.rpush "list", '2'
260
+ redis.rpush "list", '3'
261
+ redis.type('list') { |r| r.should == "list" }
262
+ redis.llen('list') { |r| r.should == 5 }
263
+ redis.lrange('list', 2, -1) { |r| r.should == ['1', '2', '3']; done }
264
+ end
265
+ end
266
+
267
+ it "trims a list (LTRIM)" do
268
+ connect do |redis|
269
+ redis.rpush "list", 'hello'
270
+ redis.rpush "list", 'goodbye'
271
+ redis.rpush "list", '1'
272
+ redis.rpush "list", '2'
273
+ redis.rpush "list", '3'
274
+ redis.type('list') { |r| r.should == "list" }
275
+ redis.llen('list') { |r| r.should == 5 }
276
+ redis.ltrim 'list', 0, 1
277
+ redis.llen('list') { |r| r.should == 2 }
278
+ redis.lrange('list', 0, -1) { |r| r.should == ['hello', 'goodbye']; done }
279
+ end
280
+ end
281
+
282
+ it "gets a value by indexing into a list (LINDEX)" do
283
+ connect do |redis|
284
+ redis.rpush "list", 'hello'
285
+ redis.rpush "list", 'goodbye'
286
+ redis.type('list') { |r| r.should == "list" }
287
+ redis.llen('list') { |r| r.should == 2 }
288
+ redis.lindex('list', 1) { |r| r.should == 'goodbye'; done }
289
+ end
290
+ end
291
+
292
+ it "sets a value by indexing into a list (LSET)" do
293
+ connect do |redis|
294
+ redis.rpush "list", 'hello'
295
+ redis.rpush "list", 'hello'
296
+ redis.type('list') { |r| r.should == "list" }
297
+ redis.llen('list') { |r| r.should == 2 }
298
+ redis.lset('list', 1, 'goodbye') { |r| r.should == 'OK' }
299
+ redis.lindex('list', 1) { |r| r.should == 'goodbye'; done }
300
+ end
301
+ end
302
+
303
+ it "removes values from a list (LREM)" do
304
+ connect do |redis|
305
+ redis.rpush "list", 'hello'
306
+ redis.rpush "list", 'goodbye'
307
+ redis.type('list') { |r| r.should == "list" }
308
+ redis.llen('list') { |r| r.should == 2 }
309
+ redis.lrem('list', 1, 'hello') { |r| r.should == 1 }
310
+ redis.lrange('list', 0, -1) { |r| r.should == ['goodbye']; done }
311
+ end
312
+ end
313
+
314
+ it "pops values from a list and push them onto a temp list(RPOPLPUSH)" do
315
+ connect do |redis|
316
+ redis.rpush "list", 'one'
317
+ redis.rpush "list", 'two'
318
+ redis.rpush "list", 'three'
319
+ redis.type('list') { |r| r.should == "list" }
320
+ redis.llen('list') { |r| r.should == 3 }
321
+ redis.lrange('list', 0, -1) { |r| r.should == ['one', 'two', 'three'] }
322
+ redis.lrange('tmp', 0, -1) { |r| r.should == [] }
323
+ redis.rpoplpush('list', 'tmp') { |r| r.should == 'three' }
324
+ redis.lrange('tmp', 0, -1) { |r| r.should == ['three'] }
325
+ redis.rpoplpush('list', 'tmp') { |r| r.should == 'two' }
326
+ redis.lrange('tmp', 0, -1) { |r| r.should == ['two', 'three'] }
327
+ redis.rpoplpush('list', 'tmp') { |r| r.should == 'one' }
328
+ redis.lrange('tmp', 0, -1) { |r| r.should == ['one', 'two', 'three']; done }
329
+ end
330
+ end
331
+
332
+ it "adds members to a set (SADD)" do
333
+ connect do |redis|
334
+ redis.sadd "set", 'key1'
335
+ redis.sadd "set", 'key2'
336
+ redis.type('set') { |r| r.should == "set" }
337
+ redis.scard('set') { |r| r.should == 2 }
338
+ redis.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort; done }
339
+ end
340
+ end
341
+
342
+ it "deletes members to a set (SREM)" do
343
+ connect do |redis|
344
+ redis.sadd "set", 'key1'
345
+ redis.sadd "set", 'key2'
346
+ redis.type('set') { |r| r.should == "set" }
347
+ redis.scard('set') { |r| r.should == 2 }
348
+ redis.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort }
349
+ redis.srem('set', 'key1')
350
+ redis.scard('set') { |r| r.should == 1 }
351
+ redis.smembers('set') { |r| r.should == ['key2']; done }
352
+ end
353
+ end
354
+
355
+ it "returns and remove random key from set (SPOP)" do
356
+ connect do |redis|
357
+ redis.sadd "set_pop", "key1"
358
+ redis.sadd "set_pop", "key2"
359
+ redis.spop("set_pop") { |r| r.should_not == nil }
360
+ redis.scard("set_pop") { |r| r.should == 1; done }
361
+ end
362
+ end
363
+
364
+ it "returns random key without delete the key from a set (SRANDMEMBER)" do
365
+ connect do |redis|
366
+ redis.sadd "set_srandmember", "key1"
367
+ redis.sadd "set_srandmember", "key2"
368
+ redis.srandmember("set_srandmember") { |r| r.should_not == nil }
369
+ redis.scard("set_srandmember") { |r| r.should == 2; done }
370
+ end
371
+ end
372
+
373
+ it "counts the members of a set (SCARD)" do
374
+ connect do |redis|
375
+ redis.sadd "set", 'key1'
376
+ redis.sadd "set", 'key2'
377
+ redis.type('set') { |r| r.should == "set" }
378
+ redis.scard('set') { |r| r.should == 2; done }
379
+ end
380
+ end
381
+
382
+ it "tests for set membership (SISMEMBER)" do
383
+ connect do |redis|
384
+ redis.sadd "set", 'key1'
385
+ redis.sadd "set", 'key2'
386
+ redis.type('set') { |r| r.should == "set" }
387
+ redis.scard('set') { |r| r.should == 2 }
388
+ redis.sismember('set', 'key1') { |r| r.should == 1 }
389
+ redis.sismember('set', 'key2') { |r| r.should == 1 }
390
+ redis.sismember('set', 'notthere') { |r| r.should == 0; done }
391
+ end
392
+ end
393
+
394
+ it "intersects sets (SINTER)" do
395
+ connect do |redis|
396
+ redis.sadd "set", 'key1'
397
+ redis.sadd "set", 'key2'
398
+ redis.sadd "set2", 'key2'
399
+ redis.sinter('set', 'set2') { |r| r.should == ['key2']; done }
400
+ end
401
+ end
402
+
403
+ it "intersects set and stores the results in a key (SINTERSTORE)" do
404
+ connect do |redis|
405
+ redis.sadd "set", 'key1'
406
+ redis.sadd "set", 'key2'
407
+ redis.sadd "set2", 'key2'
408
+ redis.sinterstore('newone', 'set', 'set2') { |r| r.should == 1 }
409
+ redis.smembers('newone') { |r| r.should == ['key2']; done }
410
+ end
411
+ end
412
+
413
+ it "performs set unions (SUNION)" do
414
+ connect do |redis|
415
+ redis.sadd "set", 'key1'
416
+ redis.sadd "set", 'key2'
417
+ redis.sadd "set2", 'key2'
418
+ redis.sadd "set2", 'key3'
419
+ redis.sunion('set', 'set2') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
420
+ end
421
+ end
422
+
423
+ it "performs a set union and store the results in a key (SUNIONSTORE)" do
424
+ connect do |redis|
425
+ redis.sadd "set", 'key1'
426
+ redis.sadd "set", 'key2'
427
+ redis.sadd "set2", 'key2'
428
+ redis.sadd "set2", 'key3'
429
+ redis.sunionstore('newone', 'set', 'set2') { |r| r.should == 3 }
430
+ redis.smembers('newone') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
431
+ end
432
+ end
433
+
434
+ it "takes a set difference (SDIFF)" do
435
+ connect do |redis|
436
+ redis.sadd "set", 'a'
437
+ redis.sadd "set", 'b'
438
+ redis.sadd "set2", 'b'
439
+ redis.sadd "set2", 'c'
440
+ redis.sdiff('set', 'set2') { |r| r.should == ['a']; done }
441
+ end
442
+ end
443
+
444
+ it "takes set difference and store the results in a key (SDIFFSTORE)" do
445
+ connect do |redis|
446
+ redis.sadd "set", 'a'
447
+ redis.sadd "set", 'b'
448
+ redis.sadd "set2", 'b'
449
+ redis.sadd "set2", 'c'
450
+ redis.sdiffstore('newone', 'set', 'set2')
451
+ redis.smembers('newone') { |r| r.should == ['a']; done }
452
+ end
453
+ end
454
+
455
+ it "moves elements from one set to another (SMOVE)" do
456
+ connect do |redis|
457
+ redis.sadd 'set1', 'a'
458
+ redis.sadd 'set1', 'b'
459
+ redis.sadd 'set2', 'x'
460
+ redis.smove('set1', 'set2', 'a') { |r| r.should == 1 }
461
+ redis.sismember('set2', 'a') { |r| r.should == 1 }
462
+ redis.del('set1') { done }
463
+ end
464
+ end
465
+
466
+ it "counts the members of a zset" do
467
+ connect do |redis|
468
+ redis.sadd "set", 'key1'
469
+ redis.sadd "set", 'key2'
470
+ redis.zadd 'zset', 1, 'set'
471
+ redis.zcount('zset') { |r| r.should == 1 }
472
+ redis.del('set')
473
+ redis.del('zset') { done }
474
+ end
475
+ end
476
+
477
+ it "adds members to a zset" do
478
+ connect do |redis|
479
+ redis.sadd "set", 'key1'
480
+ redis.sadd "set", 'key2'
481
+ redis.zadd 'zset', 1, 'set'
482
+ redis.zrange('zset', 0, 1) { |r| r.should == ['set'] }
483
+ redis.zcount('zset') { |r| r.should == 1 }
484
+ redis.del('set')
485
+ redis.del('zset') { done }
486
+ end
487
+ end
488
+
489
+ it "deletes members to a zset" do
490
+ connect do |redis|
491
+ redis.sadd "set", 'key1'
492
+ redis.sadd "set", 'key2'
493
+ redis.type?('set') { |r| r.should == "set" }
494
+ redis.sadd "set2", 'key3'
495
+ redis.sadd "set2", 'key4'
496
+ redis.type?('set2') { |r| r.should == "set" }
497
+ redis.zadd 'zset', 1, 'set'
498
+ redis.zcount('zset') { |r| r.should == 1 }
499
+ redis.zadd 'zset', 2, 'set2'
500
+ redis.zcount('zset') { |r| r.should == 2 }
501
+ redis.zset_delete 'zset', 'set'
502
+ redis.zcount('zset') { |r| r.should == 1 }
503
+ redis.del('set')
504
+ redis.del('set2')
505
+ redis.del('zset') { done }
506
+ end
507
+ end
508
+
509
+ it "gets a range of values from a zset" do
510
+ connect do |redis|
511
+ redis.sadd "set", 'key1'
512
+ redis.sadd "set", 'key2'
513
+ redis.sadd "set2", 'key3'
514
+ redis.sadd "set2", 'key4'
515
+ redis.sadd "set3", 'key1'
516
+ redis.type?('set') { |r| r.should == 'set' }
517
+ redis.type?('set2') { |r| r.should == 'set' }
518
+ redis.type?('set3') { |r| r.should == 'set' }
519
+ redis.zadd 'zset', 1, 'set'
520
+ redis.zadd 'zset', 2, 'set2'
521
+ redis.zadd 'zset', 3, 'set3'
522
+ redis.zcount('zset') { |r| r.should == 3 }
523
+ redis.zrange('zset', 0, 3) { |r| r.should == ['set', 'set2', 'set3'] }
524
+ redis.del('set')
525
+ redis.del('set2')
526
+ redis.del('set3')
527
+ redis.del('zset') { done }
528
+ end
529
+ end
530
+
531
+ it "gets a reverse range of values from a zset" do
532
+ connect do |redis|
533
+ redis.sadd "set", 'key1'
534
+ redis.sadd "set", 'key2'
535
+ redis.sadd "set2", 'key3'
536
+ redis.sadd "set2", 'key4'
537
+ redis.sadd "set3", 'key1'
538
+ redis.type?('set') { |r| r.should == 'set' }
539
+ redis.type?('set2') { |r| r.should == 'set' }
540
+ redis.type?('set3') { |r| r.should == 'set' }
541
+ redis.zadd 'zset', 1, 'set'
542
+ redis.zadd 'zset', 2, 'set2'
543
+ redis.zadd 'zset', 3, 'set3'
544
+ redis.zcount('zset') { |r| r.should == 3 }
545
+ redis.zrevrange('zset', 0, 3) { |r| r.should == ['set3', 'set2', 'set'] }
546
+ redis.del('set')
547
+ redis.del('set2')
548
+ redis.del('set3')
549
+ redis.del('zset') { done }
550
+ end
551
+ end
552
+
553
+ it "gets a range by score of values from a zset" do
554
+ connect do |redis|
555
+ redis.sadd "set", 'key1'
556
+ redis.sadd "set", 'key2'
557
+ redis.sadd "set2", 'key3'
558
+ redis.sadd "set2", 'key4'
559
+ redis.sadd "set3", 'key1'
560
+ redis.sadd "set4", 'key4'
561
+ redis.zadd 'zset', 1, 'set'
562
+ redis.zadd 'zset', 2, 'set2'
563
+ redis.zadd 'zset', 3, 'set3'
564
+ redis.zadd 'zset', 4, 'set4'
565
+ redis.zcount('zset') { |r| r.should == 4 }
566
+ redis.zrangebyscore('zset', 2, 3) { |r| r.should == ['set2', 'set3'] }
567
+ redis.del('set')
568
+ redis.del('set2')
569
+ redis.del('set3')
570
+ redis.del('set4')
571
+ redis.del('zset') { done }
572
+ end
573
+ end
574
+
575
+ it "gets a score for a specific value in a zset (ZSCORE)" do
576
+ connect do |redis|
577
+ redis.zadd "zset", 23, "value"
578
+ redis.zscore("zset", "value") { |r| r.should == "23" }
579
+
580
+ redis.zscore("zset", "value2") { |r| r.should == nil }
581
+ redis.zscore("unknown_zset", "value") { |r| r.should == nil }
582
+
583
+ redis.del("zset") { done }
584
+ end
585
+ end
586
+
587
+ it "increments a range score of a zset (ZINCRBY)" do
588
+ connect do |redis|
589
+ # create a new zset
590
+ redis.zincrby "hackers", 1965, "Yukihiro Matsumoto"
591
+ redis.zscore("hackers", "Yukihiro Matsumoto") { |r| r.should == "1965" }
592
+
593
+ # add a new element
594
+ redis.zincrby "hackers", 1912, "Alan Turing"
595
+ redis.zscore("hackers", "Alan Turing") { |r| r.should == "1912" }
596
+
597
+ # update the score
598
+ redis.zincrby "hackers", 100, "Alan Turing" # yeah, we are making Turing a bit younger
599
+ redis.zscore("hackers", "Alan Turing") { |r| r.should == "2012" }
600
+
601
+ # attempt to update a key that's not a zset
602
+ redis.set("i_am_not_a_zet", "value")
603
+ # shouldn't raise error anymore
604
+ redis.zincrby("i_am_not_a_zet", 23, "element") { |r| r.should == nil }
605
+
606
+ redis.del("hackers")
607
+ redis.del("i_am_not_a_zet") { done }
608
+ end
609
+ end
610
+
611
+ it "provides info (INFO)" do
612
+ connect do |redis|
613
+ redis.info do |r|
614
+ [:redis_version, :total_connections_received, :connected_clients, :total_commands_processed, :connected_slaves, :uptime_in_seconds, :used_memory, :uptime_in_days].each do |x|
615
+ r.keys.include?(x).should == true
616
+ end
617
+ done
618
+ end
619
+ end
620
+ end
621
+
622
+ it "provides commandstats (INFO COMMANDSTATS)" do
623
+ connect do |redis|
624
+ redis.info_commandstats do |r|
625
+ r[:get][:calls].should be_a_kind_of(Integer)
626
+ r[:get][:usec].should be_a_kind_of(Integer)
627
+ r[:get][:usec_per_call].should be_a_kind_of(Float)
628
+ done
629
+ end
630
+ end
631
+ end
632
+
633
+ it "flushes the database (FLUSHDB)" do
634
+ connect do |redis|
635
+ redis.set('key1', 'keyone')
636
+ redis.set('key2', 'keytwo')
637
+ redis.keys('*') { |r| r.sort.should == ['key1', 'key2'].sort }
638
+ redis.flushdb
639
+ redis.keys('*') { |r| r.should == []; done }
640
+ end
641
+ end
642
+
643
+ it "SELECTs database" do
644
+ connect do |redis|
645
+ redis.set("foo", "bar") do |set_response|
646
+ redis.select("10") do |select_response|
647
+ redis.get("foo") do |get_response|
648
+ get_response.should == nil; done
649
+ end
650
+ end
651
+ end
652
+ end
653
+ end
654
+
655
+ it "SELECTs database without a callback" do
656
+ connect do |redis|
657
+ redis.select("9")
658
+ redis.incr("foo") do |response|
659
+ response.should == 1
660
+ done
661
+ end
662
+ end
663
+ end
664
+
665
+ it "provides the last save time (LASTSAVE)" do
666
+ connect do |redis|
667
+ redis.lastsave do |savetime|
668
+ Time.at(savetime).class.should == Time
669
+ Time.at(savetime).should <= Time.now
670
+ done
671
+ end
672
+ end
673
+ end
674
+
675
+ it "can MGET keys" do
676
+ connect do |redis|
677
+ redis.set('foo', 1000)
678
+ redis.set('bar', 2000)
679
+ redis.mget('foo', 'bar') { |r| r.should == ['1000', '2000'] }
680
+ redis.mget('foo', 'bar', 'baz') { |r| r.should == ['1000', '2000', nil] }
681
+ redis.ping { done }
682
+ end
683
+ end
684
+
685
+ it "can MSET values" do
686
+ connect do |redis|
687
+ redis.mset "key1", "value1", "key2", "value2"
688
+ redis.get('key1') { |r| r.should == "value1" }
689
+ redis.get('key2') { |r| r.should == "value2"; done }
690
+ end
691
+ end
692
+
693
+ it "can MSETNX values" do
694
+ connect do |redis|
695
+ redis.msetnx "keynx1", "valuenx1", "keynx2", "valuenx2"
696
+ redis.mget('keynx1', 'keynx2') { |r| r.should == ["valuenx1", "valuenx2"] }
697
+
698
+ redis.set("keynx1", "value1")
699
+ redis.set("keynx2", "value2")
700
+ redis.msetnx "keynx1", "valuenx1", "keynx2", "valuenx2"
701
+ redis.mget('keynx1', 'keynx2') { |r| r.should == ["value1", "value2"]; done }
702
+ end
703
+ end
704
+
705
+ it "can BGSAVE" do
706
+ connect do |redis|
707
+ redis.bgsave do |r|
708
+ ['OK', 'Background saving started'].include?(r).should == true
709
+ done
710
+ end
711
+ end
712
+ end
713
+
714
+ it "can ECHO" do
715
+ connect do |redis|
716
+ redis.echo("message in a bottle\n") { |r| r.should == "message in a bottle\n"; done }
717
+ end
718
+ end
719
+
720
+ it "runs MULTI without a block" do
721
+ connect do |redis|
722
+ redis.multi
723
+ redis.get("key1") { |r| r.should == "QUEUED" }
724
+ redis.discard { done }
725
+ end
726
+ end
727
+
728
+ it "runs MULTI/EXEC" do
729
+ connect do |redis|
730
+ redis.multi
731
+ redis.set "key1", "value1"
732
+ redis.exec
733
+
734
+ redis.get("key1") { |r| r.should == "value1" }
735
+
736
+ begin
737
+ redis.multi
738
+ redis.set "key2", "value2"
739
+ raise "Some error"
740
+ redis.set "key3", "value3"
741
+ redis.exec
742
+ rescue
743
+ redis.discard
744
+ end
745
+
746
+ redis.get("key2") { |r| r.should == nil }
747
+ redis.get("key3") { |r| r.should == nil; done}
748
+ end
749
+ end
750
+
751
+ it "sets and get hash values" do
752
+ connect do |redis|
753
+ redis.hset("rush", "signals", "1982") { |r| r.should == 1 }
754
+ redis.hexists("rush", "signals") { |r| r.should == 1 }
755
+ redis.hget("rush", "signals") { |r| r.should == "1982"; done }
756
+ end
757
+ end
758
+
759
+ it "deletes hash values" do
760
+ connect do |redis|
761
+ redis.hset("rush", "YYZ", "1981")
762
+ redis.hdel("rush", "YYZ") { |r| r.should == 1 }
763
+ redis.hexists("rush", "YYZ") { |r| r.should == 0; done }
764
+ end
765
+ end
766
+ end
767
+
768
+ describe EventMachine::Hiredis, "with hash values" do
769
+ def set(&blk)
770
+ connect do |redis|
771
+ redis.hset("rush", "permanent waves", "1980")
772
+ redis.hset("rush", "moving pictures", "1981")
773
+ redis.hset("rush", "signals", "1982")
774
+ blk.call(redis)
775
+ end
776
+ end
777
+
778
+ it "gets the length of the hash" do
779
+ set do |redis|
780
+ redis.hlen("rush") { |r| r.should == 3 }
781
+ redis.hlen("yyz") { |r| r.should == 0; done }
782
+ end
783
+ end
784
+
785
+ it "gets the keys and values of the hash" do
786
+ set do |redis|
787
+ redis.hkeys("rush") { |r| r.should == ["permanent waves", "moving pictures", "signals"] }
788
+ redis.hvals("rush") { |r| r.should == %w[1980 1981 1982] }
789
+ redis.hvals("yyz") { |r| r.should == []; done }
790
+ end
791
+ end
792
+
793
+ it "returns all hash values" do
794
+ set do |redis|
795
+ redis.hgetall("rush") do |r|
796
+ r.should == [
797
+ "permanent waves", "1980",
798
+ "moving pictures", "1981",
799
+ "signals" , "1982"
800
+ ]
801
+ end
802
+ redis.hgetall("yyz") { |r| r.should == []; done }
803
+ end
804
+ end
805
+ end
806
+
807
+ describe EventMachine::Hiredis, "with nested multi-bulk response" do
808
+ def set(&blk)
809
+ connect do |redis|
810
+ redis.set 'user:one:id', 'id-one'
811
+ redis.set 'user:two:id', 'id-two'
812
+ redis.sadd "user:one:interests", "first-interest"
813
+ redis.sadd "user:one:interests", "second-interest"
814
+ redis.sadd "user:two:interests", "third-interest"
815
+ blk.call(redis)
816
+ end
817
+ end
818
+
819
+ it "returns array of arrays" do
820
+ set do |redis|
821
+ redis.multi
822
+ redis.smembers "user:one:interests"
823
+ redis.smembers "user:two:interests"
824
+ redis.exec do |interests_one, interests_two|
825
+ interests_one.sort.should == ["first-interest", "second-interest"]
826
+ interests_two.should == ['third-interest']
827
+ end
828
+ redis.mget("user:one:id", "user:two:id") do |user_ids|
829
+ user_ids.should == ['id-one', 'id-two']
830
+ done
831
+ end
832
+ end
833
+ end
834
+ end
835
+
836
+ describe EventMachine::Hiredis, "monitor" do
837
+ it "returns monitored commands" do
838
+ connect do |redis|
839
+ # 1. Create 2nd connection to send traffic to monitor
840
+ redis2 = EventMachine::Hiredis.connect("redis://localhost:6379/")
841
+ redis2.callback {
842
+ # 2. Monitor after command has connected
843
+ redis.monitor do |reply|
844
+ reply.should == "OK"
845
+
846
+ # 3. Command which should show up in monitor output
847
+ redis2.get('foo')
848
+ end
849
+ }
850
+
851
+ redis.on(:monitor) do |line|
852
+ line.should =~ /foo/
853
+ done
854
+ end
855
+ end
856
+ end
857
+ end
858
+
859
+ describe EventMachine::Hiredis, "sorting" do
860
+ context "with some simple sorting data" do
861
+ def set(&blk)
862
+ connect do |redis|
863
+ redis.set('dog_1', 'louie')
864
+ redis.rpush 'Dogs', 1
865
+ redis.set('dog_2', 'lucy')
866
+ redis.rpush 'Dogs', 2
867
+ redis.set('dog_3', 'max')
868
+ redis.rpush 'Dogs', 3
869
+ redis.set('dog_4', 'taj')
870
+ redis.rpush 'Dogs', 4
871
+ blk.call(redis)
872
+ end
873
+ end
874
+
875
+ it "sorts with a limit" do
876
+ set do |redis|
877
+ redis.sort('Dogs', "GET", 'dog_*', "LIMIT", "0", "1") do |r|
878
+ r.should == ['louie']
879
+ done
880
+ end
881
+ end
882
+ end
883
+
884
+ it "sorts with a limit and order" do
885
+ set do |redis|
886
+ redis.sort('Dogs', "GET", 'dog_*', "LIMIT", "0", "1", "desc", "alpha") do |r|
887
+ r.should == ['taj']
888
+ done
889
+ end
890
+ end
891
+ end
892
+ end
893
+
894
+ context "with more complex sorting data" do
895
+ def set(&blk)
896
+ connect do |redis|
897
+ redis.set('dog:1:name', 'louie')
898
+ redis.set('dog:1:breed', 'mutt')
899
+ redis.rpush 'dogs', 1
900
+ redis.set('dog:2:name', 'lucy')
901
+ redis.set('dog:2:breed', 'poodle')
902
+ redis.rpush 'dogs', 2
903
+ redis.set('dog:3:name', 'max')
904
+ redis.set('dog:3:breed', 'hound')
905
+ redis.rpush 'dogs', 3
906
+ redis.set('dog:4:name', 'taj')
907
+ redis.set('dog:4:breed', 'terrier')
908
+ redis.rpush 'dogs', 4
909
+ blk.call(redis)
910
+ end
911
+ end
912
+
913
+ it "handles multiple GETs" do
914
+ set do |redis|
915
+ redis.sort('dogs', 'GET', 'dog:*:name', 'GET', 'dog:*:breed', 'LIMIT', '0', '1') do |r|
916
+ r.should == ['louie', 'mutt']
917
+ done
918
+ end
919
+ end
920
+ end
921
+
922
+ it "handles multiple GETs with an order" do
923
+ set do |redis|
924
+ redis.sort('dogs', 'GET', 'dog:*:name', 'GET', 'dog:*:breed', 'LIMIT', '0', '1', 'desc', 'alpha') do |r|
925
+ r.should == ['taj', 'terrier']
926
+ done
927
+ end
928
+ end
929
+ end
930
+ end
931
+ end