vanity 1.3.0 → 1.4.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/CHANGELOG +61 -3
  2. data/Gemfile +22 -14
  3. data/README.rdoc +9 -4
  4. data/Rakefile +72 -12
  5. data/bin/vanity +16 -4
  6. data/lib/vanity.rb +7 -5
  7. data/lib/vanity/adapters/abstract_adapter.rb +135 -0
  8. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  9. data/lib/vanity/adapters/mongo_adapter.rb +162 -0
  10. data/lib/vanity/adapters/redis_adapter.rb +154 -0
  11. data/lib/vanity/backport.rb +0 -17
  12. data/lib/vanity/commands/upgrade.rb +34 -0
  13. data/lib/vanity/experiment/ab_test.rb +46 -41
  14. data/lib/vanity/experiment/base.rb +13 -15
  15. data/lib/vanity/frameworks/rails.rb +5 -9
  16. data/lib/vanity/metric/active_record.rb +10 -4
  17. data/lib/vanity/metric/base.rb +46 -23
  18. data/lib/vanity/metric/google_analytics.rb +7 -0
  19. data/lib/vanity/metric/remote.rb +53 -0
  20. data/lib/vanity/playground.rb +133 -49
  21. data/test/{ab_test_test.rb → experiment/ab_test.rb} +47 -3
  22. data/test/{experiment_test.rb → experiment/base_test.rb} +8 -8
  23. data/test/metric/active_record_test.rb +253 -0
  24. data/test/metric/base_test.rb +293 -0
  25. data/test/metric/google_analytics_test.rb +104 -0
  26. data/test/metric/remote_test.rb +108 -0
  27. data/test/myapp/app/controllers/application_controller.rbc +66 -0
  28. data/test/myapp/app/controllers/main_controller.rb +3 -3
  29. data/test/myapp/app/controllers/main_controller.rbc +347 -0
  30. data/test/myapp/config/boot.rbc +2534 -0
  31. data/test/myapp/config/environment.rbc +403 -0
  32. data/test/myapp/config/routes.rbc +174 -0
  33. data/test/myapp/log/production.log +2601 -0
  34. data/test/passenger_test.rb +14 -5
  35. data/test/passenger_test.rbc +0 -0
  36. data/test/playground_test.rbc +256 -0
  37. data/test/rails_test.rb +75 -22
  38. data/test/rails_test.rbc +4086 -0
  39. data/test/test_helper.rb +30 -7
  40. data/test/test_helper.rbc +4297 -0
  41. data/vanity.gemspec +6 -2
  42. metadata +74 -73
  43. data/lib/vanity/commands.rb +0 -2
  44. data/lib/vanity/mock_redis.rb +0 -76
  45. data/test/metric_test.rb +0 -622
  46. data/vendor/cache/RedCloth-4.2.2.gem +0 -0
  47. data/vendor/cache/actionmailer-2.3.5.gem +0 -0
  48. data/vendor/cache/actionpack-2.3.5.gem +0 -0
  49. data/vendor/cache/activerecord-2.3.5.gem +0 -0
  50. data/vendor/cache/activeresource-2.3.5.gem +0 -0
  51. data/vendor/cache/activesupport-2.3.5.gem +0 -0
  52. data/vendor/cache/autotest-4.2.7.gem +0 -0
  53. data/vendor/cache/autotest-fsevent-0.2.1.gem +0 -0
  54. data/vendor/cache/autotest-growl-0.2.0.gem +0 -0
  55. data/vendor/cache/bundler-0.9.7.gem +0 -0
  56. data/vendor/cache/classifier-1.3.1.gem +0 -0
  57. data/vendor/cache/directory_watcher-1.3.1.gem +0 -0
  58. data/vendor/cache/fastthread-1.0.7.gem +0 -0
  59. data/vendor/cache/garb-0.7.0.gem +0 -0
  60. data/vendor/cache/happymapper-0.3.0.gem +0 -0
  61. data/vendor/cache/jekyll-0.5.7.gem +0 -0
  62. data/vendor/cache/libxml-ruby-1.1.3.gem +0 -0
  63. data/vendor/cache/liquid-2.0.0.gem +0 -0
  64. data/vendor/cache/maruku-0.6.0.gem +0 -0
  65. data/vendor/cache/mocha-0.9.8.gem +0 -0
  66. data/vendor/cache/open4-1.0.1.gem +0 -0
  67. data/vendor/cache/passenger-2.2.9.gem +0 -0
  68. data/vendor/cache/rack-1.0.1.gem +0 -0
  69. data/vendor/cache/rails-2.3.5.gem +0 -0
  70. data/vendor/cache/rake-0.8.7.gem +0 -0
  71. data/vendor/cache/rubygems-update-1.3.5.gem +0 -0
  72. data/vendor/cache/shoulda-2.10.3.gem +0 -0
  73. data/vendor/cache/sqlite3-ruby-1.2.5.gem +0 -0
  74. data/vendor/cache/stemmer-1.0.1.gem +0 -0
  75. data/vendor/cache/syntax-1.0.0.gem +0 -0
  76. data/vendor/cache/sys-uname-0.8.4.gem +0 -0
  77. data/vendor/cache/timecop-0.3.4.gem +0 -0
  78. data/vendor/redis-rb/LICENSE +0 -20
  79. data/vendor/redis-rb/README.markdown +0 -36
  80. data/vendor/redis-rb/Rakefile +0 -62
  81. data/vendor/redis-rb/bench.rb +0 -44
  82. data/vendor/redis-rb/benchmarking/suite.rb +0 -24
  83. data/vendor/redis-rb/benchmarking/worker.rb +0 -71
  84. data/vendor/redis-rb/bin/distredis +0 -33
  85. data/vendor/redis-rb/examples/basic.rb +0 -16
  86. data/vendor/redis-rb/examples/incr-decr.rb +0 -18
  87. data/vendor/redis-rb/examples/list.rb +0 -26
  88. data/vendor/redis-rb/examples/sets.rb +0 -36
  89. data/vendor/redis-rb/lib/dist_redis.rb +0 -124
  90. data/vendor/redis-rb/lib/hash_ring.rb +0 -128
  91. data/vendor/redis-rb/lib/pipeline.rb +0 -21
  92. data/vendor/redis-rb/lib/redis.rb +0 -370
  93. data/vendor/redis-rb/lib/redis/raketasks.rb +0 -1
  94. data/vendor/redis-rb/profile.rb +0 -22
  95. data/vendor/redis-rb/redis-rb.gemspec +0 -30
  96. data/vendor/redis-rb/spec/redis_spec.rb +0 -637
  97. data/vendor/redis-rb/spec/spec_helper.rb +0 -4
  98. data/vendor/redis-rb/speed.rb +0 -16
  99. data/vendor/redis-rb/tasks/redis.tasks.rb +0 -140
@@ -1 +0,0 @@
1
- require File.dirname(__FILE__) + "/../../tasks/redis.tasks"
@@ -1,22 +0,0 @@
1
- require 'rubygems'
2
- require 'ruby-prof'
3
- require "#{File.dirname(__FILE__)}/lib/redis"
4
-
5
-
6
- mode = ARGV.shift || 'process_time'
7
- n = (ARGV.shift || 200).to_i
8
-
9
- r = Redis.new
10
- RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
11
- RubyProf.start
12
-
13
- n.times do |i|
14
- key = "foo#{i}"
15
- r[key] = key * 10
16
- r[key]
17
- end
18
-
19
- results = RubyProf.stop
20
- File.open("profile.#{mode}", 'w') do |out|
21
- RubyProf::CallTreePrinter.new(results).print(out)
22
- end
@@ -1,30 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- Gem::Specification.new do |s|
4
- s.name = %q{redis}
5
- s.version = "0.1"
6
-
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Ezra Zygmuntowicz", "Taylor Weibley", "Matthew Clark", "Brian McKinney", "Salvatore Sanfilippo", "Luca Guidi"]
9
- # s.autorequire = %q{redis-rb}
10
- s.date = %q{2009-06-23}
11
- s.description = %q{Ruby client library for redis key value storage server}
12
- s.email = %q{ez@engineyard.com}
13
- s.extra_rdoc_files = ["LICENSE"]
14
- s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/dist_redis.rb", "lib/hash_ring.rb", "lib/pipeline.rb", "lib/redis.rb", "spec/redis_spec.rb", "spec/spec_helper.rb"]
15
- s.has_rdoc = true
16
- s.homepage = %q{http://github.com/ezmobius/redis-rb}
17
- s.require_paths = ["lib"]
18
- s.rubygems_version = %q{1.3.1}
19
- s.summary = %q{Ruby client library for redis key value storage server}
20
-
21
- if s.respond_to? :specification_version then
22
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
- s.specification_version = 2
24
-
25
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
- else
27
- end
28
- else
29
- end
30
- end
@@ -1,637 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
- require 'redis/raketasks'
3
- require 'logger'
4
-
5
- class Foo
6
- attr_accessor :bar
7
- def initialize(bar)
8
- @bar = bar
9
- end
10
-
11
- def ==(other)
12
- @bar == other.bar
13
- end
14
- end
15
-
16
- describe "redis" do
17
- before(:all) do
18
- result = RedisRunner.start_detached
19
- raise("Could not start redis-server, aborting") unless result
20
-
21
- # yea, this sucks, but it seems like sometimes we try to connect too quickly w/o it
22
- sleep 1
23
-
24
- # use database 15 for testing so we dont accidentally step on you real data
25
- @r = Redis.new :db => 15
26
- end
27
-
28
- before(:each) do
29
- @r['foo'] = 'bar'
30
- end
31
-
32
- after(:each) do
33
- @r.keys('*').each {|k| @r.del k}
34
- end
35
-
36
- after(:all) do
37
- begin
38
- @r.quit
39
- ensure
40
- RedisRunner.stop
41
- end
42
- end
43
-
44
- it "should be able connect without a timeout" do
45
- lambda { Redis.new :timeout => 0 }.should_not raise_error
46
- end
47
-
48
- it "should be able to provide a logger" do
49
- log = StringIO.new
50
- r = Redis.new :db => 15, :logger => Logger.new(log)
51
- r.ping
52
- log.string.should include("ping")
53
- end
54
-
55
- it "should be able to PING" do
56
- @r.ping.should == 'PONG'
57
- end
58
-
59
- it "should be able to GET a key" do
60
- @r['foo'].should == 'bar'
61
- end
62
-
63
- it "should be able to SET a key" do
64
- @r['foo'] = 'nik'
65
- @r['foo'].should == 'nik'
66
- end
67
-
68
- it "should properly handle trailing newline characters" do
69
- @r['foo'] = "bar\n"
70
- @r['foo'].should == "bar\n"
71
- end
72
-
73
- it "should store and retrieve all possible characters at the beginning and the end of a string" do
74
- (0..255).each do |char_idx|
75
- string = "#{char_idx.chr}---#{char_idx.chr}"
76
- @r['foo'] = string
77
- @r['foo'].should == string
78
- end
79
- end
80
-
81
- it "should be able to SET a key with an expiry" do
82
- @r.set('foo', 'bar', 1)
83
- @r['foo'].should == 'bar'
84
- sleep 2
85
- @r['foo'].should == nil
86
- end
87
-
88
- it "should be able to return a TTL for a key" do
89
- @r.set('foo', 'bar', 1)
90
- @r.ttl('foo').should == 1
91
- end
92
-
93
- it "should be able to SETNX" do
94
- @r['foo'] = 'nik'
95
- @r['foo'].should == 'nik'
96
- @r.setnx 'foo', 'bar'
97
- @r['foo'].should == 'nik'
98
- end
99
- #
100
- it "should be able to GETSET" do
101
- @r.getset('foo', 'baz').should == 'bar'
102
- @r['foo'].should == 'baz'
103
- end
104
- #
105
- it "should be able to INCR a key" do
106
- @r.del('counter')
107
- @r.incr('counter').should == 1
108
- @r.incr('counter').should == 2
109
- @r.incr('counter').should == 3
110
- end
111
- #
112
- it "should be able to INCRBY a key" do
113
- @r.del('counter')
114
- @r.incrby('counter', 1).should == 1
115
- @r.incrby('counter', 2).should == 3
116
- @r.incrby('counter', 3).should == 6
117
- end
118
- #
119
- it "should be able to DECR a key" do
120
- @r.del('counter')
121
- @r.incr('counter').should == 1
122
- @r.incr('counter').should == 2
123
- @r.incr('counter').should == 3
124
- @r.decr('counter').should == 2
125
- @r.decr('counter', 2).should == 0
126
- end
127
- #
128
- it "should be able to RANDKEY" do
129
- @r.randkey.should_not be_nil
130
- end
131
- #
132
- it "should be able to RENAME a key" do
133
- @r.del 'foo'
134
- @r.del'bar'
135
- @r['foo'] = 'hi'
136
- @r.rename 'foo', 'bar'
137
- @r['bar'].should == 'hi'
138
- end
139
- #
140
- it "should be able to RENAMENX a key" do
141
- @r.del 'foo'
142
- @r.del 'bar'
143
- @r['foo'] = 'hi'
144
- @r['bar'] = 'ohai'
145
- @r.renamenx 'foo', 'bar'
146
- @r['bar'].should == 'ohai'
147
- end
148
- #
149
- it "should be able to get DBSIZE of the database" do
150
- @r.delete 'foo'
151
- dbsize_without_foo = @r.dbsize
152
- @r['foo'] = 0
153
- dbsize_with_foo = @r.dbsize
154
-
155
- dbsize_with_foo.should == dbsize_without_foo + 1
156
- end
157
- #
158
- it "should be able to EXPIRE a key" do
159
- @r['foo'] = 'bar'
160
- @r.expire 'foo', 1
161
- @r['foo'].should == "bar"
162
- sleep 2
163
- @r['foo'].should == nil
164
- end
165
- #
166
- it "should be able to EXISTS" do
167
- @r['foo'] = 'nik'
168
- @r.exists('foo').should be_true
169
- @r.del 'foo'
170
- @r.exists('foo').should be_false
171
- end
172
- #
173
- it "should be able to KEYS" do
174
- @r.keys("f*").each { |key| @r.del key }
175
- @r['f'] = 'nik'
176
- @r['fo'] = 'nak'
177
- @r['foo'] = 'qux'
178
- @r.keys("f*").sort.should == ['f','fo', 'foo'].sort
179
- end
180
- #
181
- it "should be able to return a random key (RANDOMKEY)" do
182
- 3.times { @r.exists(@r.randomkey).should be_true }
183
- end
184
- #
185
- it "should be able to check the TYPE of a key" do
186
- @r['foo'] = 'nik'
187
- @r.type('foo').should == "string"
188
- @r.del 'foo'
189
- @r.type('foo').should == "none"
190
- end
191
- #
192
- it "should be able to push to the head of a list (LPUSH)" do
193
- @r.lpush "list", 'hello'
194
- @r.lpush "list", 42
195
- @r.type('list').should == "list"
196
- @r.llen('list').should == 2
197
- @r.lpop('list').should == '42'
198
- end
199
- #
200
- it "should be able to push to the tail of a list (RPUSH)" do
201
- @r.rpush "list", 'hello'
202
- @r.type('list').should == "list"
203
- @r.llen('list').should == 1
204
- end
205
- #
206
- it "should be able to pop the tail of a list (RPOP)" do
207
- @r.rpush "list", 'hello'
208
- @r.rpush"list", 'goodbye'
209
- @r.type('list').should == "list"
210
- @r.llen('list').should == 2
211
- @r.rpop('list').should == 'goodbye'
212
- end
213
- #
214
- it "should be able to pop the head of a list (LPOP)" do
215
- @r.rpush "list", 'hello'
216
- @r.rpush "list", 'goodbye'
217
- @r.type('list').should == "list"
218
- @r.llen('list').should == 2
219
- @r.lpop('list').should == 'hello'
220
- end
221
- #
222
- it "should be able to get the length of a list (LLEN)" do
223
- @r.rpush "list", 'hello'
224
- @r.rpush "list", 'goodbye'
225
- @r.type('list').should == "list"
226
- @r.llen('list').should == 2
227
- end
228
- #
229
- it "should be able to get a range of values from a list (LRANGE)" do
230
- @r.rpush "list", 'hello'
231
- @r.rpush "list", 'goodbye'
232
- @r.rpush "list", '1'
233
- @r.rpush "list", '2'
234
- @r.rpush "list", '3'
235
- @r.type('list').should == "list"
236
- @r.llen('list').should == 5
237
- @r.lrange('list', 2, -1).should == ['1', '2', '3']
238
- end
239
- #
240
- it "should be able to trim a list (LTRIM)" do
241
- @r.rpush "list", 'hello'
242
- @r.rpush "list", 'goodbye'
243
- @r.rpush "list", '1'
244
- @r.rpush "list", '2'
245
- @r.rpush "list", '3'
246
- @r.type('list').should == "list"
247
- @r.llen('list').should == 5
248
- @r.ltrim 'list', 0, 1
249
- @r.llen('list').should == 2
250
- @r.lrange('list', 0, -1).should == ['hello', 'goodbye']
251
- end
252
- #
253
- it "should be able to get a value by indexing into a list (LINDEX)" do
254
- @r.rpush "list", 'hello'
255
- @r.rpush "list", 'goodbye'
256
- @r.type('list').should == "list"
257
- @r.llen('list').should == 2
258
- @r.lindex('list', 1).should == 'goodbye'
259
- end
260
- #
261
- it "should be able to set a value by indexing into a list (LSET)" do
262
- @r.rpush "list", 'hello'
263
- @r.rpush "list", 'hello'
264
- @r.type('list').should == "list"
265
- @r.llen('list').should == 2
266
- @r.lset('list', 1, 'goodbye').should == 'OK'
267
- @r.lindex('list', 1).should == 'goodbye'
268
- end
269
- #
270
- it "should be able to remove values from a list (LREM)" do
271
- @r.rpush "list", 'hello'
272
- @r.rpush "list", 'goodbye'
273
- @r.type('list').should == "list"
274
- @r.llen('list').should == 2
275
- @r.lrem('list', 1, 'hello').should == 1
276
- @r.lrange('list', 0, -1).should == ['goodbye']
277
- end
278
-
279
- it "should be able to pop values from a list and push them onto a temp list(RPOPLPUSH)" do
280
- @r.rpush "list", 'one'
281
- @r.rpush "list", 'two'
282
- @r.rpush "list", 'three'
283
- @r.type('list').should == "list"
284
- @r.llen('list').should == 3
285
- @r.lrange('list',0,-1).should == ['one', 'two', 'three']
286
- @r.lrange('tmp',0,-1).should == []
287
- @r.rpoplpush('list', 'tmp').should == 'three'
288
- @r.lrange('tmp',0,-1).should == ['three']
289
- @r.rpoplpush('list', 'tmp').should == 'two'
290
- @r.lrange('tmp',0,-1).should == ['two', 'three']
291
- @r.rpoplpush('list', 'tmp').should == 'one'
292
- @r.lrange('tmp',0,-1).should == ['one','two','three']
293
- end
294
- #
295
- it "should be able add members to a set (SADD)" do
296
- @r.sadd "set", 'key1'
297
- @r.sadd "set", 'key2'
298
- @r.type('set').should == "set"
299
- @r.scard('set').should == 2
300
- @r.smembers('set').sort.should == ['key1', 'key2'].sort
301
- end
302
- #
303
- it "should be able delete members to a set (SREM)" do
304
- @r.sadd "set", 'key1'
305
- @r.sadd "set", 'key2'
306
- @r.type('set').should == "set"
307
- @r.scard('set').should == 2
308
- @r.smembers('set').sort.should == ['key1', 'key2'].sort
309
- @r.srem('set', 'key1')
310
- @r.scard('set').should == 1
311
- @r.smembers('set').should == ['key2']
312
- end
313
- #
314
- it "should be able to return and remove random key from set (SPOP)" do
315
- @r.sadd "set_pop", "key1"
316
- @r.sadd "set_pop", "key2"
317
- @r.spop("set_pop").should_not be_nil
318
- @r.scard("set_pop").should == 1
319
- end
320
- #
321
- it "should be able to return random key without delete the key from a set (SRANDMEMBER)" do
322
- @r.sadd "set_srandmember", "key1"
323
- @r.sadd "set_srandmember", "key2"
324
- @r.srandmember("set_srandmember").should_not be_nil
325
- @r.scard("set_srandmember").should == 2
326
- end
327
- #
328
- it "should be able count the members of a set (SCARD)" do
329
- @r.sadd "set", 'key1'
330
- @r.sadd "set", 'key2'
331
- @r.type('set').should == "set"
332
- @r.scard('set').should == 2
333
- end
334
- #
335
- it "should be able test for set membership (SISMEMBER)" do
336
- @r.sadd "set", 'key1'
337
- @r.sadd "set", 'key2'
338
- @r.type('set').should == "set"
339
- @r.scard('set').should == 2
340
- @r.sismember('set', 'key1').should be_true
341
- @r.sismember('set', 'key2').should be_true
342
- @r.sismember('set', 'notthere').should be_false
343
- end
344
- #
345
- it "should be able to do set intersection (SINTER)" do
346
- @r.sadd "set", 'key1'
347
- @r.sadd "set", 'key2'
348
- @r.sadd "set2", 'key2'
349
- @r.sinter('set', 'set2').should == ['key2']
350
- end
351
- #
352
- it "should be able to do set intersection and store the results in a key (SINTERSTORE)" do
353
- @r.sadd "set", 'key1'
354
- @r.sadd "set", 'key2'
355
- @r.sadd "set2", 'key2'
356
- @r.sinterstore('newone', 'set', 'set2').should == 1
357
- @r.smembers('newone').should == ['key2']
358
- end
359
- #
360
- it "should be able to do set union (SUNION)" do
361
- @r.sadd "set", 'key1'
362
- @r.sadd "set", 'key2'
363
- @r.sadd "set2", 'key2'
364
- @r.sadd "set2", 'key3'
365
- @r.sunion('set', 'set2').sort.should == ['key1','key2','key3'].sort
366
- end
367
- #
368
- it "should be able to do set union and store the results in a key (SUNIONSTORE)" do
369
- @r.sadd "set", 'key1'
370
- @r.sadd "set", 'key2'
371
- @r.sadd "set2", 'key2'
372
- @r.sadd "set2", 'key3'
373
- @r.sunionstore('newone', 'set', 'set2').should == 3
374
- @r.smembers('newone').sort.should == ['key1','key2','key3'].sort
375
- end
376
- #
377
- it "should be able to do set difference (SDIFF)" do
378
- @r.sadd "set", 'a'
379
- @r.sadd "set", 'b'
380
- @r.sadd "set2", 'b'
381
- @r.sadd "set2", 'c'
382
- @r.sdiff('set', 'set2').should == ['a']
383
- end
384
- #
385
- it "should be able to do set difference and store the results in a key (SDIFFSTORE)" do
386
- @r.sadd "set", 'a'
387
- @r.sadd "set", 'b'
388
- @r.sadd "set2", 'b'
389
- @r.sadd "set2", 'c'
390
- @r.sdiffstore('newone', 'set', 'set2')
391
- @r.smembers('newone').should == ['a']
392
- end
393
- #
394
- it "should be able move elements from one set to another (SMOVE)" do
395
- @r.sadd 'set1', 'a'
396
- @r.sadd 'set1', 'b'
397
- @r.sadd 'set2', 'x'
398
- @r.smove('set1', 'set2', 'a').should be_true
399
- @r.sismember('set2', 'a').should be_true
400
- @r.delete('set1')
401
- end
402
- #
403
- it "should be able to do crazy SORT queries" do
404
- # The 'Dogs' is capitialized on purpose
405
- @r['dog_1'] = 'louie'
406
- @r.rpush 'Dogs', 1
407
- @r['dog_2'] = 'lucy'
408
- @r.rpush 'Dogs', 2
409
- @r['dog_3'] = 'max'
410
- @r.rpush 'Dogs', 3
411
- @r['dog_4'] = 'taj'
412
- @r.rpush 'Dogs', 4
413
- @r.sort('Dogs', :get => 'dog_*', :limit => [0,1]).should == ['louie']
414
- @r.sort('Dogs', :get => 'dog_*', :limit => [0,1], :order => 'desc alpha').should == ['taj']
415
- end
416
-
417
- it "should be able to handle array of :get using SORT" do
418
- @r['dog:1:name'] = 'louie'
419
- @r['dog:1:breed'] = 'mutt'
420
- @r.rpush 'dogs', 1
421
- @r['dog:2:name'] = 'lucy'
422
- @r['dog:2:breed'] = 'poodle'
423
- @r.rpush 'dogs', 2
424
- @r['dog:3:name'] = 'max'
425
- @r['dog:3:breed'] = 'hound'
426
- @r.rpush 'dogs', 3
427
- @r['dog:4:name'] = 'taj'
428
- @r['dog:4:breed'] = 'terrier'
429
- @r.rpush 'dogs', 4
430
- @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1]).should == ['louie', 'mutt']
431
- @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1], :order => 'desc alpha').should == ['taj', 'terrier']
432
- end
433
- #
434
- it "should be able count the members of a zset" do
435
- @r.set_add "set", 'key1'
436
- @r.set_add "set", 'key2'
437
- @r.zset_add 'zset', 1, 'set'
438
- @r.zset_count('zset').should == 1
439
- @r.delete('set')
440
- @r.delete('zset')
441
- end
442
- #
443
- it "should be able add members to a zset" do
444
- @r.set_add "set", 'key1'
445
- @r.set_add "set", 'key2'
446
- @r.zset_add 'zset', 1, 'set'
447
- @r.zset_range('zset', 0, 1).should == ['set']
448
- @r.zset_count('zset').should == 1
449
- @r.delete('set')
450
- @r.delete('zset')
451
- end
452
- #
453
- it "should be able delete members to a zset" do
454
- @r.set_add "set", 'key1'
455
- @r.set_add "set", 'key2'
456
- @r.type?('set').should == "set"
457
- @r.set_add "set2", 'key3'
458
- @r.set_add "set2", 'key4'
459
- @r.type?('set2').should == "set"
460
- @r.zset_add 'zset', 1, 'set'
461
- @r.zset_count('zset').should == 1
462
- @r.zset_add 'zset', 2, 'set2'
463
- @r.zset_count('zset').should == 2
464
- @r.zset_delete 'zset', 'set'
465
- @r.zset_count('zset').should == 1
466
- @r.delete('set')
467
- @r.delete('set2')
468
- @r.delete('zset')
469
- end
470
- #
471
- it "should be able to get a range of values from a zset" do
472
- @r.set_add "set", 'key1'
473
- @r.set_add "set", 'key2'
474
- @r.set_add "set2", 'key3'
475
- @r.set_add "set2", 'key4'
476
- @r.set_add "set3", 'key1'
477
- @r.type?('set').should == 'set'
478
- @r.type?('set2').should == 'set'
479
- @r.type?('set3').should == 'set'
480
- @r.zset_add 'zset', 1, 'set'
481
- @r.zset_add 'zset', 2, 'set2'
482
- @r.zset_add 'zset', 3, 'set3'
483
- @r.zset_count('zset').should == 3
484
- @r.zset_range('zset', 0, 3).should == ['set', 'set2', 'set3']
485
- @r.delete('set')
486
- @r.delete('set2')
487
- @r.delete('set3')
488
- @r.delete('zset')
489
- end
490
- #
491
- it "should be able to get a reverse range of values from a zset" do
492
- @r.set_add "set", 'key1'
493
- @r.set_add "set", 'key2'
494
- @r.set_add "set2", 'key3'
495
- @r.set_add "set2", 'key4'
496
- @r.set_add "set3", 'key1'
497
- @r.type?('set').should == 'set'
498
- @r.type?('set2').should == 'set'
499
- @r.type?('set3').should == 'set'
500
- @r.zset_add 'zset', 1, 'set'
501
- @r.zset_add 'zset', 2, 'set2'
502
- @r.zset_add 'zset', 3, 'set3'
503
- @r.zset_count('zset').should == 3
504
- @r.zset_reverse_range('zset', 0, 3).should == ['set3', 'set2', 'set']
505
- @r.delete('set')
506
- @r.delete('set2')
507
- @r.delete('set3')
508
- @r.delete('zset')
509
- end
510
- #
511
- it "should be able to get a range by score of values from a zset" do
512
- @r.set_add "set", 'key1'
513
- @r.set_add "set", 'key2'
514
- @r.set_add "set2", 'key3'
515
- @r.set_add "set2", 'key4'
516
- @r.set_add "set3", 'key1'
517
- @r.set_add "set4", 'key4'
518
- @r.zset_add 'zset', 1, 'set'
519
- @r.zset_add 'zset', 2, 'set2'
520
- @r.zset_add 'zset', 3, 'set3'
521
- @r.zset_add 'zset', 4, 'set4'
522
- @r.zset_count('zset').should == 4
523
- @r.zset_range_by_score('zset', 2, 3).should == ['set2', 'set3']
524
- @r.delete('set')
525
- @r.delete('set2')
526
- @r.delete('set3')
527
- @r.delete('set4')
528
- @r.delete('zset')
529
- end
530
-
531
- it "should provide info (INFO)" do
532
- [: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|
533
- @r.info.keys.should include(x)
534
- end
535
- end
536
- #
537
- it "should be able to flush the database (FLUSHDB)" do
538
- @r['key1'] = 'keyone'
539
- @r['key2'] = 'keytwo'
540
- @r.keys('*').sort.should == ['foo', 'key1', 'key2'].sort #foo from before
541
- @r.flushdb
542
- @r.keys('*').should == []
543
- end
544
- #
545
- it "should raise exception when manually try to change the database" do
546
- lambda { @r.select(0) }.should raise_error
547
- end
548
- #
549
- it "should be able to provide the last save time (LASTSAVE)" do
550
- savetime = @r.lastsave
551
- Time.at(savetime).class.should == Time
552
- Time.at(savetime).should <= Time.now
553
- end
554
-
555
- it "should be able to MGET keys" do
556
- @r['foo'] = 1000
557
- @r['bar'] = 2000
558
- @r.mget('foo', 'bar').should == ['1000', '2000']
559
- @r.mget('foo', 'bar', 'baz').should == ['1000', '2000', nil]
560
- end
561
-
562
- it "should be able to mapped MGET keys" do
563
- @r['foo'] = 1000
564
- @r['bar'] = 2000
565
- @r.mapped_mget('foo', 'bar').should == { 'foo' => '1000', 'bar' => '2000'}
566
- @r.mapped_mget('foo', 'baz', 'bar').should == { 'foo' => '1000', 'bar' => '2000'}
567
- end
568
-
569
- it "should be able to MSET values" do
570
- @r.mset :key1 => "value1", :key2 => "value2"
571
- @r['key1'].should == "value1"
572
- @r['key2'].should == "value2"
573
- end
574
-
575
- it "should be able to MSETNX values" do
576
- @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
577
- @r.mget('keynx1', 'keynx2').should == ["valuenx1", "valuenx2"]
578
-
579
- @r["keynx1"] = "value1"
580
- @r["keynx2"] = "value2"
581
- @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
582
- @r.mget('keynx1', 'keynx2').should == ["value1", "value2"]
583
- end
584
-
585
- it "should bgsave" do
586
- @r.bgsave.should == 'OK'
587
- end
588
-
589
- it "should be able to ECHO" do
590
- @r.echo("message in a bottle\n").should == "message in a bottle\n"
591
- end
592
-
593
- it "should raise error when invoke MONITOR" do
594
- lambda { @r.monitor }.should raise_error
595
- end
596
-
597
- it "should raise error when invoke SYNC" do
598
- lambda { @r.sync }.should raise_error
599
- end
600
-
601
- it "should handle multiple servers" do
602
- require 'dist_redis'
603
- @r = DistRedis.new(:hosts=> ['localhost:6379', '127.0.0.1:6379'], :db => 15)
604
-
605
- 100.times do |idx|
606
- @r[idx] = "foo#{idx}"
607
- end
608
-
609
- 100.times do |idx|
610
- @r[idx].should == "foo#{idx}"
611
- end
612
- end
613
-
614
- it "should be able to pipeline writes" do
615
- @r.pipelined do |pipeline|
616
- pipeline.lpush 'list', "hello"
617
- pipeline.lpush 'list', 42
618
- end
619
-
620
- @r.type('list').should == "list"
621
- @r.llen('list').should == 2
622
- @r.lpop('list').should == '42'
623
- end
624
-
625
- it "should do nothing when pipelining no commands" do
626
- @r.pipelined do |pipeline|
627
- end
628
- end
629
-
630
- it "should AUTH when connecting with a password" do
631
- r = Redis.new(:password => 'secret')
632
- r.stub!(:connect_to)
633
- r.should_receive(:call_command).with(['auth', 'secret'])
634
- r.connect_to_server
635
- end
636
-
637
- end