lunar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/examples/ohm.rb +23 -0
  8. data/lib/lunar.rb +12 -0
  9. data/lib/lunar/doc.rb +13 -0
  10. data/lib/lunar/index.rb +70 -0
  11. data/lib/lunar/scoring.rb +11 -0
  12. data/test/helper.rb +13 -0
  13. data/test/test_lunar.rb +4 -0
  14. data/test/test_lunar_document.rb +20 -0
  15. data/test/test_lunar_index.rb +174 -0
  16. data/test/test_lunar_scoring.rb +26 -0
  17. data/vendor/nest/nest.rb +7 -0
  18. data/vendor/redis/.gitignore +9 -0
  19. data/vendor/redis/LICENSE +20 -0
  20. data/vendor/redis/README.markdown +120 -0
  21. data/vendor/redis/Rakefile +75 -0
  22. data/vendor/redis/benchmarking/logging.rb +62 -0
  23. data/vendor/redis/benchmarking/pipeline.rb +44 -0
  24. data/vendor/redis/benchmarking/speed.rb +21 -0
  25. data/vendor/redis/benchmarking/suite.rb +24 -0
  26. data/vendor/redis/benchmarking/worker.rb +71 -0
  27. data/vendor/redis/bin/distredis +33 -0
  28. data/vendor/redis/examples/basic.rb +15 -0
  29. data/vendor/redis/examples/dist_redis.rb +43 -0
  30. data/vendor/redis/examples/incr-decr.rb +17 -0
  31. data/vendor/redis/examples/list.rb +26 -0
  32. data/vendor/redis/examples/pubsub.rb +25 -0
  33. data/vendor/redis/examples/sets.rb +36 -0
  34. data/vendor/redis/lib/edis.rb +3 -0
  35. data/vendor/redis/lib/redis.rb +496 -0
  36. data/vendor/redis/lib/redis/client.rb +265 -0
  37. data/vendor/redis/lib/redis/dist_redis.rb +118 -0
  38. data/vendor/redis/lib/redis/distributed.rb +460 -0
  39. data/vendor/redis/lib/redis/hash_ring.rb +131 -0
  40. data/vendor/redis/lib/redis/pipeline.rb +13 -0
  41. data/vendor/redis/lib/redis/raketasks.rb +1 -0
  42. data/vendor/redis/lib/redis/subscribe.rb +79 -0
  43. data/vendor/redis/profile.rb +22 -0
  44. data/vendor/redis/tasks/redis.tasks.rb +140 -0
  45. data/vendor/redis/test/db/.gitignore +1 -0
  46. data/vendor/redis/test/distributed_test.rb +1131 -0
  47. data/vendor/redis/test/redis_test.rb +1134 -0
  48. data/vendor/redis/test/test.conf +8 -0
  49. data/vendor/redis/test/test_helper.rb +113 -0
  50. metadata +127 -0
@@ -0,0 +1,1134 @@
1
+ require File.join(File.dirname(__FILE__), "test_helper")
2
+
3
+ class RedisTest < Test::Unit::TestCase
4
+
5
+ PORT = 6379
6
+ OPTIONS = {:port => PORT, :db => 15, :timeout => 3}.freeze
7
+
8
+ setup do
9
+ @r = Redis.new(OPTIONS)
10
+ ensure_redis_running(@r)
11
+ @r.flushdb
12
+ end
13
+
14
+ context "initialize with URL" do
15
+ test "defaults to 127.0.0.1:6379" do
16
+ redis = Redis.connect
17
+
18
+ assert_equal "127.0.0.1", redis.client.host
19
+ assert_equal 6379, redis.client.port
20
+ assert_equal 0, redis.client.db
21
+ assert_nil redis.client.password
22
+ end
23
+
24
+ test "takes a url" do
25
+ redis = Redis.connect :url => "redis://:secr3t@foo.com:999/2"
26
+
27
+ assert_equal "foo.com", redis.client.host
28
+ assert_equal 999, redis.client.port
29
+ assert_equal 2, redis.client.db
30
+ assert_equal "secr3t", redis.client.password
31
+ end
32
+
33
+ test "uses REDIS_URL over default if available" do
34
+ ENV["REDIS_URL"] = "redis://:secr3t@foo.com:999/2"
35
+
36
+ redis = Redis.connect
37
+
38
+ assert_equal "foo.com", redis.client.host
39
+ assert_equal 999, redis.client.port
40
+ assert_equal 2, redis.client.db
41
+ assert_equal "secr3t", redis.client.password
42
+
43
+ ENV.delete("REDIS_URL")
44
+ end
45
+ end
46
+
47
+ context "Internals" do
48
+ setup do
49
+ @log = StringIO.new
50
+ @r = Redis.new(OPTIONS.merge(:logger => ::Logger.new(@log)))
51
+ end
52
+
53
+ test "Logger" do
54
+ @r.ping
55
+
56
+ assert_match(/Redis >> PING/, @log.string)
57
+ assert_match(/Redis >> 0.\d+ms/, @log.string)
58
+ end
59
+
60
+ test "Logger with pipelining" do
61
+ @r.pipelined do
62
+ @r.set "foo", "bar"
63
+ @r.get "foo"
64
+ end
65
+
66
+ assert @log.string["SET foo bar"]
67
+ assert @log.string["GET foo"]
68
+ end
69
+
70
+ test "Timeout" do
71
+ assert_nothing_raised do
72
+ Redis.new(OPTIONS.merge(:timeout => 0))
73
+ end
74
+ end
75
+
76
+ test "Recovers from failed commands" do
77
+ # See http://github.com/ezmobius/redis-rb/issues#issue/28
78
+
79
+ assert_raises(ArgumentError) do
80
+ @r.srem "foo"
81
+ end
82
+
83
+ assert_nothing_raised do
84
+ @r.info
85
+ end
86
+ end
87
+ end
88
+
89
+ context "Connection handling" do
90
+ test "AUTH" do
91
+ redis = Redis.new(:port => PORT, :password => "secret").instance_variable_get("@client")
92
+
93
+ def redis.call(*attrs)
94
+ raise unless attrs == [:auth, "secret"]
95
+ end
96
+
97
+ assert_nothing_raised do
98
+ redis.send(:connect)
99
+ end
100
+ end
101
+
102
+ test "PING" do
103
+ assert_equal "PONG", @r.ping
104
+ end
105
+
106
+ test "SELECT" do
107
+ @r.set "foo", "bar"
108
+
109
+ @r.select 14
110
+ assert_equal nil, @r.get("foo")
111
+
112
+ @r.client.disconnect
113
+
114
+ assert_equal nil, @r.get("foo")
115
+ end
116
+ end
117
+
118
+ context "Commands operating on all the kind of values" do
119
+ test "EXISTS" do
120
+ assert_equal false, @r.exists("foo")
121
+
122
+ @r.set("foo", "s1")
123
+
124
+ assert_equal true, @r.exists("foo")
125
+ end
126
+
127
+ test "DEL" do
128
+ @r.set "foo", "s1"
129
+ @r.set "bar", "s2"
130
+ @r.set "baz", "s3"
131
+
132
+ assert_equal ["bar", "baz", "foo"], @r.keys("*").sort
133
+
134
+ @r.del "foo"
135
+
136
+ assert_equal ["bar", "baz"], @r.keys("*").sort
137
+
138
+ @r.del "bar", "baz"
139
+
140
+ assert_equal [], @r.keys("*").sort
141
+ end
142
+
143
+ test "TYPE" do
144
+ assert_equal "none", @r.type("foo")
145
+
146
+ @r.set("foo", "s1")
147
+
148
+ assert_equal "string", @r.type("foo")
149
+ end
150
+
151
+ test "KEYS" do
152
+ @r.set("f", "s1")
153
+ @r.set("fo", "s2")
154
+ @r.set("foo", "s3")
155
+
156
+ assert_equal ["f","fo", "foo"], @r.keys("f*").sort
157
+ end
158
+
159
+ test "RANDOMKEY" do
160
+ assert @r.randomkey.to_s.empty?
161
+
162
+ @r.set("foo", "s1")
163
+
164
+ assert_equal "foo", @r.randomkey
165
+
166
+ @r.set("bar", "s2")
167
+
168
+ 4.times do
169
+ assert ["foo", "bar"].include?(@r.randomkey)
170
+ end
171
+ end
172
+
173
+ test "RENAME" do
174
+ @r.set("foo", "s1")
175
+ @r.rename "foo", "bar"
176
+
177
+ assert_equal "s1", @r.get("bar")
178
+ assert_equal nil, @r.get("foo")
179
+ end
180
+
181
+ test "RENAMENX" do
182
+ @r.set("foo", "s1")
183
+ @r.set("bar", "s2")
184
+
185
+ assert_equal false, @r.renamenx("foo", "bar")
186
+
187
+ assert_equal "s1", @r.get("foo")
188
+ assert_equal "s2", @r.get("bar")
189
+ end
190
+
191
+ test "DBSIZE" do
192
+ assert_equal 0, @r.dbsize
193
+
194
+ @r.set("foo", "s1")
195
+
196
+ assert_equal 1, @r.dbsize
197
+ end
198
+
199
+ test "EXPIRE" do
200
+ @r.set("foo", "s1")
201
+ @r.expire("foo", 1)
202
+
203
+ assert_equal "s1", @r.get("foo")
204
+
205
+ sleep 2
206
+
207
+ assert_equal nil, @r.get("foo")
208
+ end
209
+
210
+ test "EXPIREAT" do
211
+ @r.set("foo", "s1")
212
+ @r.expireat("foo", Time.now.to_i + 1)
213
+
214
+ assert_equal "s1", @r.get("foo")
215
+
216
+ sleep 2
217
+
218
+ assert_equal nil, @r.get("foo")
219
+ end
220
+
221
+ test "TTL" do
222
+ @r.set("foo", "s1")
223
+ @r.expire("foo", 1)
224
+
225
+ assert_equal 1, @r.ttl("foo")
226
+ end
227
+
228
+ test "FLUSHDB" do
229
+ @r.set("foo", "s1")
230
+ @r.set("bar", "s2")
231
+
232
+ assert_equal 2, @r.dbsize
233
+
234
+ @r.flushdb
235
+
236
+ assert_equal 0, @r.dbsize
237
+ end
238
+ end
239
+
240
+ context "Commands operating on string values" do
241
+ test "SET and GET" do
242
+ @r.set("foo", "s1")
243
+
244
+ assert_equal "s1", @r.get("foo")
245
+ end
246
+
247
+ test "SET and GET with brackets" do
248
+ @r["foo"] = "s1"
249
+
250
+ assert_equal "s1", @r["foo"]
251
+ end
252
+
253
+ test "SET and GET with newline characters" do
254
+ @r.set("foo", "1\n")
255
+
256
+ assert_equal "1\n", @r.get("foo")
257
+ end
258
+
259
+ test "SET and GET with ASCII characters" do
260
+ (0..255).each do |i|
261
+ str = "#{i.chr}---#{i.chr}"
262
+ @r.set("foo", str)
263
+
264
+ assert_equal str, @r.get("foo")
265
+ end
266
+ end
267
+
268
+ test "SETEX" do
269
+ @r.setex("foo", 1, "s1")
270
+
271
+ assert_equal "s1", @r.get("foo")
272
+
273
+ sleep 2
274
+
275
+ assert_equal nil, @r.get("foo")
276
+ end
277
+
278
+ test "GETSET" do
279
+ @r.set("foo", "bar")
280
+
281
+ assert_equal "bar", @r.getset("foo", "baz")
282
+ assert_equal "baz", @r.get("foo")
283
+ end
284
+
285
+ test "MGET" do
286
+ @r.set("foo", "s1")
287
+ @r.set("bar", "s2")
288
+
289
+ assert_equal ["s1", "s2"], @r.mget("foo", "bar")
290
+ assert_equal ["s1", "s2", nil], @r.mget("foo", "bar", "baz")
291
+ end
292
+
293
+ test "MGET mapped" do
294
+ @r.set("foo", "s1")
295
+ @r.set("bar", "s2")
296
+
297
+ assert_equal({"foo" => "s1", "bar" => "s2"}, @r.mapped_mget("foo", "bar"))
298
+ assert_equal({"foo" => "s1", "bar" => "s2"}, @r.mapped_mget("foo", "baz", "bar"))
299
+ end
300
+
301
+ test "SETNX" do
302
+ @r.set("foo", "s1")
303
+
304
+ assert_equal "s1", @r.get("foo")
305
+
306
+ @r.setnx("foo", "s2")
307
+
308
+ assert_equal "s1", @r.get("foo")
309
+ end
310
+
311
+ test "MSET" do
312
+ @r.mset(:foo, "s1", :bar, "s2")
313
+
314
+ assert_equal "s1", @r.get("foo")
315
+ assert_equal "s2", @r.get("bar")
316
+ end
317
+
318
+ test "MSET mapped" do
319
+ @r.mapped_mset(:foo => "s1", :bar => "s2")
320
+
321
+ assert_equal "s1", @r.get("foo")
322
+ assert_equal "s2", @r.get("bar")
323
+ end
324
+
325
+ test "MSETNX" do
326
+ @r.set("foo", "s1")
327
+ @r.msetnx(:foo, "s2", :bar, "s3")
328
+
329
+ assert_equal "s1", @r.get("foo")
330
+ assert_equal nil, @r.get("bar")
331
+ end
332
+
333
+ test "MSETNX mapped" do
334
+ @r.set("foo", "s1")
335
+ @r.mapped_msetnx(:foo => "s2", :bar => "s3")
336
+
337
+ assert_equal "s1", @r.get("foo")
338
+ assert_equal nil, @r.get("bar")
339
+ end
340
+
341
+ test "INCR" do
342
+ assert_equal 1, @r.incr("foo")
343
+ assert_equal 2, @r.incr("foo")
344
+ assert_equal 3, @r.incr("foo")
345
+ end
346
+
347
+ test "INCRBY" do
348
+ assert_equal 1, @r.incrby("foo", 1)
349
+ assert_equal 3, @r.incrby("foo", 2)
350
+ assert_equal 6, @r.incrby("foo", 3)
351
+ end
352
+
353
+ test "DECR" do
354
+ @r.set("foo", 3)
355
+
356
+ assert_equal 2, @r.decr("foo")
357
+ assert_equal 1, @r.decr("foo")
358
+ assert_equal 0, @r.decr("foo")
359
+ end
360
+
361
+ test "DECRBY" do
362
+ @r.set("foo", 6)
363
+
364
+ assert_equal 3, @r.decrby("foo", 3)
365
+ assert_equal 1, @r.decrby("foo", 2)
366
+ assert_equal 0, @r.decrby("foo", 1)
367
+ end
368
+ end
369
+
370
+ context "Commands operating on lists" do
371
+ test "RPUSH" do
372
+ @r.rpush "foo", "s1"
373
+ @r.rpush "foo", "s2"
374
+
375
+ assert_equal 2, @r.llen("foo")
376
+ assert_equal "s2", @r.rpop("foo")
377
+ end
378
+
379
+ test "LPUSH" do
380
+ @r.lpush "foo", "s1"
381
+ @r.lpush "foo", "s2"
382
+
383
+ assert_equal 2, @r.llen("foo")
384
+ assert_equal "s2", @r.lpop("foo")
385
+ end
386
+
387
+ test "LLEN" do
388
+ @r.rpush "foo", "s1"
389
+ @r.rpush "foo", "s2"
390
+
391
+ assert_equal 2, @r.llen("foo")
392
+ end
393
+
394
+ test "LRANGE" do
395
+ @r.rpush "foo", "s1"
396
+ @r.rpush "foo", "s2"
397
+ @r.rpush "foo", "s3"
398
+
399
+ assert_equal ["s2", "s3"], @r.lrange("foo", 1, -1)
400
+ assert_equal ["s1", "s2"], @r.lrange("foo", 0, 1)
401
+ end
402
+
403
+ test "LTRIM" do
404
+ @r.rpush "foo", "s1"
405
+ @r.rpush "foo", "s2"
406
+ @r.rpush "foo", "s3"
407
+
408
+ @r.ltrim "foo", 0, 1
409
+
410
+ assert_equal 2, @r.llen("foo")
411
+ assert_equal ["s1", "s2"], @r.lrange("foo", 0, -1)
412
+ end
413
+
414
+ test "LINDEX" do
415
+ @r.rpush "foo", "s1"
416
+ @r.rpush "foo", "s2"
417
+
418
+ assert_equal "s1", @r.lindex("foo", 0)
419
+ assert_equal "s2", @r.lindex("foo", 1)
420
+ end
421
+
422
+ test "LSET" do
423
+ @r.rpush "foo", "s1"
424
+ @r.rpush "foo", "s2"
425
+
426
+ assert_equal "s2", @r.lindex("foo", 1)
427
+ assert @r.lset("foo", 1, "s3")
428
+ assert_equal "s3", @r.lindex("foo", 1)
429
+
430
+ assert_raises RuntimeError do
431
+ @r.lset("foo", 4, "s3")
432
+ end
433
+ end
434
+
435
+ test "LREM" do
436
+ @r.rpush "foo", "s1"
437
+ @r.rpush "foo", "s2"
438
+
439
+ assert_equal 1, @r.lrem("foo", 1, "s1")
440
+ assert_equal ["s2"], @r.lrange("foo", 0, -1)
441
+ end
442
+
443
+ test "LPOP" do
444
+ @r.rpush "foo", "s1"
445
+ @r.rpush "foo", "s2"
446
+
447
+ assert_equal 2, @r.llen("foo")
448
+ assert_equal "s1", @r.lpop("foo")
449
+ assert_equal 1, @r.llen("foo")
450
+ end
451
+
452
+ test "RPOP" do
453
+ @r.rpush "foo", "s1"
454
+ @r.rpush "foo", "s2"
455
+
456
+ assert_equal 2, @r.llen("foo")
457
+ assert_equal "s2", @r.rpop("foo")
458
+ assert_equal 1, @r.llen("foo")
459
+ end
460
+
461
+ test "RPOPLPUSH" do
462
+ @r.rpush "foo", "s1"
463
+ @r.rpush "foo", "s2"
464
+
465
+ assert_equal "s2", @r.rpoplpush("foo", "bar")
466
+ assert_equal ["s2"], @r.lrange("bar", 0, -1)
467
+ assert_equal "s1", @r.rpoplpush("foo", "bar")
468
+ assert_equal ["s1", "s2"], @r.lrange("bar", 0, -1)
469
+ end
470
+ end
471
+
472
+ context "Blocking commands" do
473
+ test "BLPOP" do
474
+ @r.lpush("foo", "s1")
475
+ @r.lpush("foo", "s2")
476
+
477
+ thread = Thread.new do
478
+ redis = Redis.new(OPTIONS)
479
+ sleep 0.3
480
+ redis.lpush("foo", "s3")
481
+ end
482
+
483
+ assert_equal @r.blpop("foo", 0.1), ["foo", "s2"]
484
+ assert_equal @r.blpop("foo", 0.1), ["foo", "s1"]
485
+ assert_equal @r.blpop("foo", 0.4), ["foo", "s3"]
486
+
487
+ thread.join
488
+ end
489
+
490
+ test "BRPOP" do
491
+ @r.rpush("foo", "s1")
492
+ @r.rpush("foo", "s2")
493
+
494
+ t = Thread.new do
495
+ redis = Redis.new(OPTIONS)
496
+ sleep 0.3
497
+ redis.rpush("foo", "s3")
498
+ end
499
+
500
+ assert_equal @r.brpop("foo", 0.1), ["foo", "s2"]
501
+ assert_equal @r.brpop("foo", 0.1), ["foo", "s1"]
502
+ assert_equal @r.brpop("foo", 0.4), ["foo", "s3"]
503
+
504
+ t.join
505
+ end
506
+
507
+ test "BRPOP should unset a configured socket timeout" do
508
+ @r = Redis.new(OPTIONS.merge(:timeout => 1))
509
+ assert_nothing_raised do
510
+ @r.brpop("foo", 2)
511
+ end # Errno::EAGAIN raised if socket times out before redis command times out
512
+ end
513
+
514
+ test "BRPOP should restore the timeout after the command is run"
515
+
516
+ test "BRPOP should restore the timeout even if the command fails"
517
+ end
518
+
519
+ context "Commands operating on sets" do
520
+ test "SADD" do
521
+ @r.sadd "foo", "s1"
522
+ @r.sadd "foo", "s2"
523
+
524
+ assert_equal ["s1", "s2"], @r.smembers("foo").sort
525
+ end
526
+
527
+ test "SREM" do
528
+ @r.sadd "foo", "s1"
529
+ @r.sadd "foo", "s2"
530
+
531
+ @r.srem("foo", "s1")
532
+
533
+ assert_equal ["s2"], @r.smembers("foo")
534
+ end
535
+
536
+ test "SPOP" do
537
+ @r.sadd "foo", "s1"
538
+ @r.sadd "foo", "s2"
539
+
540
+ assert ["s1", "s2"].include?(@r.spop("foo"))
541
+ assert ["s1", "s2"].include?(@r.spop("foo"))
542
+ assert_nil @r.spop("foo")
543
+ end
544
+
545
+ test "SMOVE" do
546
+ @r.sadd "foo", "s1"
547
+ @r.sadd "bar", "s2"
548
+
549
+ assert @r.smove("foo", "bar", "s1")
550
+ assert @r.sismember("bar", "s1")
551
+ end
552
+
553
+ test "SCARD" do
554
+ assert_equal 0, @r.scard("foo")
555
+
556
+ @r.sadd "foo", "s1"
557
+
558
+ assert_equal 1, @r.scard("foo")
559
+
560
+ @r.sadd "foo", "s2"
561
+
562
+ assert_equal 2, @r.scard("foo")
563
+ end
564
+
565
+ test "SISMEMBER" do
566
+ assert_equal false, @r.sismember("foo", "s1")
567
+
568
+ @r.sadd "foo", "s1"
569
+
570
+ assert_equal true, @r.sismember("foo", "s1")
571
+ assert_equal false, @r.sismember("foo", "s2")
572
+ end
573
+
574
+ test "SINTER" do
575
+ @r.sadd "foo", "s1"
576
+ @r.sadd "foo", "s2"
577
+ @r.sadd "bar", "s2"
578
+
579
+ assert_equal ["s2"], @r.sinter("foo", "bar")
580
+ end
581
+
582
+ test "SINTERSTORE" do
583
+ @r.sadd "foo", "s1"
584
+ @r.sadd "foo", "s2"
585
+ @r.sadd "bar", "s2"
586
+
587
+ @r.sinterstore("baz", "foo", "bar")
588
+
589
+ assert_equal ["s2"], @r.smembers("baz")
590
+ end
591
+
592
+ test "SUNION" do
593
+ @r.sadd "foo", "s1"
594
+ @r.sadd "foo", "s2"
595
+ @r.sadd "bar", "s2"
596
+ @r.sadd "bar", "s3"
597
+
598
+ assert_equal ["s1", "s2", "s3"], @r.sunion("foo", "bar").sort
599
+ end
600
+
601
+ test "SUNIONSTORE" do
602
+ @r.sadd "foo", "s1"
603
+ @r.sadd "foo", "s2"
604
+ @r.sadd "bar", "s2"
605
+ @r.sadd "bar", "s3"
606
+
607
+ @r.sunionstore("baz", "foo", "bar")
608
+
609
+ assert_equal ["s1", "s2", "s3"], @r.smembers("baz").sort
610
+ end
611
+
612
+ test "SDIFF" do
613
+ @r.sadd "foo", "s1"
614
+ @r.sadd "foo", "s2"
615
+ @r.sadd "bar", "s2"
616
+ @r.sadd "bar", "s3"
617
+
618
+ assert_equal ["s1"], @r.sdiff("foo", "bar")
619
+ assert_equal ["s3"], @r.sdiff("bar", "foo")
620
+ end
621
+
622
+ test "SDIFFSTORE" do
623
+ @r.sadd "foo", "s1"
624
+ @r.sadd "foo", "s2"
625
+ @r.sadd "bar", "s2"
626
+ @r.sadd "bar", "s3"
627
+
628
+ @r.sdiffstore("baz", "foo", "bar")
629
+
630
+ assert_equal ["s1"], @r.smembers("baz")
631
+ end
632
+
633
+ test "SMEMBERS" do
634
+ assert_equal [], @r.smembers("foo")
635
+
636
+ @r.sadd "foo", "s1"
637
+ @r.sadd "foo", "s2"
638
+
639
+ assert_equal ["s1", "s2"], @r.smembers("foo").sort
640
+ end
641
+
642
+ test "SRANDMEMBER" do
643
+ @r.sadd "foo", "s1"
644
+ @r.sadd "foo", "s2"
645
+
646
+ 4.times do
647
+ assert ["s1", "s2"].include?(@r.srandmember("foo"))
648
+ end
649
+
650
+ assert_equal 2, @r.scard("foo")
651
+ end
652
+ end
653
+
654
+ context "Commands operating on sorted sets" do
655
+ test "ZADD" do
656
+ assert_equal 0, @r.zcard("foo")
657
+
658
+ @r.zadd "foo", 1, "s1"
659
+
660
+ assert_equal 1, @r.zcard("foo")
661
+ end
662
+
663
+ test "ZREM" do
664
+ @r.zadd "foo", 1, "s1"
665
+
666
+ assert_equal 1, @r.zcard("foo")
667
+
668
+ @r.zadd "foo", 2, "s2"
669
+
670
+ assert_equal 2, @r.zcard("foo")
671
+
672
+ @r.zrem "foo", "s1"
673
+
674
+ assert_equal 1, @r.zcard("foo")
675
+ end
676
+
677
+ test "ZINCRBY" do
678
+ @r.zincrby "foo", 1, "s1"
679
+
680
+ assert_equal "1", @r.zscore("foo", "s1")
681
+
682
+ @r.zincrby "foo", 10, "s1"
683
+
684
+ assert_equal "11", @r.zscore("foo", "s1")
685
+ end
686
+
687
+ test "ZRANK"
688
+
689
+ test "ZREVRANK"
690
+
691
+ test "ZRANGE" do
692
+ @r.zadd "foo", 1, "s1"
693
+ @r.zadd "foo", 2, "s2"
694
+ @r.zadd "foo", 3, "s3"
695
+
696
+ assert_equal ["s1", "s2"], @r.zrange("foo", 0, 1)
697
+ assert_equal ["s1", "1", "s2", "2"], @r.zrange("foo", 0, 1, true)
698
+ end
699
+
700
+ test "ZREVRANGE" do
701
+ @r.zadd "foo", 1, "s1"
702
+ @r.zadd "foo", 2, "s2"
703
+ @r.zadd "foo", 3, "s3"
704
+
705
+ assert_equal ["s3", "s2"], @r.zrevrange("foo", 0, 1)
706
+ assert_equal ["s3", "3", "s2", "2"], @r.zrevrange("foo", 0, 1, true)
707
+ end
708
+
709
+ test "ZRANGEBYSCORE" do
710
+ @r.zadd "foo", 1, "s1"
711
+ @r.zadd "foo", 2, "s2"
712
+ @r.zadd "foo", 3, "s3"
713
+
714
+ assert_equal ["s2", "s3"], @r.zrangebyscore("foo", 2, 3)
715
+ end
716
+
717
+ test "ZRANGEBYSCORE with LIMIT"
718
+ test "ZRANGEBYSCORE with WITHSCORES"
719
+
720
+ test "ZCARD" do
721
+ assert_equal 0, @r.zcard("foo")
722
+
723
+ @r.zadd "foo", 1, "s1"
724
+
725
+ assert_equal 1, @r.zcard("foo")
726
+ end
727
+
728
+ test "ZSCORE" do
729
+ @r.zadd "foo", 1, "s1"
730
+
731
+ assert_equal "1", @r.zscore("foo", "s1")
732
+
733
+ assert_nil @r.zscore("foo", "s2")
734
+ assert_nil @r.zscore("bar", "s1")
735
+ end
736
+
737
+ test "ZREMRANGEBYRANK"
738
+
739
+ test "ZREMRANGEBYSCORE"
740
+
741
+ test "ZUNION"
742
+
743
+ test "ZINTER"
744
+ end
745
+
746
+ context "Commands operating on hashes" do
747
+ test "HSET and HGET" do
748
+ @r.hset("foo", "f1", "s1")
749
+
750
+ assert_equal "s1", @r.hget("foo", "f1")
751
+ end
752
+
753
+ test "HDEL" do
754
+ @r.hset("foo", "f1", "s1")
755
+
756
+ assert_equal "s1", @r.hget("foo", "f1")
757
+
758
+ @r.hdel("foo", "f1")
759
+
760
+ assert_equal nil, @r.hget("foo", "f1")
761
+ end
762
+
763
+ test "HEXISTS" do
764
+ assert_equal false, @r.hexists("foo", "f1")
765
+
766
+ @r.hset("foo", "f1", "s1")
767
+
768
+ assert @r.hexists("foo", "f1")
769
+ end
770
+
771
+ test "HLEN" do
772
+ assert_equal 0, @r.hlen("foo")
773
+
774
+ @r.hset("foo", "f1", "s1")
775
+
776
+ assert_equal 1, @r.hlen("foo")
777
+
778
+ @r.hset("foo", "f2", "s2")
779
+
780
+ assert_equal 2, @r.hlen("foo")
781
+ end
782
+
783
+ test "HKEYS" do
784
+ assert_equal [], @r.hkeys("foo")
785
+
786
+ @r.hset("foo", "f1", "s1")
787
+ @r.hset("foo", "f2", "s2")
788
+
789
+ assert_equal ["f1", "f2"], @r.hkeys("foo")
790
+ end
791
+
792
+ test "HVALS" do
793
+ assert_equal [], @r.hvals("foo")
794
+
795
+ @r.hset("foo", "f1", "s1")
796
+ @r.hset("foo", "f2", "s2")
797
+
798
+ assert_equal ["s1", "s2"], @r.hvals("foo")
799
+ end
800
+
801
+ test "HGETALL" do
802
+ assert_equal({}, @r.hgetall("foo"))
803
+
804
+ @r.hset("foo", "f1", "s1")
805
+ @r.hset("foo", "f2", "s2")
806
+
807
+ assert_equal({"f1" => "s1", "f2" => "s2"}, @r.hgetall("foo"))
808
+ end
809
+
810
+ test "HMSET" do
811
+ @r.hmset("hash", "foo1", "bar1", "foo2", "bar2")
812
+
813
+ assert_equal "bar1", @r.hget("hash", "foo1")
814
+ assert_equal "bar2", @r.hget("hash", "foo2")
815
+ end
816
+
817
+ test "HMSET with invalid arguments" do
818
+ assert_raise(RuntimeError) do
819
+ @r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3")
820
+ end
821
+ end
822
+ end
823
+
824
+ context "Sorting" do
825
+ test "SORT" do
826
+ @r.set("foo:1", "s1")
827
+ @r.set("foo:2", "s2")
828
+
829
+ @r.rpush("bar", "1")
830
+ @r.rpush("bar", "2")
831
+
832
+ assert_equal ["s1"], @r.sort("bar", :get => "foo:*", :limit => [0, 1])
833
+ assert_equal ["s2"], @r.sort("bar", :get => "foo:*", :limit => [0, 1], :order => "desc alpha")
834
+ end
835
+
836
+ test "SORT with an array of GETs" do
837
+ @r.set("foo:1:a", "s1a")
838
+ @r.set("foo:1:b", "s1b")
839
+
840
+ @r.set("foo:2:a", "s2a")
841
+ @r.set("foo:2:b", "s2b")
842
+
843
+ @r.rpush("bar", "1")
844
+ @r.rpush("bar", "2")
845
+
846
+ assert_equal ["s1a", "s1b"], @r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1])
847
+ assert_equal ["s2a", "s2b"], @r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1], :order => "desc alpha")
848
+ end
849
+
850
+ test "SORT with STORE" do
851
+ @r.set("foo:1", "s1")
852
+ @r.set("foo:2", "s2")
853
+
854
+ @r.rpush("bar", "1")
855
+ @r.rpush("bar", "2")
856
+
857
+ @r.sort("bar", :get => "foo:*", :store => "baz")
858
+ assert_equal ["s1", "s2"], @r.lrange("baz", 0, -1)
859
+ end
860
+ end
861
+
862
+ context "Transactions" do
863
+ test "MULTI/DISCARD" do
864
+ @r.multi
865
+
866
+ assert_equal "QUEUED", @r.set("foo", "1")
867
+ assert_equal "QUEUED", @r.get("foo")
868
+
869
+ @r.discard
870
+
871
+ assert_equal nil, @r.get("foo")
872
+ end
873
+
874
+ test "MULTI/EXEC with a block" do
875
+ @r.multi do
876
+ @r.set "foo", "s1"
877
+ end
878
+
879
+ assert_equal "s1", @r.get("foo")
880
+
881
+ begin
882
+ @r.multi do
883
+ @r.set "bar", "s2"
884
+ raise "Some error"
885
+ @r.set "baz", "s3"
886
+ end
887
+ rescue
888
+ end
889
+
890
+ assert_nil @r.get("bar")
891
+ assert_nil @r.get("baz")
892
+ end
893
+
894
+ test "MULTI with a block yielding the client" do
895
+ @r.multi do |multi|
896
+ multi.set "foo", "s1"
897
+ end
898
+
899
+ assert_equal "s1", @r.get("foo")
900
+ end
901
+ end
902
+
903
+ context "Publish/Subscribe" do
904
+
905
+ test "SUBSCRIBE and UNSUBSCRIBE" do
906
+ thread = Thread.new do
907
+ @r.subscribe("foo") do |on|
908
+ on.subscribe do |channel, total|
909
+ @subscribed = true
910
+ @t1 = total
911
+ end
912
+
913
+ on.message do |channel, message|
914
+ if message == "s1"
915
+ @r.unsubscribe
916
+ @message = message
917
+ end
918
+ end
919
+
920
+ on.unsubscribe do |channel, total|
921
+ @unsubscribed = true
922
+ @t2 = total
923
+ end
924
+ end
925
+ end
926
+
927
+ Redis.new(OPTIONS).publish("foo", "s1")
928
+
929
+ thread.join
930
+
931
+ assert @subscribed
932
+ assert_equal 1, @t1
933
+ assert @unsubscribed
934
+ assert_equal 0, @t2
935
+ assert_equal "s1", @message
936
+ end
937
+
938
+ test "PSUBSCRIBE and PUNSUBSCRIBE" do
939
+ thread = Thread.new do
940
+ @r.psubscribe("f*") do |on|
941
+ on.psubscribe do |pattern, total|
942
+ @subscribed = true
943
+ @t1 = total
944
+ end
945
+
946
+ on.pmessage do |pattern, channel, message|
947
+ if message == "s1"
948
+ @r.punsubscribe
949
+ @message = message
950
+ end
951
+ end
952
+
953
+ on.punsubscribe do |pattern, total|
954
+ @unsubscribed = true
955
+ @t2 = total
956
+ end
957
+ end
958
+ end
959
+
960
+ Redis.new(OPTIONS).publish("foo", "s1")
961
+
962
+ thread.join
963
+
964
+ assert @subscribed
965
+ assert_equal 1, @t1
966
+ assert @unsubscribed
967
+ assert_equal 0, @t2
968
+ assert_equal "s1", @message
969
+ end
970
+
971
+ test "SUBSCRIBE within SUBSCRIBE" do
972
+ @channels = []
973
+
974
+ thread = Thread.new do
975
+ @r.subscribe("foo") do |on|
976
+ on.subscribe do |channel, total|
977
+ @channels << channel
978
+
979
+ @r.subscribe("bar") if channel == "foo"
980
+ @r.unsubscribe if channel == "bar"
981
+ end
982
+ end
983
+ end
984
+
985
+ Redis.new(OPTIONS).publish("foo", "s1")
986
+
987
+ thread.join
988
+
989
+ assert_equal ["foo", "bar"], @channels
990
+ end
991
+
992
+ test "other commands within a SUBSCRIBE" do
993
+ assert_raise RuntimeError do
994
+ @r.subscribe("foo") do |on|
995
+ on.subscribe do |channel, total|
996
+ @r.set("bar", "s2")
997
+ end
998
+ end
999
+ end
1000
+ end
1001
+
1002
+ test "SUBSCRIBE without a block" do
1003
+ assert_raise LocalJumpError do
1004
+ @r.subscribe("foo")
1005
+ end
1006
+ end
1007
+
1008
+ test "UNSUBSCRIBE without a SUBSCRIBE" do
1009
+ assert_raise RuntimeError do
1010
+ @r.unsubscribe
1011
+ end
1012
+
1013
+ assert_raise RuntimeError do
1014
+ @r.punsubscribe
1015
+ end
1016
+ end
1017
+
1018
+ test "SUBSCRIBE timeout"
1019
+ end
1020
+
1021
+ context "Persistence control commands" do
1022
+ test "SAVE and BGSAVE" do
1023
+ assert_nothing_raised do
1024
+ @r.save
1025
+ end
1026
+
1027
+ assert_nothing_raised do
1028
+ @r.bgsave
1029
+ end
1030
+ end
1031
+
1032
+ test "LASTSAVE" do
1033
+ assert Time.at(@r.lastsave) <= Time.now
1034
+ end
1035
+ end
1036
+
1037
+ context "Remote server control commands" do
1038
+ test "INFO" do
1039
+ %w(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|
1040
+ assert @r.info.keys.include?(x)
1041
+ end
1042
+ end
1043
+
1044
+ test "MONITOR" do
1045
+ assert_raises NotImplementedError do
1046
+ @r.monitor
1047
+ end
1048
+ end
1049
+
1050
+ test "ECHO" do
1051
+ assert_equal "foo bar baz\n", @r.echo("foo bar baz\n")
1052
+ end
1053
+ end
1054
+
1055
+ context "Pipelining commands" do
1056
+ test "BULK commands" do
1057
+ @r.pipelined do
1058
+ @r.lpush "foo", "s1"
1059
+ @r.lpush "foo", "s2"
1060
+ end
1061
+
1062
+ assert_equal 2, @r.llen("foo")
1063
+ assert_equal "s2", @r.lpop("foo")
1064
+ assert_equal "s1", @r.lpop("foo")
1065
+ end
1066
+
1067
+ test "MULTI_BULK commands" do
1068
+ @r.pipelined do
1069
+ @r.mset("foo", "s1", "bar", "s2")
1070
+ @r.mset("baz", "s3", "qux", "s4")
1071
+ end
1072
+
1073
+ assert_equal "s1", @r.get("foo")
1074
+ assert_equal "s2", @r.get("bar")
1075
+ assert_equal "s3", @r.get("baz")
1076
+ assert_equal "s4", @r.get("qux")
1077
+ end
1078
+
1079
+ test "BULK and MULTI_BULK commands mixed" do
1080
+ @r.pipelined do
1081
+ @r.lpush "foo", "s1"
1082
+ @r.lpush "foo", "s2"
1083
+ @r.mset("baz", "s3", "qux", "s4")
1084
+ end
1085
+
1086
+ assert_equal 2, @r.llen("foo")
1087
+ assert_equal "s2", @r.lpop("foo")
1088
+ assert_equal "s1", @r.lpop("foo")
1089
+ assert_equal "s3", @r.get("baz")
1090
+ assert_equal "s4", @r.get("qux")
1091
+ end
1092
+
1093
+ test "MULTI_BULK and BULK commands mixed" do
1094
+ @r.pipelined do
1095
+ @r.mset("baz", "s3", "qux", "s4")
1096
+ @r.lpush "foo", "s1"
1097
+ @r.lpush "foo", "s2"
1098
+ end
1099
+
1100
+ assert_equal 2, @r.llen("foo")
1101
+ assert_equal "s2", @r.lpop("foo")
1102
+ assert_equal "s1", @r.lpop("foo")
1103
+ assert_equal "s3", @r.get("baz")
1104
+ assert_equal "s4", @r.get("qux")
1105
+ end
1106
+
1107
+ test "Pipelined with an empty block" do
1108
+ assert_nothing_raised do
1109
+ @r.pipelined do
1110
+ end
1111
+ end
1112
+
1113
+ assert_equal 0, @r.dbsize
1114
+ end
1115
+
1116
+ test "Returning the result of a pipeline" do
1117
+ result = @r.pipelined do
1118
+ @r.set "foo", "bar"
1119
+ @r.get "foo"
1120
+ @r.get "bar"
1121
+ end
1122
+
1123
+ assert_equal ["OK", "bar", nil], result
1124
+ end
1125
+ end
1126
+
1127
+ context "Unknown commands" do
1128
+ should "try to work" do
1129
+ assert_raises RuntimeError do
1130
+ @r.not_yet_implemented_command
1131
+ end
1132
+ end
1133
+ end
1134
+ end