lunar 0.1.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.
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