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