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