]> git.saurik.com Git - redis.git/blob - tests/unit/basic.tcl
9d556594f538be412aa057c12276c85fceb6cfb9
[redis.git] / tests / unit / basic.tcl
1 start_server {tags {"basic"}} {
2 test {DEL all keys to start with a clean DB} {
3 foreach key [r keys *] {r del $key}
4 r dbsize
5 } {0}
6
7 test {SET and GET an item} {
8 r set x foobar
9 r get x
10 } {foobar}
11
12 test {SET and GET an empty item} {
13 r set x {}
14 r get x
15 } {}
16
17 test {DEL against a single item} {
18 r del x
19 r get x
20 } {}
21
22 test {Vararg DEL} {
23 r set foo1 a
24 r set foo2 b
25 r set foo3 c
26 list [r del foo1 foo2 foo3 foo4] [r mget foo1 foo2 foo3]
27 } {3 {{} {} {}}}
28
29 test {KEYS with pattern} {
30 foreach key {key_x key_y key_z foo_a foo_b foo_c} {
31 r set $key hello
32 }
33 lsort [r keys foo*]
34 } {foo_a foo_b foo_c}
35
36 test {KEYS to get all keys} {
37 lsort [r keys *]
38 } {foo_a foo_b foo_c key_x key_y key_z}
39
40 test {DBSIZE} {
41 r dbsize
42 } {6}
43
44 test {DEL all keys} {
45 foreach key [r keys *] {r del $key}
46 r dbsize
47 } {0}
48
49 test {Very big payload in GET/SET} {
50 set buf [string repeat "abcd" 1000000]
51 r set foo $buf
52 r get foo
53 } [string repeat "abcd" 1000000]
54
55 tags {"slow"} {
56 test {Very big payload random access} {
57 set err {}
58 array set payload {}
59 for {set j 0} {$j < 100} {incr j} {
60 set size [expr 1+[randomInt 100000]]
61 set buf [string repeat "pl-$j" $size]
62 set payload($j) $buf
63 r set bigpayload_$j $buf
64 }
65 for {set j 0} {$j < 1000} {incr j} {
66 set index [randomInt 100]
67 set buf [r get bigpayload_$index]
68 if {$buf != $payload($index)} {
69 set err "Values differ: I set '$payload($index)' but I read back '$buf'"
70 break
71 }
72 }
73 unset payload
74 set _ $err
75 } {}
76
77 test {SET 10000 numeric keys and access all them in reverse order} {
78 set err {}
79 for {set x 0} {$x < 10000} {incr x} {
80 r set $x $x
81 }
82 set sum 0
83 for {set x 9999} {$x >= 0} {incr x -1} {
84 set val [r get $x]
85 if {$val ne $x} {
86 set err "Eleemnt at position $x is $val instead of $x"
87 break
88 }
89 }
90 set _ $err
91 } {}
92
93 test {DBSIZE should be 10101 now} {
94 r dbsize
95 } {10101}
96 }
97
98 test {INCR against non existing key} {
99 set res {}
100 append res [r incr novar]
101 append res [r get novar]
102 } {11}
103
104 test {INCR against key created by incr itself} {
105 r incr novar
106 } {2}
107
108 test {INCR against key originally set with SET} {
109 r set novar 100
110 r incr novar
111 } {101}
112
113 test {INCR over 32bit value} {
114 r set novar 17179869184
115 r incr novar
116 } {17179869185}
117
118 test {INCRBY over 32bit value with over 32bit increment} {
119 r set novar 17179869184
120 r incrby novar 17179869184
121 } {34359738368}
122
123 test {INCR fails against key with spaces (no integer encoded)} {
124 r set novar " 11 "
125 catch {r incr novar} err
126 format $err
127 } {ERR*}
128
129 test {INCR fails against a key holding a list} {
130 r rpush mylist 1
131 catch {r incr mylist} err
132 r rpop mylist
133 format $err
134 } {ERR*}
135
136 test {DECRBY over 32bit value with over 32bit increment, negative res} {
137 r set novar 17179869184
138 r decrby novar 17179869185
139 } {-1}
140
141 test {INCRBYFLOAT against non existing key} {
142 r del novar
143 list [r incrbyfloat novar 1] [r get novar] [r incrbyfloat novar 0.25] \
144 [r get novar]
145 } {1 1 1.25 1.25}
146
147 test {INCRBYFLOAT against key originally set with SET} {
148 r set novar 1.5
149 r incrbyfloat novar 1.5
150 } {3}
151
152 test {INCRBYFLOAT over 32bit value} {
153 r set novar 17179869184
154 r incrbyfloat novar 1.5
155 } {17179869185.5}
156
157 test {INCRBYFLOAT over 32bit value with over 32bit increment} {
158 r set novar 17179869184
159 r incrbyfloat novar 17179869184
160 } {34359738368}
161
162 test {INCRBYFLOAT fails against key with spaces (left)} {
163 set err {}
164 r set novar " 11"
165 catch {r incrbyfloat novar 1.0} err
166 format $err
167 } {ERR*valid*}
168
169 test {INCRBYFLOAT fails against key with spaces (right)} {
170 set err {}
171 r set novar "11 "
172 catch {r incrbyfloat novar 1.0} err
173 format $err
174 } {ERR*valid*}
175
176 test {INCRBYFLOAT fails against key with spaces (both)} {
177 set err {}
178 r set novar " 11 "
179 catch {r incrbyfloat novar 1.0} err
180 format $err
181 } {ERR*valid*}
182
183 test {INCRBYFLOAT fails against a key holding a list} {
184 r del mylist
185 set err {}
186 r rpush mylist 1
187 catch {r incrbyfloat mylist 1.0} err
188 r del mylist
189 format $err
190 } {ERR*kind*}
191
192 test {INCRBYFLOAT does not allow NaN or Infinity} {
193 r set foo 0
194 set err {}
195 catch {r incrbyfloat foo +inf} err
196 set err
197 # p.s. no way I can force NaN to test it from the API because
198 # there is no way to increment / decrement by infinity nor to
199 # perform divisions.
200 } {ERR*would produce*}
201
202 test {INCRBYFLOAT decrement} {
203 r set foo 1
204 r incrbyfloat foo -1.256
205 } {-0.256}
206
207 test "SETNX target key missing" {
208 r del novar
209 assert_equal 1 [r setnx novar foobared]
210 assert_equal "foobared" [r get novar]
211 }
212
213 test "SETNX target key exists" {
214 r set novar foobared
215 assert_equal 0 [r setnx novar blabla]
216 assert_equal "foobared" [r get novar]
217 }
218
219 test "SETNX against not-expired volatile key" {
220 r set x 10
221 r expire x 10000
222 assert_equal 0 [r setnx x 20]
223 assert_equal 10 [r get x]
224 }
225
226 test "SETNX against expired volatile key" {
227 # Make it very unlikely for the key this test uses to be expired by the
228 # active expiry cycle. This is tightly coupled to the implementation of
229 # active expiry and dbAdd() but currently the only way to test that
230 # SETNX expires a key when it should have been.
231 for {set x 0} {$x < 9999} {incr x} {
232 r setex key-$x 3600 value
233 }
234
235 # This will be one of 10000 expiring keys. A cycle is executed every
236 # 100ms, sampling 10 keys for being expired or not. This key will be
237 # expired for at most 1s when we wait 2s, resulting in a total sample
238 # of 100 keys. The probability of the success of this test being a
239 # false positive is therefore approx. 1%.
240 r set x 10
241 r expire x 1
242
243 # Wait for the key to expire
244 after 2000
245
246 assert_equal 1 [r setnx x 20]
247 assert_equal 20 [r get x]
248 }
249
250 test {EXISTS} {
251 set res {}
252 r set newkey test
253 append res [r exists newkey]
254 r del newkey
255 append res [r exists newkey]
256 } {10}
257
258 test {Zero length value in key. SET/GET/EXISTS} {
259 r set emptykey {}
260 set res [r get emptykey]
261 append res [r exists emptykey]
262 r del emptykey
263 append res [r exists emptykey]
264 } {10}
265
266 test {Commands pipelining} {
267 set fd [r channel]
268 puts -nonewline $fd "SET k1 xyzk\r\nGET k1\r\nPING\r\n"
269 flush $fd
270 set res {}
271 append res [string match OK* [::redis::redis_read_reply $fd]]
272 append res [::redis::redis_read_reply $fd]
273 append res [string match PONG* [::redis::redis_read_reply $fd]]
274 format $res
275 } {1xyzk1}
276
277 test {Non existing command} {
278 catch {r foobaredcommand} err
279 string match ERR* $err
280 } {1}
281
282 test {RENAME basic usage} {
283 r set mykey hello
284 r rename mykey mykey1
285 r rename mykey1 mykey2
286 r get mykey2
287 } {hello}
288
289 test {RENAME source key should no longer exist} {
290 r exists mykey
291 } {0}
292
293 test {RENAME against already existing key} {
294 r set mykey a
295 r set mykey2 b
296 r rename mykey2 mykey
297 set res [r get mykey]
298 append res [r exists mykey2]
299 } {b0}
300
301 test {RENAMENX basic usage} {
302 r del mykey
303 r del mykey2
304 r set mykey foobar
305 r renamenx mykey mykey2
306 set res [r get mykey2]
307 append res [r exists mykey]
308 } {foobar0}
309
310 test {RENAMENX against already existing key} {
311 r set mykey foo
312 r set mykey2 bar
313 r renamenx mykey mykey2
314 } {0}
315
316 test {RENAMENX against already existing key (2)} {
317 set res [r get mykey]
318 append res [r get mykey2]
319 } {foobar}
320
321 test {RENAME against non existing source key} {
322 catch {r rename nokey foobar} err
323 format $err
324 } {ERR*}
325
326 test {RENAME where source and dest key is the same} {
327 catch {r rename mykey mykey} err
328 format $err
329 } {ERR*}
330
331 test {RENAME with volatile key, should move the TTL as well} {
332 r del mykey mykey2
333 r set mykey foo
334 r expire mykey 100
335 assert {[r ttl mykey] > 95 && [r ttl mykey] <= 100}
336 r rename mykey mykey2
337 assert {[r ttl mykey2] > 95 && [r ttl mykey2] <= 100}
338 }
339
340 test {RENAME with volatile key, should not inherit TTL of target key} {
341 r del mykey mykey2
342 r set mykey foo
343 r set mykey2 bar
344 r expire mykey2 100
345 assert {[r ttl mykey] == -1 && [r ttl mykey2] > 0}
346 r rename mykey mykey2
347 r ttl mykey2
348 } {-1}
349
350 test {DEL all keys again (DB 0)} {
351 foreach key [r keys *] {
352 r del $key
353 }
354 r dbsize
355 } {0}
356
357 test {DEL all keys again (DB 1)} {
358 r select 10
359 foreach key [r keys *] {
360 r del $key
361 }
362 set res [r dbsize]
363 r select 9
364 format $res
365 } {0}
366
367 test {MOVE basic usage} {
368 r set mykey foobar
369 r move mykey 10
370 set res {}
371 lappend res [r exists mykey]
372 lappend res [r dbsize]
373 r select 10
374 lappend res [r get mykey]
375 lappend res [r dbsize]
376 r select 9
377 format $res
378 } [list 0 0 foobar 1]
379
380 test {MOVE against key existing in the target DB} {
381 r set mykey hello
382 r move mykey 10
383 } {0}
384
385 test {SET/GET keys in different DBs} {
386 r set a hello
387 r set b world
388 r select 10
389 r set a foo
390 r set b bared
391 r select 9
392 set res {}
393 lappend res [r get a]
394 lappend res [r get b]
395 r select 10
396 lappend res [r get a]
397 lappend res [r get b]
398 r select 9
399 format $res
400 } {hello world foo bared}
401
402 test {MGET} {
403 r flushdb
404 r set foo BAR
405 r set bar FOO
406 r mget foo bar
407 } {BAR FOO}
408
409 test {MGET against non existing key} {
410 r mget foo baazz bar
411 } {BAR {} FOO}
412
413 test {MGET against non-string key} {
414 r sadd myset ciao
415 r sadd myset bau
416 r mget foo baazz bar myset
417 } {BAR {} FOO {}}
418
419 test {RANDOMKEY} {
420 r flushdb
421 r set foo x
422 r set bar y
423 set foo_seen 0
424 set bar_seen 0
425 for {set i 0} {$i < 100} {incr i} {
426 set rkey [r randomkey]
427 if {$rkey eq {foo}} {
428 set foo_seen 1
429 }
430 if {$rkey eq {bar}} {
431 set bar_seen 1
432 }
433 }
434 list $foo_seen $bar_seen
435 } {1 1}
436
437 test {RANDOMKEY against empty DB} {
438 r flushdb
439 r randomkey
440 } {}
441
442 test {RANDOMKEY regression 1} {
443 r flushdb
444 r set x 10
445 r del x
446 r randomkey
447 } {}
448
449 test {GETSET (set new value)} {
450 list [r getset foo xyz] [r get foo]
451 } {{} xyz}
452
453 test {GETSET (replace old value)} {
454 r set foo bar
455 list [r getset foo xyz] [r get foo]
456 } {bar xyz}
457
458 test {MSET base case} {
459 r mset x 10 y "foo bar" z "x x x x x x x\n\n\r\n"
460 r mget x y z
461 } [list 10 {foo bar} "x x x x x x x\n\n\r\n"]
462
463 test {MSET wrong number of args} {
464 catch {r mset x 10 y "foo bar" z} err
465 format $err
466 } {*wrong number*}
467
468 test {MSETNX with already existent key} {
469 list [r msetnx x1 xxx y2 yyy x 20] [r exists x1] [r exists y2]
470 } {0 0 0}
471
472 test {MSETNX with not existing keys} {
473 list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]
474 } {1 xxx yyy}
475
476 test "STRLEN against non-existing key" {
477 assert_equal 0 [r strlen notakey]
478 }
479
480 test "STRLEN against integer-encoded value" {
481 r set myinteger -555
482 assert_equal 4 [r strlen myinteger]
483 }
484
485 test "STRLEN against plain string" {
486 r set mystring "foozzz0123456789 baz"
487 assert_equal 20 [r strlen mystring]
488 }
489
490 test "SETBIT against non-existing key" {
491 r del mykey
492 assert_equal 0 [r setbit mykey 1 1]
493 assert_equal [binary format B* 01000000] [r get mykey]
494 }
495
496 test "SETBIT against string-encoded key" {
497 # Ascii "@" is integer 64 = 01 00 00 00
498 r set mykey "@"
499
500 assert_equal 0 [r setbit mykey 2 1]
501 assert_equal [binary format B* 01100000] [r get mykey]
502 assert_equal 1 [r setbit mykey 1 0]
503 assert_equal [binary format B* 00100000] [r get mykey]
504 }
505
506 test "SETBIT against integer-encoded key" {
507 # Ascii "1" is integer 49 = 00 11 00 01
508 r set mykey 1
509 assert_encoding int mykey
510
511 assert_equal 0 [r setbit mykey 6 1]
512 assert_equal [binary format B* 00110011] [r get mykey]
513 assert_equal 1 [r setbit mykey 2 0]
514 assert_equal [binary format B* 00010011] [r get mykey]
515 }
516
517 test "SETBIT against key with wrong type" {
518 r del mykey
519 r lpush mykey "foo"
520 assert_error "*wrong kind*" {r setbit mykey 0 1}
521 }
522
523 test "SETBIT with out of range bit offset" {
524 r del mykey
525 assert_error "*out of range*" {r setbit mykey [expr 4*1024*1024*1024] 1}
526 assert_error "*out of range*" {r setbit mykey -1 1}
527 }
528
529 test "SETBIT with non-bit argument" {
530 r del mykey
531 assert_error "*out of range*" {r setbit mykey 0 -1}
532 assert_error "*out of range*" {r setbit mykey 0 2}
533 assert_error "*out of range*" {r setbit mykey 0 10}
534 assert_error "*out of range*" {r setbit mykey 0 20}
535 }
536
537 test "SETBIT fuzzing" {
538 set str ""
539 set len [expr 256*8]
540 r del mykey
541
542 for {set i 0} {$i < 2000} {incr i} {
543 set bitnum [randomInt $len]
544 set bitval [randomInt 2]
545 set fmt [format "%%-%ds%%d%%-s" $bitnum]
546 set head [string range $str 0 $bitnum-1]
547 set tail [string range $str $bitnum+1 end]
548 set str [string map {" " 0} [format $fmt $head $bitval $tail]]
549
550 r setbit mykey $bitnum $bitval
551 assert_equal [binary format B* $str] [r get mykey]
552 }
553 }
554
555 test "GETBIT against non-existing key" {
556 r del mykey
557 assert_equal 0 [r getbit mykey 0]
558 }
559
560 test "GETBIT against string-encoded key" {
561 # Single byte with 2nd and 3rd bit set
562 r set mykey "`"
563
564 # In-range
565 assert_equal 0 [r getbit mykey 0]
566 assert_equal 1 [r getbit mykey 1]
567 assert_equal 1 [r getbit mykey 2]
568 assert_equal 0 [r getbit mykey 3]
569
570 # Out-range
571 assert_equal 0 [r getbit mykey 8]
572 assert_equal 0 [r getbit mykey 100]
573 assert_equal 0 [r getbit mykey 10000]
574 }
575
576 test "GETBIT against integer-encoded key" {
577 r set mykey 1
578 assert_encoding int mykey
579
580 # Ascii "1" is integer 49 = 00 11 00 01
581 assert_equal 0 [r getbit mykey 0]
582 assert_equal 0 [r getbit mykey 1]
583 assert_equal 1 [r getbit mykey 2]
584 assert_equal 1 [r getbit mykey 3]
585
586 # Out-range
587 assert_equal 0 [r getbit mykey 8]
588 assert_equal 0 [r getbit mykey 100]
589 assert_equal 0 [r getbit mykey 10000]
590 }
591
592 test "SETRANGE against non-existing key" {
593 r del mykey
594 assert_equal 3 [r setrange mykey 0 foo]
595 assert_equal "foo" [r get mykey]
596
597 r del mykey
598 assert_equal 0 [r setrange mykey 0 ""]
599 assert_equal 0 [r exists mykey]
600
601 r del mykey
602 assert_equal 4 [r setrange mykey 1 foo]
603 assert_equal "\000foo" [r get mykey]
604 }
605
606 test "SETRANGE against string-encoded key" {
607 r set mykey "foo"
608 assert_equal 3 [r setrange mykey 0 b]
609 assert_equal "boo" [r get mykey]
610
611 r set mykey "foo"
612 assert_equal 3 [r setrange mykey 0 ""]
613 assert_equal "foo" [r get mykey]
614
615 r set mykey "foo"
616 assert_equal 3 [r setrange mykey 1 b]
617 assert_equal "fbo" [r get mykey]
618
619 r set mykey "foo"
620 assert_equal 7 [r setrange mykey 4 bar]
621 assert_equal "foo\000bar" [r get mykey]
622 }
623
624 test "SETRANGE against integer-encoded key" {
625 r set mykey 1234
626 assert_encoding int mykey
627 assert_equal 4 [r setrange mykey 0 2]
628 assert_encoding raw mykey
629 assert_equal 2234 [r get mykey]
630
631 # Shouldn't change encoding when nothing is set
632 r set mykey 1234
633 assert_encoding int mykey
634 assert_equal 4 [r setrange mykey 0 ""]
635 assert_encoding int mykey
636 assert_equal 1234 [r get mykey]
637
638 r set mykey 1234
639 assert_encoding int mykey
640 assert_equal 4 [r setrange mykey 1 3]
641 assert_encoding raw mykey
642 assert_equal 1334 [r get mykey]
643
644 r set mykey 1234
645 assert_encoding int mykey
646 assert_equal 6 [r setrange mykey 5 2]
647 assert_encoding raw mykey
648 assert_equal "1234\0002" [r get mykey]
649 }
650
651 test "SETRANGE against key with wrong type" {
652 r del mykey
653 r lpush mykey "foo"
654 assert_error "*wrong kind*" {r setrange mykey 0 bar}
655 }
656
657 test "SETRANGE with out of range offset" {
658 r del mykey
659 assert_error "*maximum allowed size*" {r setrange mykey [expr 512*1024*1024-4] world}
660
661 r set mykey "hello"
662 assert_error "*out of range*" {r setrange mykey -1 world}
663 assert_error "*maximum allowed size*" {r setrange mykey [expr 512*1024*1024-4] world}
664 }
665
666 test "GETRANGE against non-existing key" {
667 r del mykey
668 assert_equal "" [r getrange mykey 0 -1]
669 }
670
671 test "GETRANGE against string value" {
672 r set mykey "Hello World"
673 assert_equal "Hell" [r getrange mykey 0 3]
674 assert_equal "Hello World" [r getrange mykey 0 -1]
675 assert_equal "orld" [r getrange mykey -4 -1]
676 assert_equal "" [r getrange mykey 5 3]
677 assert_equal " World" [r getrange mykey 5 5000]
678 assert_equal "Hello World" [r getrange mykey -5000 10000]
679 }
680
681 test "GETRANGE against integer-encoded value" {
682 r set mykey 1234
683 assert_equal "123" [r getrange mykey 0 2]
684 assert_equal "1234" [r getrange mykey 0 -1]
685 assert_equal "234" [r getrange mykey -3 -1]
686 assert_equal "" [r getrange mykey 5 3]
687 assert_equal "4" [r getrange mykey 3 5000]
688 assert_equal "1234" [r getrange mykey -5000 10000]
689 }
690
691 test "GETRANGE fuzzing" {
692 for {set i 0} {$i < 1000} {incr i} {
693 r set bin [set bin [randstring 0 1024 binary]]
694 set _start [set start [randomInt 1500]]
695 set _end [set end [randomInt 1500]]
696 if {$_start < 0} {set _start "end-[abs($_start)-1]"}
697 if {$_end < 0} {set _end "end-[abs($_end)-1]"}
698 assert_equal [string range $bin $_start $_end] [r getrange bin $start $end]
699 }
700 }
701 }