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