]> git.saurik.com Git - redis.git/blame - client-libraries/ruby/spec/redis_spec.rb
Redis release candidate 1
[redis.git] / client-libraries / ruby / spec / redis_spec.rb
CommitLineData
ed9b544e 1require File.dirname(__FILE__) + '/spec_helper'
2
3class Foo
4 attr_accessor :bar
5 def initialize(bar)
6 @bar = bar
7 end
8
9 def ==(other)
10 @bar == other.bar
11 end
12end
13
14describe "redis" do
9495122b 15 before(:all) do
d7fc9edb 16 # use database 15 for testing so we dont accidentally step on you real data
17 @r = Redis.new :db => 15
9495122b 18 end
19
20 before(:each) do
ed9b544e 21 @r['foo'] = 'bar'
9495122b 22 end
23
24 after(:each) do
0df1ead7 25 @r.keys('*').each {|k| @r.del k}
ed9b544e 26 end
9495122b 27
28 after(:all) do
29fac617 29 @r.quit
ed9b544e 30 end
31
d7fc9edb 32 it 'should be able to PING' do
0df1ead7 33 @r.ping.should == 'PONG'
d7fc9edb 34 end
ed9b544e 35
36 it "should be able to GET a key" do
37 @r['foo'].should == 'bar'
38 end
39
40 it "should be able to SET a key" do
41 @r['foo'] = 'nik'
42 @r['foo'].should == 'nik'
43 end
44
57172ffb 45 it "should properly handle trailing newline characters" do
46 @r['foo'] = "bar\n"
47 @r['foo'].should == "bar\n"
48 end
49
50 it "should store and retrieve all possible characters at the beginning and the end of a string" do
51 (0..255).each do |char_idx|
52 string = "#{char_idx.chr}---#{char_idx.chr}"
53 @r['foo'] = string
54 @r['foo'].should == string
55 end
56 end
57
9495122b 58 it "should be able to SET a key with an expiry" do
59 @r.set('foo', 'bar', 1)
60 @r['foo'].should == 'bar'
61 sleep 2
62 @r['foo'].should == nil
63 end
64
0df1ead7 65 it "should be able to SETNX" do
ed9b544e 66 @r['foo'] = 'nik'
67 @r['foo'].should == 'nik'
0df1ead7 68 @r.setnx 'foo', 'bar'
ed9b544e 69 @r['foo'].should == 'nik'
70 end
29fac617 71 #
0df1ead7 72 it "should be able to INCR a key" do
73 @r.del('counter')
ed9b544e 74 @r.incr('counter').should == 1
75 @r.incr('counter').should == 2
76 @r.incr('counter').should == 3
77 end
29fac617 78 #
0df1ead7 79 it "should be able to DECR a key" do
80 @r.del('counter')
ed9b544e 81 @r.incr('counter').should == 1
82 @r.incr('counter').should == 2
83 @r.incr('counter').should == 3
84 @r.decr('counter').should == 2
9495122b 85 @r.decr('counter', 2).should == 0
ed9b544e 86 end
29fac617 87 #
0df1ead7 88 it "should be able to RANDKEY" do
ed9b544e 89 @r.randkey.should_not be_nil
90 end
29fac617 91 #
ed9b544e 92 it "should be able to RENAME a key" do
0df1ead7 93 @r.del 'foo'
94 @r.del'bar'
ed9b544e 95 @r['foo'] = 'hi'
0df1ead7 96 @r.rename 'foo', 'bar'
ed9b544e 97 @r['bar'].should == 'hi'
98 end
29fac617 99 #
0df1ead7 100 it "should be able to RENAMENX a key" do
101 @r.del 'foo'
102 @r.del 'bar'
ed9b544e 103 @r['foo'] = 'hi'
104 @r['bar'] = 'ohai'
0df1ead7 105 @r.renamenx 'foo', 'bar'
ed9b544e 106 @r['bar'].should == 'ohai'
107 end
d7fc9edb 108 #
109 it "should be able to get DBSIZE of the database" do
110 @r.delete 'foo'
111 dbsize_without_foo = @r.dbsize
112 @r['foo'] = 0
113 dbsize_with_foo = @r.dbsize
114
115 dbsize_with_foo.should == dbsize_without_foo + 1
116 end
117 #
9495122b 118 it "should be able to EXPIRE a key" do
119 @r['foo'] = 'bar'
0df1ead7 120 @r.expire 'foo', 1
9495122b 121 @r['foo'].should == "bar"
122 sleep 2
123 @r['foo'].should == nil
124 end
125 #
0df1ead7 126 it "should be able to EXISTS" do
ed9b544e 127 @r['foo'] = 'nik'
0df1ead7 128 @r.exists('foo').should be_true
129 @r.del 'foo'
130 @r.exists('foo').should be_false
ed9b544e 131 end
29fac617 132 #
0df1ead7 133 it "should be able to KEYS" do
134 @r.keys("f*").each { |key| @r.del key }
ed9b544e 135 @r['f'] = 'nik'
136 @r['fo'] = 'nak'
137 @r['foo'] = 'qux'
138 @r.keys("f*").sort.should == ['f','fo', 'foo'].sort
139 end
0df1ead7 140 #BTM - TODO
ed9b544e 141 it "should be able to check the TYPE of a key" do
142 @r['foo'] = 'nik'
0df1ead7 143 @r.type('foo').should == "string"
144 @r.del 'foo'
145 @r.type('foo').should == "none"
ed9b544e 146 end
29fac617 147 #
0df1ead7 148 it "should be able to push to the head of a list (LPUSH)" do
149 @r.lpush "list", 'hello'
150 @r.lpush "list", 42
151 @r.type('list').should == "list"
152 @r.llen('list').should == 2
153 @r.lpop('list').should == '42'
ed9b544e 154 end
29fac617 155 #
0df1ead7 156 it "should be able to push to the tail of a list (RPUSH)" do
157 @r.rpush "list", 'hello'
158 @r.type('list').should == "list"
159 @r.llen('list').should == 1
ed9b544e 160 end
29fac617 161 #
0df1ead7 162 it "should be able to pop the tail of a list (RPOP)" do
163 @r.rpush "list", 'hello'
164 @r.rpush"list", 'goodbye'
165 @r.type('list').should == "list"
166 @r.llen('list').should == 2
167 @r.rpop('list').should == 'goodbye'
ed9b544e 168 end
29fac617 169 #
0df1ead7 170 it "should be able to pop the head of a list (LPOP)" do
171 @r.rpush "list", 'hello'
172 @r.rpush "list", 'goodbye'
173 @r.type('list').should == "list"
174 @r.llen('list').should == 2
175 @r.lpop('list').should == 'hello'
ed9b544e 176 end
29fac617 177 #
0df1ead7 178 it "should be able to get the length of a list (LLEN)" do
179 @r.rpush "list", 'hello'
180 @r.rpush "list", 'goodbye'
181 @r.type('list').should == "list"
182 @r.llen('list').should == 2
ed9b544e 183 end
29fac617 184 #
0df1ead7 185 it "should be able to get a range of values from a list (LRANGE)" do
186 @r.rpush "list", 'hello'
187 @r.rpush "list", 'goodbye'
188 @r.rpush "list", '1'
189 @r.rpush "list", '2'
190 @r.rpush "list", '3'
191 @r.type('list').should == "list"
192 @r.llen('list').should == 5
193 @r.lrange('list', 2, -1).should == ['1', '2', '3']
ed9b544e 194 end
29fac617 195 #
0df1ead7 196 it "should be able to trim a list (LTRIM)" do
197 @r.rpush "list", 'hello'
198 @r.rpush "list", 'goodbye'
199 @r.rpush "list", '1'
200 @r.rpush "list", '2'
201 @r.rpush "list", '3'
202 @r.type('list').should == "list"
203 @r.llen('list').should == 5
204 @r.ltrim 'list', 0, 1
205 @r.llen('list').should == 2
206 @r.lrange('list', 0, -1).should == ['hello', 'goodbye']
ed9b544e 207 end
29fac617 208 #
0df1ead7 209 it "should be able to get a value by indexing into a list (LINDEX)" do
210 @r.rpush "list", 'hello'
211 @r.rpush "list", 'goodbye'
212 @r.type('list').should == "list"
213 @r.llen('list').should == 2
214 @r.lindex('list', 1).should == 'goodbye'
ed9b544e 215 end
29fac617 216 #
0df1ead7 217 it "should be able to set a value by indexing into a list (LSET)" do
218 @r.rpush "list", 'hello'
219 @r.rpush "list", 'hello'
220 @r.type('list').should == "list"
221 @r.llen('list').should == 2
222 @r.lset('list', 1, 'goodbye').should == 'OK'
223 @r.lindex('list', 1).should == 'goodbye'
ed9b544e 224 end
29fac617 225 #
0df1ead7 226 it "should be able to remove values from a list (LREM)" do
227 @r.rpush "list", 'hello'
228 @r.rpush "list", 'goodbye'
229 @r.type('list').should == "list"
230 @r.llen('list').should == 2
231 @r.lrem('list', 1, 'hello').should == 1
232 @r.lrange('list', 0, -1).should == ['goodbye']
29fac617 233 end
234 #
0df1ead7 235 it "should be able add members to a set (SADD)" do
236 @r.sadd "set", 'key1'
237 @r.sadd "set", 'key2'
238 @r.type('set').should == "set"
239 @r.scard('set').should == 2
240 @r.smembers('set').sort.should == ['key1', 'key2'].sort
ed9b544e 241 end
29fac617 242 #
0df1ead7 243 it "should be able delete members to a set (SREM)" do
244 @r.sadd "set", 'key1'
245 @r.sadd "set", 'key2'
246 @r.type('set').should == "set"
247 @r.scard('set').should == 2
248 @r.smembers('set').sort.should == ['key1', 'key2'].sort
249 @r.srem('set', 'key1')
250 @r.scard('set').should == 1
251 @r.smembers('set').should == ['key2']
ed9b544e 252 end
29fac617 253 #
0df1ead7 254 it "should be able count the members of a set (SCARD)" do
255 @r.sadd "set", 'key1'
256 @r.sadd "set", 'key2'
257 @r.type('set').should == "set"
258 @r.scard('set').should == 2
ed9b544e 259 end
29fac617 260 #
0df1ead7 261 it "should be able test for set membership (SISMEMBER)" do
262 @r.sadd "set", 'key1'
263 @r.sadd "set", 'key2'
264 @r.type('set').should == "set"
265 @r.scard('set').should == 2
266 @r.sismember('set', 'key1').should be_true
267 @r.sismember('set', 'key2').should be_true
268 @r.sismember('set', 'notthere').should be_false
ed9b544e 269 end
29fac617 270 #
0df1ead7 271 it "should be able to do set intersection (SINTER)" do
272 @r.sadd "set", 'key1'
273 @r.sadd "set", 'key2'
274 @r.sadd "set2", 'key2'
275 @r.sinter('set', 'set2').should == ['key2']
ed9b544e 276 end
29fac617 277 #
0df1ead7 278 it "should be able to do set intersection and store the results in a key (SINTERSTORE)" do
279 @r.sadd "set", 'key1'
280 @r.sadd "set", 'key2'
281 @r.sadd "set2", 'key2'
282 @r.sinterstore('newone', 'set', 'set2').should == 1
283 @r.smembers('newone').should == ['key2']
ed9b544e 284 end
57172ffb 285 #
0df1ead7 286 it "should be able to do set union (SUNION)" do
287 @r.sadd "set", 'key1'
288 @r.sadd "set", 'key2'
289 @r.sadd "set2", 'key2'
290 @r.sadd "set2", 'key3'
291 @r.sunion('set', 'set2').sort.should == ['key1','key2','key3'].sort
57172ffb 292 end
293 #
0df1ead7 294 it "should be able to do set union and store the results in a key (SUNIONSTORE)" do
295 @r.sadd "set", 'key1'
296 @r.sadd "set", 'key2'
297 @r.sadd "set2", 'key2'
298 @r.sadd "set2", 'key3'
299 @r.sunionstore('newone', 'set', 'set2').should == 3
300 @r.smembers('newone').sort.should == ['key1','key2','key3'].sort
57172ffb 301 end
d7fc9edb 302 #
0df1ead7 303 it "should be able to do set difference (SDIFF)" do
304 @r.sadd "set", 'a'
305 @r.sadd "set", 'b'
306 @r.sadd "set2", 'b'
307 @r.sadd "set2", 'c'
308 @r.sdiff('set', 'set2').should == ['a']
d7fc9edb 309 end
310 #
0df1ead7 311 it "should be able to do set difference and store the results in a key (SDIFFSTORE)" do
312 @r.sadd "set", 'a'
313 @r.sadd "set", 'b'
314 @r.sadd "set2", 'b'
315 @r.sadd "set2", 'c'
316 @r.sdiffstore('newone', 'set', 'set2')
317 @r.smembers('newone').should == ['a']
d7fc9edb 318 end
29fac617 319 #
0df1ead7 320 it "should be able move elements from one set to another (SMOVE)" do
321 @r.sadd 'set1', 'a'
322 @r.sadd 'set1', 'b'
323 @r.sadd 'set2', 'x'
324 @r.smove('set1', 'set2', 'a').should be_true
325 @r.sismember('set2', 'a').should be_true
57172ffb 326 @r.delete('set1')
327 end
328 #
ed9b544e 329 it "should be able to do crazy SORT queries" do
330 @r['dog_1'] = 'louie'
0df1ead7 331 @r.rpush 'dogs', 1
ed9b544e 332 @r['dog_2'] = 'lucy'
0df1ead7 333 @r.rpush 'dogs', 2
ed9b544e 334 @r['dog_3'] = 'max'
0df1ead7 335 @r.rpush 'dogs', 3
ed9b544e 336 @r['dog_4'] = 'taj'
0df1ead7 337 @r.rpush 'dogs', 4
ed9b544e 338 @r.sort('dogs', :get => 'dog_*', :limit => [0,1]).should == ['louie']
339 @r.sort('dogs', :get => 'dog_*', :limit => [0,1], :order => 'desc alpha').should == ['taj']
340 end
d7fc9edb 341
342 it "should be able to handle array of :get using SORT" do
343 @r['dog:1:name'] = 'louie'
344 @r['dog:1:breed'] = 'mutt'
0df1ead7 345 @r.rpush 'dogs', 1
d7fc9edb 346 @r['dog:2:name'] = 'lucy'
347 @r['dog:2:breed'] = 'poodle'
0df1ead7 348 @r.rpush 'dogs', 2
d7fc9edb 349 @r['dog:3:name'] = 'max'
350 @r['dog:3:breed'] = 'hound'
0df1ead7 351 @r.rpush 'dogs', 3
d7fc9edb 352 @r['dog:4:name'] = 'taj'
353 @r['dog:4:breed'] = 'terrier'
0df1ead7 354 @r.rpush 'dogs', 4
d7fc9edb 355 @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1]).should == ['louie', 'mutt']
356 @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1], :order => 'desc alpha').should == ['taj', 'terrier']
357 end
29fac617 358 #
359 it "should provide info" do
360 [: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|
361 @r.info.keys.should include(x)
362 end
363 end
364 #
365 it "should be able to flush the database" do
366 @r['key1'] = 'keyone'
367 @r['key2'] = 'keytwo'
0df1ead7 368 @r.keys('*').sort.should == ['foo', 'key1', 'key2'].sort #foo from before
369 @r.flushdb
29fac617 370 @r.keys('*').should == []
371 end
372 #
0df1ead7 373 it "should be able to provide the last save time (LASTSAVE)" do
374 savetime = @r.lastsave
29fac617 375 Time.at(savetime).class.should == Time
376 Time.at(savetime).should <= Time.now
377 end
378
379 it "should be able to MGET keys" do
380 @r['foo'] = 1000
381 @r['bar'] = 2000
382 @r.mget('foo', 'bar').should == ['1000', '2000']
383 @r.mget('foo', 'bar', 'baz').should == ['1000', '2000', nil]
384 end
385
386 it "should bgsave" do
0df1ead7 387 @r.bgsave.should == 'OK'
29fac617 388 end
389
390 it "should handle multiple servers" do
391 require 'dist_redis'
0df1ead7 392 @r = DistRedis.new(:hosts=> ['localhost:6379', '127.0.0.1:6379'], :db => 15)
29fac617 393
394 100.times do |idx|
395 @r[idx] = "foo#{idx}"
396 end
397
398 100.times do |idx|
399 @r[idx].should == "foo#{idx}"
400 end
401 end
402
57172ffb 403 it "should be able to pipeline writes" do
404 @r.pipelined do |pipeline|
0df1ead7 405 pipeline.lpush 'list', "hello"
406 pipeline.lpush 'list', 42
57172ffb 407 end
408
0df1ead7 409 @r.type('list').should == "list"
410 @r.llen('list').should == 2
411 @r.lpop('list').should == '42'
57172ffb 412 end
d7fc9edb 413
57172ffb 414end