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