gilmour-em-hiredis 0.3.0

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,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe EventMachine::Hiredis, "connecting" do
4
+ let(:replies) do
5
+ # shove db number into PING reply since redis has no way
6
+ # of exposing the currently selected DB
7
+ replies = {
8
+ :select => lambda { |db| $db = db; "+OK" },
9
+ :ping => lambda { "+PONG #{$db}" },
10
+ :auth => lambda { |password| $auth = password; "+OK" },
11
+ :get => lambda { |key| $auth == "secret" ? "$3\r\nbar" : "$-1" },
12
+ }
13
+ end
14
+
15
+ def connect_to_mock(url, &blk)
16
+ redis_mock(replies) do
17
+ connect(1, url, &blk)
18
+ end
19
+ end
20
+
21
+ it "doesn't call select by default" do
22
+ connect_to_mock("redis://localhost:6380/") do |redis|
23
+ redis.ping do |response|
24
+ response.should == "PONG "
25
+ done
26
+ end
27
+ end
28
+ end
29
+
30
+ it "selects the right db" do
31
+ connect_to_mock("redis://localhost:6380/9") do |redis|
32
+ redis.ping do |response|
33
+ response.should == "PONG 9"
34
+ done
35
+ end
36
+ end
37
+ end
38
+
39
+ it "authenticates with a password" do
40
+ connect_to_mock("redis://:secret@localhost:6380/9") do |redis|
41
+ redis.get("foo") do |response|
42
+ response.should == "bar"
43
+ done
44
+ end
45
+ end
46
+ end
47
+
48
+ it "rejects a bad password" do
49
+ connect_to_mock("redis://:failboat@localhost:6380/9") do |redis|
50
+ redis.get("foo") do |response|
51
+ response.should be_nil
52
+ done
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'support/inprocess_redis_mock'
3
+
4
+ def connect_mock(timeout = 10, url = "redis://localhost:6381", server = nil, &blk)
5
+ em(timeout) do
6
+ IRedisMock.start
7
+ redis = EventMachine::Hiredis.connect(url)
8
+ blk.call(redis)
9
+ IRedisMock.stop
10
+ end
11
+ end
12
+
13
+ describe EM::Hiredis::BaseClient do
14
+ it "should ping after activity timeout reached" do
15
+ connect_mock do |redis|
16
+ redis.configure_inactivity_check(2, 1)
17
+ EM.add_timer(4) {
18
+ IRedisMock.received.should include("ping")
19
+ done
20
+ }
21
+ end
22
+ end
23
+
24
+ it "should not ping before activity timeout reached" do
25
+ connect_mock do |redis|
26
+ redis.configure_inactivity_check(3, 1)
27
+ EM.add_timer(2) {
28
+ IRedisMock.received.should_not include("ping")
29
+ done
30
+ }
31
+ end
32
+ end
33
+
34
+ it "should ping after timeout reached even though command has been sent (no response)" do
35
+ connect_mock do |redis|
36
+ redis.configure_inactivity_check(2, 1)
37
+ IRedisMock.pause # no responses from now on
38
+
39
+ EM.add_timer(1.5) {
40
+ redis.get "test"
41
+ }
42
+
43
+ EM.add_timer(4) {
44
+ IRedisMock.received.should include("ping")
45
+ done
46
+ }
47
+ end
48
+ end
49
+
50
+ it "should trigger a reconnect when there's no response to ping" do
51
+ connect_mock do |redis|
52
+ redis.configure_inactivity_check(2, 1)
53
+ IRedisMock.pause # no responses from now on
54
+
55
+ EM.add_timer(1.5) {
56
+ redis.get "test"
57
+ }
58
+
59
+ EM.add_timer(5) {
60
+ IRedisMock.received.should include("disconnect")
61
+ done
62
+ }
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,527 @@
1
+ require 'spec_helper'
2
+
3
+ describe EventMachine::Hiredis, "connected to an empty db" do
4
+ it "sets a string value" do
5
+ connect do |redis|
6
+ redis.set("foo", "bar") do |r|
7
+ r.should == "OK"
8
+ done
9
+ end
10
+ end
11
+ end
12
+
13
+ it "increments the value of a string" do
14
+ connect do |redis|
15
+ redis.incr "foo" do |r|
16
+ r.should == 1
17
+ redis.incr "foo" do |r|
18
+ r.should == 2
19
+ done
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ it "increments the value of a string by an amount" do
26
+ connect do |redis|
27
+ redis.incrby "foo", 10 do |r|
28
+ r.should == 10
29
+ done
30
+ end
31
+ end
32
+ end
33
+
34
+ it "decrements the value of a string" do
35
+ connect do |redis|
36
+ redis.incr "foo" do |r|
37
+ r.should == 1
38
+ redis.decr "foo" do |r|
39
+ r.should == 0
40
+ done
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ it "decrement the value of a string by an amount" do
47
+ connect do |redis|
48
+ redis.incrby "foo", 20 do |r|
49
+ r.should == 20
50
+ redis.decrby "foo", 10 do |r|
51
+ r.should == 10
52
+ done
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ it "can 'lpush' to a nonexistent list" do
59
+ connect do |redis|
60
+ redis.lpush("foo", "bar") do |r|
61
+ r.should == 1
62
+ done
63
+ end
64
+ end
65
+ end
66
+
67
+ it "can 'rpush' to a nonexistent list" do
68
+ connect do |redis|
69
+ redis.rpush("foo", "bar") do |r|
70
+ r.should == 1
71
+ done
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+ it "gets the size of the database" do
78
+ connect do |redis|
79
+ redis.dbsize do |r|
80
+ r.should == 0
81
+ done
82
+ end
83
+ end
84
+ end
85
+
86
+ it "adds a member to a nonexistent set" do
87
+ connect do |redis|
88
+ redis.sadd("set_foo", "bar") do |r|
89
+ r.should == 1
90
+ done
91
+ end
92
+ end
93
+ end
94
+
95
+ it "reads info about the db" do
96
+ connect do |redis|
97
+ redis.info do |info|
98
+ info[:redis_version].should_not be_nil
99
+ done
100
+ end
101
+ end
102
+ end
103
+
104
+ it "can save the db" do
105
+ connect do |redis|
106
+ redis.save do |r|
107
+ r.should == "OK"
108
+ done
109
+ end
110
+ end
111
+ end
112
+
113
+ it "can save the db in the background" do
114
+ connect do |redis|
115
+ redis.bgsave do |r|
116
+ r.should == "Background saving started"
117
+ done
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ describe EventMachine::Hiredis, "connected to a db containing some simple string-valued keys" do
124
+ def set(&blk)
125
+ connect do |redis|
126
+ redis.flushdb
127
+ redis.set "a", "b"
128
+ redis.set "x", "y"
129
+ blk.call(redis)
130
+ end
131
+ end
132
+
133
+ it "fetches the values of multiple keys" do
134
+ set do |redis|
135
+ redis.mget "a", "x" do |r|
136
+ r.should == ["b", "y"]
137
+ done
138
+ end
139
+ end
140
+ end
141
+
142
+ it "fetches all the keys" do
143
+ set do |redis|
144
+ redis.keys "*" do |r|
145
+ r.sort.should == ["a", "x"]
146
+ done
147
+ end
148
+ end
149
+ end
150
+
151
+ it "sets a value if a key doesn't exist" do
152
+ set do |redis|
153
+ redis.setnx "a", "foo" do |r|
154
+ r.should == 0
155
+ redis.setnx "zzz", "foo" do |r|
156
+ r.should == 1
157
+ done
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ it "tests for the existence of a key" do
164
+ set do |redis|
165
+ redis.exists "a" do |r|
166
+ r.should == 1
167
+ redis.exists "zzz" do |r|
168
+ r.should == 0
169
+ done
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ it "deletes a key" do
176
+ set do |redis|
177
+ redis.del "a" do |r|
178
+ r.should == 1
179
+ redis.exists "a" do |r|
180
+ r.should == 0
181
+ redis.del "a" do |r|
182
+ r.should == 0
183
+ done
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ it "detects the type of a key, existing or not" do
191
+ set do |redis|
192
+ redis.type "a" do |r|
193
+ r.should == "string"
194
+ redis.type "zzz" do |r|
195
+ r.should == "none"
196
+ done
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ it "renames a key" do
203
+ set do |redis|
204
+ redis.rename "a", "x" do |r|
205
+ redis.get "x" do |r|
206
+ r.should == "b"
207
+ done
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ it "renames a key unless it exists" do
214
+ set do |redis|
215
+ redis.renamenx "a", "x" do |r|
216
+ r.should == 0
217
+ redis.renamenx "a", "zzz" do |r|
218
+ r.should == 1
219
+ redis.get "zzz" do |r|
220
+ r.should == "b"
221
+ done
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ describe EventMachine::Hiredis, "connected to a db containing a list" do
230
+ def set(&blk)
231
+ connect do |redis|
232
+ redis.flushdb
233
+ redis.lpush "foo", "c"
234
+ redis.lpush "foo", "b"
235
+ redis.lpush "foo", "a"
236
+ blk.call(redis)
237
+ end
238
+ end
239
+
240
+ it "sets a list member and 'lindex' to retrieve it" do
241
+ set do |redis|
242
+ redis.lset("foo", 1, "bar") do |r|
243
+ redis.lindex("foo", 1) do |r|
244
+ r.should == "bar"
245
+ done
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ it "pushes onto tail of the list" do
252
+ set do |redis|
253
+ redis.rpush "foo", "d" do |r|
254
+ r.should == 4
255
+ redis.rpop "foo" do |r|
256
+ r.should == "d"
257
+ done
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ it "pushes onto the head of the list" do
264
+ set do |redis|
265
+ redis.lpush "foo", "d" do |r|
266
+ r.should == 4
267
+ redis.lpop "foo" do |r|
268
+ r.should == "d"
269
+ done
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ it "pops off the tail of the list" do
276
+ set do |redis|
277
+ redis.rpop("foo") do |r|
278
+ r.should == "c"
279
+ done
280
+ end
281
+ end
282
+ end
283
+
284
+ it "pops off the tail of the list" do
285
+ set do |redis|
286
+ redis.lpop("foo") do |r|
287
+ r.should == "a"
288
+ done
289
+ end
290
+ end
291
+ end
292
+
293
+ it "gets a range of values from a list" do
294
+ set do |redis|
295
+ redis.lrange("foo", 0, 1) do |r|
296
+ r.should == ["a", "b"]
297
+ done
298
+ end
299
+ end
300
+ end
301
+
302
+ it "trims a list" do
303
+ set do |redis|
304
+ redis.ltrim("foo", 0, 1) do |r|
305
+ r.should == "OK"
306
+ redis.llen("foo") do |r|
307
+ r.should == 2
308
+ done
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ it "removes a list element" do
315
+ set do |redis|
316
+ redis.lrem("foo", 0, "a") do |r|
317
+ r.should == 1
318
+ redis.llen("foo") do |r|
319
+ r.should == 2
320
+ done
321
+ end
322
+ end
323
+ end
324
+ end
325
+
326
+ it "detects the type of a list" do
327
+ set do |redis|
328
+ redis.type "foo" do |r|
329
+ r.should == "list"
330
+ done
331
+ end
332
+ end
333
+ end
334
+ end
335
+
336
+ describe EventMachine::Hiredis, "connected to a db containing two sets" do
337
+ def set(&blk)
338
+ connect do |redis|
339
+ redis.flushdb
340
+ redis.sadd "foo", "a"
341
+ redis.sadd "foo", "b"
342
+ redis.sadd "foo", "c"
343
+ redis.sadd "bar", "c"
344
+ redis.sadd "bar", "d"
345
+ redis.sadd "bar", "e"
346
+ blk.call(redis)
347
+ end
348
+ end
349
+
350
+ it "finds a set's cardinality" do
351
+ set do |redis|
352
+ redis.scard("foo") do |r|
353
+ r.should == 3
354
+ done
355
+ end
356
+ end
357
+ end
358
+
359
+ it "adds a new member to a set unless it is a duplicate" do
360
+ set do |redis|
361
+ redis.sadd("foo", "d") do |r|
362
+ r.should == 1 # success
363
+ redis.sadd("foo", "a") do |r|
364
+ r.should == 0 # failure
365
+ redis.scard("foo") do |r|
366
+ r.should == 4
367
+ done
368
+ end
369
+ end
370
+ end
371
+ end
372
+ end
373
+
374
+ it "removes a set member if it exists" do
375
+ set do |redis|
376
+ redis.srem("foo", "a") do |r|
377
+ r.should == 1
378
+ redis.srem("foo", "z") do |r|
379
+ r.should == 0
380
+ redis.scard("foo") do |r|
381
+ r.should == 2
382
+ done
383
+ end
384
+ end
385
+ end
386
+ end
387
+ end
388
+
389
+ it "retrieves a set's members" do
390
+ set do |redis|
391
+ redis.smembers("foo") do |r|
392
+ r.sort.should == ["a", "b", "c"]
393
+ done
394
+ end
395
+ end
396
+ end
397
+
398
+ it "detects set membership" do
399
+ set do |redis|
400
+ redis.sismember("foo", "a") do |r|
401
+ r.should == 1
402
+ redis.sismember("foo", "z") do |r|
403
+ r.should == 0
404
+ done
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+ it "finds the sets' intersection" do
411
+ set do |redis|
412
+ redis.sinter("foo", "bar") do |r|
413
+ r.should == ["c"]
414
+ done
415
+ end
416
+ end
417
+ end
418
+
419
+ it "finds and stores the sets' intersection" do
420
+ set do |redis|
421
+ redis.sinterstore("baz", "foo", "bar") do |r|
422
+ r.should == 1
423
+ redis.smembers("baz") do |r|
424
+ r.should == ["c"]
425
+ done
426
+ end
427
+ end
428
+ end
429
+ end
430
+
431
+ it "finds the sets' union" do
432
+ set do |redis|
433
+ redis.sunion("foo", "bar") do |r|
434
+ r.sort.should == ["a","b","c","d","e"]
435
+ done
436
+ end
437
+ end
438
+ end
439
+
440
+ it "finds and stores the sets' union" do
441
+ set do |redis|
442
+ redis.sunionstore("baz", "foo", "bar") do |r|
443
+ r.should == 5
444
+ redis.smembers("baz") do |r|
445
+ r.sort.should == ["a","b","c","d","e"]
446
+ done
447
+ end
448
+ end
449
+ end
450
+ end
451
+
452
+ it "detects the type of a set" do
453
+ set do |redis|
454
+ redis.type "foo" do |r|
455
+ r.should == "set"
456
+ done
457
+ end
458
+ end
459
+ end
460
+ end
461
+
462
+ describe EventMachine::Hiredis, "connected to a db containing three linked lists" do
463
+ def set(&blk)
464
+ connect do |redis|
465
+ redis.flushdb
466
+ redis.rpush "foo", "a"
467
+ redis.rpush "foo", "b"
468
+ redis.set "a_sort", "2"
469
+ redis.set "b_sort", "1"
470
+ redis.set "a_data", "foo"
471
+ redis.set "b_data", "bar"
472
+ blk.call(redis)
473
+ end
474
+ end
475
+
476
+ it "collates a sorted set of data" do
477
+ set do |redis|
478
+ redis.sort("foo", "BY", "*_sort", "GET", "*_data") do |r|
479
+ r.should == ["bar", "foo"]
480
+ done
481
+ end
482
+ end
483
+ end
484
+
485
+ it "gets keys selectively" do
486
+ set do |redis|
487
+ redis.keys "a_*" do |r|
488
+ r.sort.should == ["a_sort", "a_data"].sort
489
+ done
490
+ end
491
+ end
492
+ end
493
+ end
494
+
495
+ describe EventMachine::Hiredis, "when reconnecting" do
496
+ it "select previously selected dataset" do
497
+ connect(3) do |redis|
498
+ #simulate disconnect
499
+ redis.set('foo', 'a') { redis.close_connection_after_writing }
500
+
501
+ EventMachine.add_timer(2) do
502
+ redis.get('foo') do |r|
503
+ r.should == 'a'
504
+ redis.get('non_existing') do |r|
505
+ r.should == nil
506
+ done
507
+ end
508
+ end
509
+ end
510
+ end
511
+ end
512
+ end
513
+
514
+ describe EventMachine::Hiredis, "when closing_connection" do
515
+ it "should fail deferred commands" do
516
+ errored = false
517
+ connect do |redis|
518
+ op = redis.blpop 'empty_list'
519
+ op.callback { fail }
520
+ op.errback { EM.stop }
521
+
522
+ redis.close_connection
523
+
524
+ EM.add_timer(1) { fail }
525
+ end
526
+ end
527
+ end