modesty 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 (130) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +18 -0
  3. data/LICENSE +21 -0
  4. data/README.md +121 -0
  5. data/Rakefile +29 -0
  6. data/VERSION +1 -0
  7. data/init.rb +1 -0
  8. data/lib/modesty.rb +26 -0
  9. data/lib/modesty/api.rb +14 -0
  10. data/lib/modesty/core_ext.rb +5 -0
  11. data/lib/modesty/core_ext/array.rb +21 -0
  12. data/lib/modesty/core_ext/fixnum.rb +5 -0
  13. data/lib/modesty/core_ext/hash.rb +39 -0
  14. data/lib/modesty/core_ext/string.rb +9 -0
  15. data/lib/modesty/core_ext/symbol.rb +33 -0
  16. data/lib/modesty/datastore.rb +51 -0
  17. data/lib/modesty/datastore/redis.rb +180 -0
  18. data/lib/modesty/experiment.rb +87 -0
  19. data/lib/modesty/experiment/base.rb +47 -0
  20. data/lib/modesty/experiment/builder.rb +48 -0
  21. data/lib/modesty/experiment/console.rb +4 -0
  22. data/lib/modesty/experiment/data.rb +75 -0
  23. data/lib/modesty/experiment/interface.rb +29 -0
  24. data/lib/modesty/experiment/significance.rb +376 -0
  25. data/lib/modesty/experiment/stats.rb +163 -0
  26. data/lib/modesty/frameworks/rails.rb +27 -0
  27. data/lib/modesty/identity.rb +32 -0
  28. data/lib/modesty/load.rb +80 -0
  29. data/lib/modesty/load/load_experiments.rb +14 -0
  30. data/lib/modesty/load/load_metrics.rb +17 -0
  31. data/lib/modesty/metric.rb +56 -0
  32. data/lib/modesty/metric/base.rb +38 -0
  33. data/lib/modesty/metric/builder.rb +23 -0
  34. data/lib/modesty/metric/data.rb +133 -0
  35. data/modesty.gemspec +192 -0
  36. data/spec/core_ext_spec.rb +17 -0
  37. data/spec/experiment_spec.rb +239 -0
  38. data/spec/identity_spec.rb +161 -0
  39. data/spec/load_spec.rb +87 -0
  40. data/spec/metric_spec.rb +176 -0
  41. data/spec/rails_spec.rb +48 -0
  42. data/spec/redis_spec.rb +29 -0
  43. data/spec/significance_spec.rb +147 -0
  44. data/spec/spec.opts +1 -0
  45. data/test/myapp/config/modesty.yml +9 -0
  46. data/test/myapp/modesty/experiments/cookbook.rb +4 -0
  47. data/test/myapp/modesty/metrics/kitchen_metrics.rb +9 -0
  48. data/test/myapp/modesty/metrics/stove/burner_metrics.rb +2 -0
  49. data/vendor/.piston.yml +8 -0
  50. data/vendor/mock_redis/.gitignore +2 -0
  51. data/vendor/mock_redis/README +8 -0
  52. data/vendor/mock_redis/lib/mock_redis.rb +10 -0
  53. data/vendor/mock_redis/lib/mock_redis/hash.rb +61 -0
  54. data/vendor/mock_redis/lib/mock_redis/list.rb +6 -0
  55. data/vendor/mock_redis/lib/mock_redis/misc.rb +69 -0
  56. data/vendor/mock_redis/lib/mock_redis/set.rb +108 -0
  57. data/vendor/mock_redis/lib/mock_redis/string.rb +32 -0
  58. data/vendor/redis-rb/.gitignore +8 -0
  59. data/vendor/redis-rb/LICENSE +20 -0
  60. data/vendor/redis-rb/README.markdown +129 -0
  61. data/vendor/redis-rb/Rakefile +155 -0
  62. data/vendor/redis-rb/benchmarking/logging.rb +62 -0
  63. data/vendor/redis-rb/benchmarking/pipeline.rb +51 -0
  64. data/vendor/redis-rb/benchmarking/speed.rb +21 -0
  65. data/vendor/redis-rb/benchmarking/suite.rb +24 -0
  66. data/vendor/redis-rb/benchmarking/thread_safety.rb +38 -0
  67. data/vendor/redis-rb/benchmarking/worker.rb +71 -0
  68. data/vendor/redis-rb/examples/basic.rb +15 -0
  69. data/vendor/redis-rb/examples/dist_redis.rb +43 -0
  70. data/vendor/redis-rb/examples/incr-decr.rb +17 -0
  71. data/vendor/redis-rb/examples/list.rb +26 -0
  72. data/vendor/redis-rb/examples/pubsub.rb +31 -0
  73. data/vendor/redis-rb/examples/sets.rb +36 -0
  74. data/vendor/redis-rb/examples/unicorn/config.ru +3 -0
  75. data/vendor/redis-rb/examples/unicorn/unicorn.rb +20 -0
  76. data/vendor/redis-rb/lib/redis.rb +676 -0
  77. data/vendor/redis-rb/lib/redis/client.rb +201 -0
  78. data/vendor/redis-rb/lib/redis/compat.rb +21 -0
  79. data/vendor/redis-rb/lib/redis/connection.rb +134 -0
  80. data/vendor/redis-rb/lib/redis/distributed.rb +526 -0
  81. data/vendor/redis-rb/lib/redis/hash_ring.rb +131 -0
  82. data/vendor/redis-rb/lib/redis/pipeline.rb +13 -0
  83. data/vendor/redis-rb/lib/redis/subscribe.rb +79 -0
  84. data/vendor/redis-rb/redis.gemspec +29 -0
  85. data/vendor/redis-rb/test/commands_on_hashes_test.rb +46 -0
  86. data/vendor/redis-rb/test/commands_on_lists_test.rb +50 -0
  87. data/vendor/redis-rb/test/commands_on_sets_test.rb +78 -0
  88. data/vendor/redis-rb/test/commands_on_sorted_sets_test.rb +109 -0
  89. data/vendor/redis-rb/test/commands_on_strings_test.rb +70 -0
  90. data/vendor/redis-rb/test/commands_on_value_types_test.rb +88 -0
  91. data/vendor/redis-rb/test/connection_handling_test.rb +87 -0
  92. data/vendor/redis-rb/test/db/.gitignore +1 -0
  93. data/vendor/redis-rb/test/distributd_key_tags_test.rb +53 -0
  94. data/vendor/redis-rb/test/distributed_blocking_commands_test.rb +54 -0
  95. data/vendor/redis-rb/test/distributed_commands_on_hashes_test.rb +12 -0
  96. data/vendor/redis-rb/test/distributed_commands_on_lists_test.rb +18 -0
  97. data/vendor/redis-rb/test/distributed_commands_on_sets_test.rb +85 -0
  98. data/vendor/redis-rb/test/distributed_commands_on_strings_test.rb +50 -0
  99. data/vendor/redis-rb/test/distributed_commands_on_value_types_test.rb +73 -0
  100. data/vendor/redis-rb/test/distributed_commands_requiring_clustering_test.rb +141 -0
  101. data/vendor/redis-rb/test/distributed_connection_handling_test.rb +25 -0
  102. data/vendor/redis-rb/test/distributed_internals_test.rb +18 -0
  103. data/vendor/redis-rb/test/distributed_persistence_control_commands_test.rb +24 -0
  104. data/vendor/redis-rb/test/distributed_publish_subscribe_test.rb +90 -0
  105. data/vendor/redis-rb/test/distributed_remote_server_control_commands_test.rb +31 -0
  106. data/vendor/redis-rb/test/distributed_sorting_test.rb +21 -0
  107. data/vendor/redis-rb/test/distributed_test.rb +60 -0
  108. data/vendor/redis-rb/test/distributed_transactions_test.rb +34 -0
  109. data/vendor/redis-rb/test/encoding_test.rb +16 -0
  110. data/vendor/redis-rb/test/helper.rb +86 -0
  111. data/vendor/redis-rb/test/internals_test.rb +27 -0
  112. data/vendor/redis-rb/test/lint/hashes.rb +90 -0
  113. data/vendor/redis-rb/test/lint/internals.rb +53 -0
  114. data/vendor/redis-rb/test/lint/lists.rb +93 -0
  115. data/vendor/redis-rb/test/lint/sets.rb +66 -0
  116. data/vendor/redis-rb/test/lint/sorted_sets.rb +132 -0
  117. data/vendor/redis-rb/test/lint/strings.rb +98 -0
  118. data/vendor/redis-rb/test/lint/value_types.rb +84 -0
  119. data/vendor/redis-rb/test/persistence_control_commands_test.rb +22 -0
  120. data/vendor/redis-rb/test/pipelining_commands_test.rb +78 -0
  121. data/vendor/redis-rb/test/publish_subscribe_test.rb +151 -0
  122. data/vendor/redis-rb/test/redis_mock.rb +64 -0
  123. data/vendor/redis-rb/test/remote_server_control_commands_test.rb +56 -0
  124. data/vendor/redis-rb/test/sorting_test.rb +44 -0
  125. data/vendor/redis-rb/test/test.conf +8 -0
  126. data/vendor/redis-rb/test/thread_safety_test.rb +34 -0
  127. data/vendor/redis-rb/test/transactions_test.rb +91 -0
  128. data/vendor/redis-rb/test/unknown_commands_test.rb +14 -0
  129. data/vendor/redis-rb/test/url_param_test.rb +52 -0
  130. metadata +277 -0
@@ -0,0 +1,21 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("./helper", File.dirname(__FILE__))
4
+ require "redis/distributed"
5
+
6
+ setup do
7
+ log = StringIO.new
8
+ init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
+ end
10
+
11
+ test "SORT" do |r|
12
+ assert_raise Redis::Distributed::CannotDistribute do
13
+ r.set("foo:1", "s1")
14
+ r.set("foo:2", "s2")
15
+
16
+ r.rpush("bar", "1")
17
+ r.rpush("bar", "2")
18
+
19
+ r.sort("bar", :get => "foo:*", :limit => [0, 1])
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("./helper", File.dirname(__FILE__))
4
+ require "redis/distributed"
5
+
6
+ setup do
7
+ log = StringIO.new
8
+ init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
+ end
10
+
11
+ test "handle multiple servers" do
12
+ @r = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
13
+
14
+ 100.times do |idx|
15
+ @r.set(idx.to_s, "foo#{idx}")
16
+ end
17
+
18
+ 100.times do |idx|
19
+ assert "foo#{idx}" == @r.get(idx.to_s)
20
+ end
21
+
22
+ assert "0" == @r.keys("*").sort.first
23
+ assert "string" == @r.type("1")
24
+ end
25
+
26
+ test "add nodes" do
27
+ logger = Logger.new("/dev/null")
28
+
29
+ @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
30
+
31
+ assert "127.0.0.1" == @r.nodes[0].client.host
32
+ assert 6379 == @r.nodes[0].client.port
33
+ assert 15 == @r.nodes[0].client.db
34
+ assert 10 == @r.nodes[0].client.timeout
35
+ assert logger == @r.nodes[0].client.logger
36
+
37
+ @r.add_node("redis://localhost:6380/14")
38
+
39
+ assert "localhost" == @r.nodes[1].client.host
40
+ assert 6380 == @r.nodes[1].client.port
41
+ assert 14 == @r.nodes[1].client.db
42
+ assert 10 == @r.nodes[1].client.timeout
43
+ assert logger == @r.nodes[1].client.logger
44
+ end
45
+
46
+ test "Pipelining commands cannot be distributed" do |r|
47
+ assert_raise Redis::Distributed::CannotDistribute do
48
+ r.pipelined do
49
+ r.lpush "foo", "s1"
50
+ r.lpush "foo", "s2"
51
+ end
52
+ end
53
+ end
54
+
55
+ test "Unknown commands does not work by default" do |r|
56
+ assert_raise NoMethodError do
57
+ r.not_yet_implemented_command
58
+ end
59
+ end
60
+
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("./helper", File.dirname(__FILE__))
4
+ require "redis/distributed"
5
+
6
+ setup do
7
+ log = StringIO.new
8
+ init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
9
+ end
10
+
11
+ test "MULTI/DISCARD" do |r|
12
+ @foo = nil
13
+
14
+ assert_raise Redis::Distributed::CannotDistribute do
15
+ r.multi { @foo = 1 }
16
+ end
17
+
18
+ assert nil == @foo
19
+
20
+ assert_raise Redis::Distributed::CannotDistribute do
21
+ r.discard
22
+ end
23
+ end
24
+
25
+ test "WATCH/UNWATCH" do |r|
26
+ assert_raise Redis::Distributed::CannotDistribute do
27
+ r.watch("foo")
28
+ end
29
+
30
+ assert_raise Redis::Distributed::CannotDistribute do
31
+ r.unwatch
32
+ end
33
+ end
34
+
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("./helper", File.dirname(__FILE__))
4
+
5
+ setup do
6
+ init Redis.new(OPTIONS)
7
+ end
8
+
9
+ test "returns properly encoded strings" do |r|
10
+ with_external_encoding("UTF-8") do
11
+ r.set "foo", "שלום"
12
+
13
+ assert "Shalom שלום" == "Shalom " + r.get("foo")
14
+ end
15
+ end if defined?(Encoding)
16
+
@@ -0,0 +1,86 @@
1
+ $:.unshift File.expand_path('../lib', File.dirname(__FILE__))
2
+
3
+ require "cutest"
4
+ require "logger"
5
+ require "stringio"
6
+
7
+ begin
8
+ require "ruby-debug"
9
+ rescue LoadError
10
+ end
11
+
12
+ PORT = 6379
13
+ OPTIONS = {:port => PORT, :db => 15, :timeout => 3}
14
+ NODES = ["redis://127.0.0.1:6379/15"]
15
+
16
+ def init(redis)
17
+ begin
18
+ redis.flushdb
19
+ redis.select 14
20
+ redis.flushdb
21
+ redis.select 15
22
+ redis
23
+ rescue Errno::ECONNREFUSED
24
+ puts <<-EOS
25
+
26
+ Cannot connect to Redis.
27
+
28
+ Make sure Redis is running on localhost, port 6379.
29
+ This testing suite connects to the database 15.
30
+
31
+ To install redis:
32
+ visit <http://code.google.com/p/redis/>.
33
+
34
+ To start the server:
35
+ rake start
36
+
37
+ To stop the server:
38
+ rake stop
39
+
40
+ EOS
41
+ exit 1
42
+ end
43
+ end
44
+
45
+ $VERBOSE = true
46
+
47
+ require "redis"
48
+
49
+ def capture_stderr
50
+ stderr = $stderr
51
+ $stderr = StringIO.new
52
+
53
+ yield
54
+
55
+ $stderr = stderr
56
+ end
57
+
58
+ def silent
59
+ verbose, $VERBOSE = $VERBOSE, false
60
+
61
+ begin
62
+ yield
63
+ ensure
64
+ $VERBOSE = verbose
65
+ end
66
+ end
67
+
68
+ def with_external_encoding(encoding)
69
+ original_encoding = Encoding.default_external
70
+
71
+ begin
72
+ silent { Encoding.default_external = Encoding.find(encoding) }
73
+ yield
74
+ ensure
75
+ silent { Encoding.default_external = original_encoding }
76
+ end
77
+ end
78
+
79
+ def assert_nothing_raised(*exceptions)
80
+ begin
81
+ yield
82
+ rescue *exceptions
83
+ flunk(caller[1])
84
+ end
85
+ end
86
+
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("./helper", File.dirname(__FILE__))
4
+ require File.expand_path("./redis_mock", File.dirname(__FILE__))
5
+
6
+ include RedisMock::Helper
7
+
8
+ setup do
9
+ log = StringIO.new
10
+
11
+ [Redis.new(OPTIONS.merge(:logger => ::Logger.new(log))), log]
12
+ end
13
+
14
+ $TEST_PIPELINING = true
15
+ $TEST_INSPECT = true
16
+
17
+ load File.expand_path("./lint/internals.rb", File.dirname(__FILE__))
18
+
19
+ test "Redis.current" do
20
+ Redis.current.set("foo", "bar")
21
+
22
+ assert "bar" == Redis.current.get("foo")
23
+
24
+ Redis.current = Redis.new(OPTIONS.merge(:db => 14))
25
+
26
+ assert Redis.current.get("foo").nil?
27
+ end
@@ -0,0 +1,90 @@
1
+ test "HSET and HGET" do |r|
2
+ r.hset("foo", "f1", "s1")
3
+
4
+ assert "s1" == r.hget("foo", "f1")
5
+ end
6
+
7
+ test "HDEL" do |r|
8
+ r.hset("foo", "f1", "s1")
9
+
10
+ assert "s1" == r.hget("foo", "f1")
11
+
12
+ r.hdel("foo", "f1")
13
+
14
+ assert nil == r.hget("foo", "f1")
15
+ end
16
+
17
+ test "HEXISTS" do |r|
18
+ assert false == r.hexists("foo", "f1")
19
+
20
+ r.hset("foo", "f1", "s1")
21
+
22
+ assert r.hexists("foo", "f1")
23
+ end
24
+
25
+ test "HLEN" do |r|
26
+ assert 0 == r.hlen("foo")
27
+
28
+ r.hset("foo", "f1", "s1")
29
+
30
+ assert 1 == r.hlen("foo")
31
+
32
+ r.hset("foo", "f2", "s2")
33
+
34
+ assert 2 == r.hlen("foo")
35
+ end
36
+
37
+ test "HKEYS" do |r|
38
+ assert [] == r.hkeys("foo")
39
+
40
+ r.hset("foo", "f1", "s1")
41
+ r.hset("foo", "f2", "s2")
42
+
43
+ assert ["f1", "f2"] == r.hkeys("foo")
44
+ end
45
+
46
+ test "HVALS" do |r|
47
+ assert [] == r.hvals("foo")
48
+
49
+ r.hset("foo", "f1", "s1")
50
+ r.hset("foo", "f2", "s2")
51
+
52
+ assert ["s1", "s2"] == r.hvals("foo")
53
+ end
54
+
55
+ test "HGETALL" do |r|
56
+ assert({} == r.hgetall("foo"))
57
+
58
+ r.hset("foo", "f1", "s1")
59
+ r.hset("foo", "f2", "s2")
60
+
61
+ assert({"f1" => "s1", "f2" => "s2"} == r.hgetall("foo"))
62
+ end
63
+
64
+ test "HMSET" do |r|
65
+ r.hmset("hash", "foo1", "bar1", "foo2", "bar2")
66
+
67
+ assert "bar1" == r.hget("hash", "foo1")
68
+ assert "bar2" == r.hget("hash", "foo2")
69
+ end
70
+
71
+ test "HMSET with invalid arguments" do |r|
72
+ assert_raise(RuntimeError) do
73
+ r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3")
74
+ end
75
+ end
76
+
77
+ test "HINCRBY" do |r|
78
+ r.hincrby("foo", "f1", 1)
79
+
80
+ assert "1" == r.hget("foo", "f1")
81
+
82
+ r.hincrby("foo", "f1", 2)
83
+
84
+ assert "3" == r.hget("foo", "f1")
85
+
86
+ r.hincrby("foo", "f1", -1)
87
+
88
+ assert "2" == r.hget("foo", "f1")
89
+ end
90
+
@@ -0,0 +1,53 @@
1
+ test "Logger" do |r, log|
2
+ r.ping
3
+
4
+ assert log.string =~ /Redis >> PING/
5
+ assert log.string =~ /Redis >> \d+\.\d+ms/
6
+ end
7
+
8
+ test "Logger with pipelining" do |r, log|
9
+ r.pipelined do
10
+ r.set "foo", "bar"
11
+ r.get "foo"
12
+ end
13
+
14
+ assert log.string["SET foo bar"]
15
+ assert log.string["GET foo"]
16
+ end if $TEST_PIPELINING
17
+
18
+ test "Timeout" do
19
+ assert_nothing_raised do
20
+ Redis.new(OPTIONS.merge(:timeout => 0))
21
+ end
22
+ end
23
+
24
+ test "Connection timeout" do
25
+ assert_raise(Timeout::Error) do
26
+ Redis.new(OPTIONS.merge(:host => "127.0.0.2", :timeout => 1)).ping
27
+ end
28
+ end
29
+
30
+ test "Recovers from failed commands" do |r, _|
31
+ # See http://github.com/ezmobius/redis-rb/issues#issue/28
32
+
33
+ assert_raise(ArgumentError) do
34
+ r.srem "foo"
35
+ end
36
+
37
+ assert_nothing_raised do
38
+ r.info
39
+ end
40
+ end
41
+
42
+ test "provides a meaningful inspect" do |r, _|
43
+ assert "#<Redis client v#{Redis::VERSION} connected to redis://127.0.0.1:6379/15 (Redis v#{r.info["redis_version"]})>" == r.inspect
44
+ end if $TEST_INSPECT
45
+
46
+ test "raises on protocol errors" do
47
+ redis_mock(:ping => lambda { |*_| "foo" }) do
48
+ assert_raise(Redis::ProtocolError) do
49
+ Redis.connect(:port => 6380).ping
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,93 @@
1
+ test "RPUSH" do |r|
2
+ r.rpush "foo", "s1"
3
+ r.rpush "foo", "s2"
4
+
5
+ assert 2 == r.llen("foo")
6
+ assert "s2" == r.rpop("foo")
7
+ end
8
+
9
+ test "LPUSH" do |r|
10
+ r.lpush "foo", "s1"
11
+ r.lpush "foo", "s2"
12
+
13
+ assert 2 == r.llen("foo")
14
+ assert "s2" == r.lpop("foo")
15
+ end
16
+
17
+ test "LLEN" do |r|
18
+ r.rpush "foo", "s1"
19
+ r.rpush "foo", "s2"
20
+
21
+ assert 2 == r.llen("foo")
22
+ end
23
+
24
+ test "LRANGE" do |r|
25
+ r.rpush "foo", "s1"
26
+ r.rpush "foo", "s2"
27
+ r.rpush "foo", "s3"
28
+
29
+ assert ["s2", "s3"] == r.lrange("foo", 1, -1)
30
+ assert ["s1", "s2"] == r.lrange("foo", 0, 1)
31
+
32
+ assert [] == r.lrange("bar", 0, -1)
33
+ end
34
+
35
+ test "LTRIM" do |r|
36
+ r.rpush "foo", "s1"
37
+ r.rpush "foo", "s2"
38
+ r.rpush "foo", "s3"
39
+
40
+ r.ltrim "foo", 0, 1
41
+
42
+ assert 2 == r.llen("foo")
43
+ assert ["s1", "s2"] == r.lrange("foo", 0, -1)
44
+ end
45
+
46
+ test "LINDEX" do |r|
47
+ r.rpush "foo", "s1"
48
+ r.rpush "foo", "s2"
49
+
50
+ assert "s1" == r.lindex("foo", 0)
51
+ assert "s2" == r.lindex("foo", 1)
52
+ end
53
+
54
+ test "LSET" do |r|
55
+ r.rpush "foo", "s1"
56
+ r.rpush "foo", "s2"
57
+
58
+ assert "s2" == r.lindex("foo", 1)
59
+ assert r.lset("foo", 1, "s3")
60
+ assert "s3" == r.lindex("foo", 1)
61
+
62
+ assert_raise RuntimeError do
63
+ r.lset("foo", 4, "s3")
64
+ end
65
+ end
66
+
67
+ test "LREM" do |r|
68
+ r.rpush "foo", "s1"
69
+ r.rpush "foo", "s2"
70
+
71
+ assert 1 == r.lrem("foo", 1, "s1")
72
+ assert ["s2"] == r.lrange("foo", 0, -1)
73
+ end
74
+
75
+ test "LPOP" do |r|
76
+ r.rpush "foo", "s1"
77
+ r.rpush "foo", "s2"
78
+
79
+ assert 2 == r.llen("foo")
80
+ assert "s1" == r.lpop("foo")
81
+ assert 1 == r.llen("foo")
82
+ end
83
+
84
+ test "RPOP" do |r|
85
+ r.rpush "foo", "s1"
86
+ r.rpush "foo", "s2"
87
+
88
+ assert 2 == r.llen("foo")
89
+ assert "s2" == r.rpop("foo")
90
+ assert 1 == r.llen("foo")
91
+ end
92
+
93
+