2 # Redis test suite. Copyright (C) 2009 Salvatore Sanfilippo antirez@gmail.com 
   3 # This softare is released under the BSD License. See the COPYING file for 
  13 proc test 
{name code okpattern
} { 
  15     if {$::testnum < $::first || 
$::testnum > $::last} return 
  16     puts -nonewline [format "%-70s " "#$::testnum $name"] 
  18     set retval 
[uplevel 1 $code] 
  19     if {$okpattern eq 
$retval || 
[string match 
$okpattern $retval]} { 
  23         puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'" 
  28 proc randstring 
{min max 
{type 
binary}} { 
  29     set len 
[expr {$min+int
(rand
()*($max-$min+1))}] 
  31     if {$type eq 
{binary}} { 
  34     } elseif 
{$type eq 
{alpha
}} { 
  37     } elseif 
{$type eq 
{compr
}} { 
  42         append output 
[format "%c" [expr {$minval+int
(rand
()*($maxval-$minval+1))}]] 
  48 # Useful for some test 
  49 proc zlistAlikeSort 
{a b
} { 
  50     if {[lindex $a 0] > [lindex $b 0]} {return 1} 
  51     if {[lindex $a 0] < [lindex $b 0]} {return -1} 
  52     string compare 
[lindex $a 1] [lindex $b 1] 
  55 proc waitForBgsave r 
{ 
  58         if {[string match 
{*bgsave_in_progress
:1*} $i]} { 
  59             puts -nonewline "\nWaiting for background save to finish... " 
  68 proc waitForBgrewriteaof r 
{ 
  71         if {[string match 
{*bgrewriteaof_in_progress
:1*} $i]} { 
  72             puts -nonewline "\nWaiting for background AOF rewrite to finish... " 
  81 proc randomInt 
{max
} { 
  82     expr {int
(rand
()*$max)} 
  86     set path 
[expr {int
(rand
()*[llength $args])}] 
  87     uplevel 1 [lindex $args $path] 
  92         # Small enough to likely collide 
  95         # 32 bit compressible signed/unsigned 
  96         randpath 
{randomInt 
2000000000} {randomInt 
4000000000} 
  99         randpath 
{randomInt 
1000000000000} 
 102         randpath 
{randstring 
0 256 alpha
} \ 
 103                 {randstring 
0 256 compr
} \ 
 104                 {randstring 
0 256 binary} 
 110         # Small enough to likely collide 
 113         # 32 bit compressible signed/unsigned 
 114         randpath 
{randomInt 
2000000000} {randomInt 
4000000000} 
 117         randpath 
{randomInt 
1000000000000} 
 120         randpath 
{randstring 
1 256 alpha
} \ 
 121                 {randstring 
1 256 compr
} 
 125 proc createComplexDataset 
{r ops
} { 
 126     for {set j 
0} {$j < $ops} {incr j
} { 
 130             set d 
[expr {rand
()}] 
 132             set d 
[expr {rand
()}] 
 134             set d 
[expr {rand
()}] 
 136             set d 
[expr {rand
()}] 
 138             set d 
[expr {rand
()}] 
 140             randpath 
{set d 
+inf
} {set d 
-inf} 
 162                 randpath 
{$r lpush 
$k $v} \ 
 169                 randpath 
{$r sadd 
$k $v} \ 
 173                 randpath 
{$r zadd 
$k $d $v} \ 
 180 proc datasetDigest r 
{ 
 181     set keys 
[lsort [split [$r keys 
*] " "]] 
 187                 set aux 
[::sha1::sha1 -hex [$r get 
$k]] 
 189                 if {[$r llen 
$k] == 0} { 
 192                     set aux 
[::sha1::sha1 -hex [$r lrange $k 0 -1]] 
 195                 if {[$r scard 
$k] == 0} { 
 198                     set aux 
[::sha1::sha1 -hex [lsort [$r smembers 
$k]]] 
 201                 if {[$r zcard 
$k] == 0} { 
 204                     set aux 
[::sha1::sha1 -hex [$r zrange 
$k 0 -1]] 
 207                 error "Type not supported" 
 210         if {$aux eq 
{}} continue 
 211         set digest 
[::sha1::sha1 -hex [join [list $aux $digest $k] "\n"]] 
 216 proc main 
{server port
} { 
 217     set r 
[redis 
$server $port] 
 222     # The following AUTH test should be enabled only when requirepass 
 223     # <PASSWORD> is set in redis.conf and redis-server was started with 
 224     # redis.conf as the first argument.   
 226     #test {AUTH with requirepass in redis.conf} { 
 230     test 
{DEL all keys to start with a clean DB
} { 
 231         foreach key 
[$r keys 
*] {$r del 
$key} 
 235     test 
{SET and GET an item
} { 
 240     test 
{SET and GET an empty item
} { 
 245     test 
{DEL against a single item
} { 
 254         list [$r del foo1 foo2 foo3 foo4
] [$r mget foo1 foo2 foo3
] 
 257     test 
{KEYS with pattern
} { 
 258         foreach key 
{key_x key_y key_z foo_a foo_b foo_c
} { 
 262     } {foo_a foo_b foo_c
} 
 264     test 
{KEYS to get all keys
} { 
 266     } {foo_a foo_b foo_c key_x key_y key_z
} 
 272     test 
{DEL all keys
} { 
 273         foreach key 
[$r keys 
*] {$r del 
$key} 
 277     test 
{Very big payload in GET
/SET
} { 
 278         set buf 
[string repeat 
"abcd" 1000000] 
 281     } [string repeat 
"abcd" 1000000] 
 283     test 
{SET 
10000 numeric keys and access all them in reverse order
} { 
 285         for {set x 
0} {$x < 10000} {incr x
} { 
 289         for {set x 
9999} {$x >= 0} {incr x 
-1} { 
 292                 set err 
"Eleemnt at position $x is $val instead of $x" 
 299     test 
{DBSIZE should be 
10001 now
} { 
 303     test 
{INCR against non existing key
} { 
 305         append res 
[$r incr novar
] 
 306         append res 
[$r get novar
] 
 309     test 
{INCR against key created by 
incr itself
} { 
 313     test 
{INCR against key originally 
set with SET
} { 
 318     test 
{INCR over 
32bit value
} { 
 319         $r set novar 
17179869184 
 323     test 
{INCRBY over 
32bit value with over 
32bit increment
} { 
 324         $r set novar 
17179869184 
 325         $r incrby novar 
17179869184 
 328     test 
{INCR against key with spaces 
(no integer encoded
)} { 
 333     test 
{DECRBY over 
32bit value with over 
32bit increment
, negative res
} { 
 334         $r set novar 
17179869184 
 335         $r decrby novar 
17179869185 
 338     test 
{SETNX target key missing
} { 
 339         $r setnx novar2 foobared
 
 343     test 
{SETNX target key exists
} { 
 344         $r setnx novar2 blabla
 
 348     test 
{SETNX will overwrite EXPIREing key
} { 
 358         append res 
[$r exists newkey
] 
 360         append res 
[$r exists newkey
] 
 363     test 
{Zero length value in key. SET
/GET
/EXISTS
} { 
 365         set res 
[$r get emptykey
] 
 366         append res 
[$r exists emptykey
] 
 368         append res 
[$r exists emptykey
] 
 371     test 
{Commands pipelining
} { 
 373         puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n" 
 376         append res 
[string match OK
* [::redis::redis_read_reply $fd]] 
 377         append res 
[::redis::redis_read_reply $fd] 
 378         append res 
[string match PONG
* [::redis::redis_read_reply $fd]] 
 382     test 
{Non existing command
} { 
 383         catch {$r foobaredcommand
} err
 
 384         string match ERR
* $err 
 387     test 
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} { 
 391         set res 
[$r llen mylist
] 
 392         append res 
[$r lindex mylist 
0] 
 393         append res 
[$r lindex mylist 
1] 
 394         append res 
[$r lindex mylist 
2] 
 395         list $res [$r lindex mylist 
100] 
 403     test 
{Create a long 
list and check every single element with LINDEX
} { 
 405         for {set i 
0} {$i < 1000} {incr i
} { 
 408         for {set i 
0} {$i < 1000} {incr i
} { 
 409             if {[$r lindex mylist 
$i] eq 
$i} {incr ok
} 
 410             if {[$r lindex mylist 
[expr (-$i)-1]] eq 
[expr 999-$i]} { 
 417     test 
{Test elements with LINDEX in random access
} { 
 419         for {set i 
0} {$i < 1000} {incr i
} { 
 420             set rint 
[expr int
(rand
()*1000)] 
 421             if {[$r lindex mylist 
$rint] eq 
$rint} {incr ok
} 
 422             if {[$r lindex mylist 
[expr (-$rint)-1]] eq 
[expr 999-$rint]} { 
 429     test 
{Check 
if the 
list is still ok 
after a DEBUG RELOAD
} { 
 432         for {set i 
0} {$i < 1000} {incr i
} { 
 433             set rint 
[expr int
(rand
()*1000)] 
 434             if {[$r lindex mylist 
$rint] eq 
$rint} {incr ok
} 
 435             if {[$r lindex mylist 
[expr (-$rint)-1]] eq 
[expr 999-$rint]} { 
 442     test 
{LLEN against non-list value 
error} { 
 445         catch {$r llen mylist
} err
 
 449     test 
{LLEN against non existing key
} { 
 453     test 
{LINDEX against non-list value 
error} { 
 454         catch {$r lindex mylist 
0} err
 
 458     test 
{LINDEX against non existing key
} { 
 459         $r lindex not-a-key 
10 
 462     test 
{LPUSH against non-list value 
error} { 
 463         catch {$r lpush mylist 
0} err
 
 467     test 
{RPUSH against non-list value 
error} { 
 468         catch {$r rpush mylist 
0} err
 
 472     test 
{RPOPLPUSH base case
} { 
 478         set v1 
[$r rpoplpush mylist newlist
] 
 479         set v2 
[$r rpoplpush mylist newlist
] 
 480         set l1 
[$r lrange mylist 
0 -1] 
 481         set l2 
[$r lrange newlist 
0 -1] 
 485     test 
{RPOPLPUSH with the same 
list as src and dst
} { 
 490         set l1 
[$r lrange mylist 
0 -1] 
 491         set v 
[$r rpoplpush mylist mylist
] 
 492         set l2 
[$r lrange mylist 
0 -1] 
 494     } {{a b c
} c 
{c a b
}} 
 496     test 
{RPOPLPUSH target 
list already exists
} { 
 504         set v1 
[$r rpoplpush mylist newlist
] 
 505         set v2 
[$r rpoplpush mylist newlist
] 
 506         set l1 
[$r lrange mylist 
0 -1] 
 507         set l2 
[$r lrange newlist 
0 -1] 
 509     } {d c 
{a b
} {c d x
}} 
 511     test 
{RPOPLPUSH against non existing key
} { 
 514         set v1 
[$r rpoplpush mylist newlist
] 
 515         list $v1 [$r exists mylist
] [$r exists newlist
] 
 518     test 
{RPOPLPUSH against non 
list src key
} { 
 522         catch {$r rpoplpush mylist newlist
} err
 
 523         list [$r type mylist
] [$r exists newlist
] [string range 
$err 0 2] 
 526     test 
{RPOPLPUSH against non 
list dst key
} { 
 534         catch {$r rpoplpush mylist newlist
} err
 
 535         list [$r lrange mylist 
0 -1] [$r type newlist
] [string range 
$err 0 2] 
 536     } {{a b c d
} string ERR
} 
 538     test 
{RPOPLPUSH against non existing src key
} { 
 541         $r rpoplpush mylist newlist
 
 544     test 
{RENAME basic usage
} { 
 546         $r rename mykey mykey1
 
 547         $r rename mykey1 mykey2
 
 551     test 
{RENAME 
source key should no longer exist
} { 
 555     test 
{RENAME against already existing key
} { 
 558         $r rename mykey2 mykey
 
 559         set res 
[$r get mykey
] 
 560         append res 
[$r exists mykey2
] 
 563     test 
{RENAMENX basic usage
} { 
 567         $r renamenx mykey mykey2
 
 568         set res 
[$r get mykey2
] 
 569         append res 
[$r exists mykey
] 
 572     test 
{RENAMENX against already existing key
} { 
 575         $r renamenx mykey mykey2
 
 578     test 
{RENAMENX against already existing key 
(2)} { 
 579         set res 
[$r get mykey
] 
 580         append res 
[$r get mykey2
] 
 583     test 
{RENAME against non existing 
source key
} { 
 584         catch {$r rename nokey foobar
} err
 
 588     test 
{RENAME where 
source and dest key is the same
} { 
 589         catch {$r rename mykey mykey
} err
 
 593     test 
{DEL all keys again 
(DB 
0)} { 
 594         foreach key 
[$r keys 
*] { 
 600     test 
{DEL all keys again 
(DB 
1)} { 
 602         foreach key 
[$r keys 
*] { 
 610     test 
{MOVE basic usage
} { 
 614         lappend res 
[$r exists mykey
] 
 615         lappend res 
[$r dbsize
] 
 617         lappend res 
[$r get mykey
] 
 618         lappend res 
[$r dbsize
] 
 621     } [list 0 0 foobar 
1] 
 623     test 
{MOVE against key existing in the target DB
} { 
 628     test 
{SET
/GET keys in different DBs
} { 
 636         lappend res 
[$r get a
] 
 637         lappend res 
[$r get b
] 
 639         lappend res 
[$r get a
] 
 640         lappend res 
[$r get b
] 
 643     } {hello world foo bared
} 
 645     test 
{Basic LPOP
/RPOP
} { 
 650         list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
] 
 653     test 
{LPOP
/RPOP against empty 
list} { 
 657     test 
{LPOP against non 
list value
} { 
 659         catch {$r lpop notalist
} err
 
 663     test 
{Mass LPUSH
/LPOP
} { 
 665         for {set i 
0} {$i < 1000} {incr i
} { 
 670         for {set i 
0} {$i < 500} {incr i
} { 
 671             incr sum2 
[$r lpop mylist
] 
 672             incr sum2 
[$r rpop mylist
] 
 677     test 
{LRANGE basics
} { 
 678         for {set i 
0} {$i < 10} {incr i
} { 
 681         list [$r lrange mylist 
1 -2] \ 
 682                 [$r lrange mylist 
-3 -1] \ 
 683                 [$r lrange mylist 
4 4] 
 684     } {{1 2 3 4 5 6 7 8} {7 8 9} 4} 
 686     test 
{LRANGE inverted indexes
} { 
 690     test 
{LRANGE out of range indexes including the full 
list} { 
 691         $r lrange mylist 
-1000 1000 
 692     } {0 1 2 3 4 5 6 7 8 9} 
 694     test 
{LRANGE against non existing key
} { 
 695         $r lrange nosuchkey 
0 1 
 698     test 
{LTRIM basics
} { 
 700         for {set i 
0} {$i < 100} {incr i
} { 
 704         $r lrange mylist 
0 -1 
 707     test 
{LTRIM stress testing
} { 
 710         for {set i 
0} {$i < 20} {incr i
} { 
 714         for {set j 
0} {$j < 100} {incr j
} { 
 717             for {set i 
0} {$i < 20} {incr i
} { 
 723             $r ltrim mylist 
$a $b 
 724             if {[$r lrange mylist 
0 -1] ne 
[lrange $mylist $a $b]} { 
 725                 set err 
"[$r lrange mylist 0 -1] != [lrange $mylist $a $b]" 
 734         foreach x 
{99 98 97 96 95} { 
 738         $r lset mylist 
-1 bar
 
 739         $r lrange mylist 
0 -1 
 742     test 
{LSET out of range index
} { 
 743         catch {$r lset mylist 
10 foo
} err
 
 747     test 
{LSET against non existing key
} { 
 748         catch {$r lset nosuchkey 
10 foo
} err
 
 752     test 
{LSET against non 
list value
} { 
 754         catch {$r lset nolist 
0 foo
} err
 
 758     test 
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} { 
 761         list [$r scard myset
] [$r sismember myset foo
] \ 
 762             [$r sismember myset bar
] [$r sismember myset bla
] \ 
 763             [lsort [$r smembers myset
]] 
 764     } {2 1 1 0 {bar foo
}} 
 766     test 
{SADD adding the same element multiple times
} { 
 773     test 
{SADD against non 
set} { 
 774         catch {$r sadd mylist foo
} err
 
 781         lsort [$r smembers myset
] 
 784     test 
{Mass SADD and SINTER with two sets
} { 
 785         for {set i 
0} {$i < 1000} {incr i
} { 
 787             $r sadd set2 
[expr $i+995] 
 789         lsort [$r sinter set1 set2
] 
 790     } {995 996 997 998 999} 
 792     test 
{SUNION with two sets
} { 
 793         lsort [$r sunion set1 set2
] 
 794     } [lsort -uniq "[$r smembers set1] [$r smembers set2]"] 
 796     test 
{SINTERSTORE with two sets
} { 
 797         $r sinterstore setres set1 set2
 
 798         lsort [$r smembers setres
] 
 799     } {995 996 997 998 999} 
 801     test 
{SINTERSTORE with two sets
, after a DEBUG RELOAD
} { 
 803         $r sinterstore setres set1 set2
 
 804         lsort [$r smembers setres
] 
 805     } {995 996 997 998 999} 
 807     test 
{SUNIONSTORE with two sets
} { 
 808         $r sunionstore setres set1 set2
 
 809         lsort [$r smembers setres
] 
 810     } [lsort -uniq "[$r smembers set1] [$r smembers set2]"] 
 812     test 
{SUNIONSTORE against non existing keys
} { 
 814         list [$r sunionstore setres foo111 bar222
] [$r exists xxx
] 
 817     test 
{SINTER against three sets
} { 
 822         lsort [$r sinter set1 set2 set3
] 
 825     test 
{SINTERSTORE with three sets
} { 
 826         $r sinterstore setres set1 set2 set3
 
 827         lsort [$r smembers setres
] 
 830     test 
{SUNION with non existing keys
} { 
 831         lsort [$r sunion nokey1 set1 set2 nokey2
] 
 832     } [lsort -uniq "[$r smembers set1] [$r smembers set2]"] 
 834     test 
{SDIFF with two sets
} { 
 835         for {set i 
5} {$i < 1000} {incr i
} { 
 838         lsort [$r sdiff set1 set4
] 
 841     test 
{SDIFF with three sets
} { 
 843         lsort [$r sdiff set1 set4 set5
] 
 846     test 
{SDIFFSTORE with three sets
} { 
 847         $r sdiffstore sres set1 set4 set5
 
 848         lsort [$r smembers sres
] 
 856         list [lsort [list [$r spop myset
] [$r spop myset
] [$r spop myset
]]] [$r scard myset
] 
 859     test 
{SAVE 
- make sure there are all the types as values
} { 
 860         # Wait for a background saving in progress to terminate 
 862         $r lpush mysavelist hello
 
 863         $r lpush mysavelist world
 
 865         $r set mynormalkey 
{blablablba
} 
 866         $r zadd mytestzset a 
10 
 867         $r zadd mytestzset b 
20 
 868         $r zadd mytestzset c 
30 
 877         unset -nocomplain myset
 
 879         for {set i 
0} {$i < 100} {incr i
} { 
 880             set myset
([$r srandmember myset
]) 1 
 882         lsort [array names myset
] 
 885     test 
{Create a random 
list and a random 
set} { 
 887         array set seenrand 
{} 
 888         for {set i 
0} {$i < 10000} {incr i
} { 
 890                 # Make sure all the weights are different because 
 891                 # Redis does not use a stable sort but Tcl does. 
 893                     set rint 
[expr int
(rand
()*1000000)] 
 895                     set rint 
[expr rand
()] 
 897                 if {![info exists seenrand
($rint)]} break 
 899             set seenrand
($rint) x
 
 901             $r sadd tosort-set 
$i 
 902             $r set weight_
$i $rint 
 903             lappend tosort 
[list $i $rint] 
 905         set sorted 
[lsort -index 1 -real $tosort] 
 907         for {set i 
0} {$i < 10000} {incr i
} { 
 908             lappend res 
[lindex $sorted $i 0] 
 913     test 
{SORT with BY against the newly created 
list} { 
 914         $r sort tosort 
{BY weight_
*} 
 917     test 
{the same SORT with BY
, but against the newly created 
set} { 
 918         $r sort tosort-set 
{BY weight_
*} 
 921     test 
{SORT with BY and STORE against the newly created 
list} { 
 922         $r sort tosort 
{BY weight_
*} store sort-res
 
 923         $r lrange sort-res 
0 -1 
 926     test 
{SORT direct
, numeric
, against the newly created 
list} { 
 928     } [lsort -integer $res] 
 930     test 
{SORT decreasing sort
} { 
 931         $r sort tosort 
{DESC
} 
 932     } [lsort -decreasing -integer $res] 
 934     test 
{SORT speed
, sorting 
10000 elements 
list using BY
, 100 times
} { 
 935         set start 
[clock clicks 
-milliseconds] 
 936         for {set i 
0} {$i < 100} {incr i
} { 
 937             set sorted 
[$r sort tosort 
{BY weight_
* LIMIT 
0 10}] 
 939         set elapsed 
[expr [clock clicks 
-milliseconds]-$start] 
 940         puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds " 
 945     test 
{SORT speed
, sorting 
10000 elements 
list directly
, 100 times
} { 
 946         set start 
[clock clicks 
-milliseconds] 
 947         for {set i 
0} {$i < 100} {incr i
} { 
 948             set sorted 
[$r sort tosort 
{LIMIT 
0 10}] 
 950         set elapsed 
[expr [clock clicks 
-milliseconds]-$start] 
 951         puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds " 
 956     test 
{SORT speed
, pseudo-sorting 
10000 elements 
list, BY 
<const
>, 100 times
} { 
 957         set start 
[clock clicks 
-milliseconds] 
 958         for {set i 
0} {$i < 100} {incr i
} { 
 959             set sorted 
[$r sort tosort 
{BY nokey LIMIT 
0 10}] 
 961         set elapsed 
[expr [clock clicks 
-milliseconds]-$start] 
 962         puts -nonewline "\n  Average time to sort: [expr double($elapsed)/100] milliseconds " 
 967     test 
{SORT regression 
for issue 
#19, sorting floats} { 
 969         foreach x 
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} { 
 973     } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}] 
 975     test 
{SORT with GET 
#} { 
 980         $r mset weight_1 
10 weight_2 
5 weight_3 
30 
 981         $r sort mylist BY weight_
* GET 
# 
 984     test 
{SORT with constant GET
} { 
 985         $r sort mylist GET foo
 
 988     test 
{LREM
, remove all the occurrences
} { 
 992         $r rpush mylist foobar
 
 993         $r rpush mylist foobared
 
 998         set res 
[$r lrem mylist 
0 bar
] 
 999         list [$r lrange mylist 
0 -1] $res 
1000     } {{foo foobar foobared zap test foo
} 2} 
1002     test 
{LREM
, remove the first occurrence
} { 
1003         set res 
[$r lrem mylist 
1 foo
] 
1004         list [$r lrange mylist 
0 -1] $res 
1005     } {{foobar foobared zap test foo
} 1} 
1007     test 
{LREM
, remove non existing element
} { 
1008         set res 
[$r lrem mylist 
1 nosuchelement
] 
1009         list [$r lrange mylist 
0 -1] $res 
1010     } {{foobar foobared zap test foo
} 0} 
1012     test 
{LREM
, starting from tail with negative count
} { 
1016         $r rpush mylist foobar
 
1017         $r rpush mylist foobared
 
1020         $r rpush mylist test
 
1023         set res 
[$r lrem mylist 
-1 bar
] 
1024         list [$r lrange mylist 
0 -1] $res 
1025     } {{foo bar foobar foobared zap test foo foo
} 1} 
1027     test 
{LREM
, starting from tail with negative count 
(2)} { 
1028         set res 
[$r lrem mylist 
-2 foo
] 
1029         list [$r lrange mylist 
0 -1] $res 
1030     } {{foo bar foobar foobared zap test
} 2} 
1032     test 
{LREM
, deleting objects that may be encoded as integers
} { 
1033         $r lpush myotherlist 
1 
1034         $r lpush myotherlist 
2 
1035         $r lpush myotherlist 
3 
1036         $r lrem myotherlist 
1 2 
1047     test 
{MGET against non existing key
} { 
1048         $r mget foo baazz bar
 
1051     test 
{MGET against non-string key
} { 
1054         $r mget foo baazz bar myset
 
1063         for {set i 
0} {$i < 100} {incr i
} { 
1064             set rkey 
[$r randomkey
] 
1065             if {$rkey eq 
{foo
}} { 
1068             if {$rkey eq 
{bar
}} { 
1072         list $foo_seen $bar_seen 
1075     test 
{RANDOMKEY against empty DB
} { 
1080     test 
{RANDOMKEY regression 
1} { 
1087     test 
{GETSET 
(set new value
)} { 
1088         list [$r getset foo xyz
] [$r get foo
] 
1091     test 
{GETSET 
(replace old value
)} { 
1093         list [$r getset foo xyz
] [$r get foo
] 
1096     test 
{SMOVE basics
} { 
1103         $r smove myset1 myset2 a
 
1104         list [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]] 
1107     test 
{SMOVE non existing key
} { 
1108         list [$r smove myset1 myset2 foo
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]] 
1109     } {0 {a x y z
} {b c
}} 
1111     test 
{SMOVE non existing src 
set} { 
1112         list [$r smove noset myset2 foo
] [lsort [$r smembers myset2
]] 
1115     test 
{SMOVE non existing dst 
set} { 
1116         list [$r smove myset2 myset3 y
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset3
]] 
1119     test 
{SMOVE wrong src key type
} { 
1121         catch {$r smove x myset2 foo
} err
 
1125     test 
{SMOVE wrong dst key type
} { 
1127         catch {$r smove myset2 x foo
} err
 
1131     test 
{MSET base case
} { 
1132         $r mset x 
10 y 
"foo bar" z 
"x x x x x x x\n\n\r\n" 
1134     } [list 10 {foo bar
} "x x x x x x x\n\n\r\n"] 
1136     test 
{MSET wrong number of args
} { 
1137         catch {$r mset x 
10 y 
"foo bar" z
} err
 
1141     test 
{MSETNX with already existent key
} { 
1142         list [$r msetnx x1 xxx y2 yyy x 
20] [$r exists x1
] [$r exists y2
] 
1145     test 
{MSETNX with not existing keys
} { 
1146         list [$r msetnx x1 xxx y2 yyy
] [$r get x1
] [$r get y2
] 
1149     test 
{MSETNX should remove all the volatile keys even on 
failure} { 
1153         list [$r msetnx x A y B z C
] [$r mget x y z
] 
1156     test 
{ZSET basic ZADD and score 
update} { 
1160         set aux1 
[$r zrange ztmp 
0 -1] 
1162         set aux2 
[$r zrange ztmp 
0 -1] 
1166     test 
{ZCARD basics
} { 
1170     test 
{ZCARD non existing key
} { 
1171         $r zcard ztmp-blabla
 
1177         for {set i 
0} {$i < 1000} {incr i
} { 
1178             set score 
[expr rand
()] 
1180             $r zadd zscoretest 
$score $i 
1182         for {set i 
0} {$i < 1000} {incr i
} { 
1183             if {[$r zscore zscoretest 
$i] != [lindex $aux $i]} { 
1184                 set err 
"Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i" 
1191     test 
{ZSCORE 
after a DEBUG RELOAD
} { 
1195         for {set i 
0} {$i < 1000} {incr i
} { 
1196             set score 
[expr rand
()] 
1198             $r zadd zscoretest 
$score $i 
1201         for {set i 
0} {$i < 1000} {incr i
} { 
1202             if {[$r zscore zscoretest 
$i] != [lindex $aux $i]} { 
1203                 set err 
"Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i" 
1210     test 
{ZRANGE and ZREVRANGE basics
} { 
1211         list [$r zrange ztmp 
0 -1] [$r zrevrange ztmp 
0 -1] \ 
1212             [$r zrange ztmp 
1 -1] [$r zrevrange ztmp 
1 -1] 
1213     } {{y x z
} {z x y
} {x z
} {x y
}} 
1215     test 
{ZRANGE WITHSCORES
} { 
1216         $r zrange ztmp 
0 -1 withscores
 
1219     test 
{ZSETs stress tester 
- sorting is working well?
} { 
1221         for {set test 
0} {$test < 2} {incr test
} { 
1222             unset -nocomplain auxarray
 
1223             array set auxarray 
{} 
1226             for {set i 
0} {$i < 1000} {incr i
} { 
1228                     set score 
[expr rand
()] 
1230                     set score 
[expr int
(rand
()*10)] 
1232                 set auxarray
($i) $score 
1233                 $r zadd myzset 
$score $i 
1235                 if {[expr rand
()] < .2} { 
1236                     set j 
[expr int
(rand
()*1000)] 
1238                         set score 
[expr rand
()] 
1240                         set score 
[expr int
(rand
()*10)] 
1242                     set auxarray
($j) $score 
1243                     $r zadd myzset 
$score $j 
1246             foreach {item score
} [array get auxarray
] { 
1247                 lappend auxlist 
[list $score $item] 
1249             set sorted 
[lsort -command zlistAlikeSort 
$auxlist] 
1252                 lappend auxlist 
[lindex $x 1] 
1254             set fromredis 
[$r zrange myzset 
0 -1] 
1256             for {set i 
0} {$i < [llength $fromredis]} {incr i
} { 
1257                 if {[lindex $fromredis $i] != [lindex $auxlist $i]} { 
1265     test 
{ZINCRBY 
- can create a new sorted 
set} { 
1267         $r zincrby zset 
1 foo
 
1268         list [$r zrange zset 
0 -1] [$r zscore zset foo
] 
1271     test 
{ZINCRBY 
- increment and decrement
} { 
1272         $r zincrby zset 
2 foo
 
1273         $r zincrby zset 
1 bar
 
1274         set v1 
[$r zrange zset 
0 -1] 
1275         $r zincrby zset 
10 bar
 
1276         $r zincrby zset 
-5 foo
 
1277         $r zincrby zset 
-5 bar
 
1278         set v2 
[$r zrange zset 
0 -1] 
1279         list $v1 $v2 [$r zscore zset foo
] [$r zscore zset bar
] 
1280     } {{bar foo
} {foo bar
} -2 6} 
1282     test 
{ZRANGEBYSCORE basics
} { 
1289         $r zrangebyscore zset 
2 4 
1292     test 
{ZRANGEBYSCORE fuzzy test
, 100 ranges in 
1000 elements sorted 
set} { 
1295         for {set i 
0} {$i < 1000} {incr i
} { 
1296             $r zadd zset 
[expr rand
()] $i 
1298         for {set i 
0} {$i < 100} {incr i
} { 
1299             set min 
[expr rand
()] 
1300             set max 
[expr rand
()] 
1306             set low 
[$r zrangebyscore zset 
-inf $min] 
1307             set ok 
[$r zrangebyscore zset 
$min $max] 
1308             set high 
[$r zrangebyscore zset 
$max +inf
] 
1310                 set score 
[$r zscore zset 
$x] 
1311                 if {$score > $min} { 
1312                     append err 
"Error, score for $x is $score > $min\n" 
1316                 set score 
[$r zscore zset 
$x] 
1317                 if {$score < $min || 
$score > $max} { 
1318                     append err 
"Error, score for $x is $score outside $min-$max range\n" 
1322                 set score 
[$r zscore zset 
$x] 
1323                 if {$score < $max} { 
1324                     append err 
"Error, score for $x is $score < $max\n" 
1331     test 
{ZRANGEBYSCORE with LIMIT
} { 
1339             [$r zrangebyscore zset 
0 10 LIMIT 
0 2] \ 
1340             [$r zrangebyscore zset 
0 10 LIMIT 
2 3] \ 
1341             [$r zrangebyscore zset 
0 10 LIMIT 
2 10] \ 
1342             [$r zrangebyscore zset 
0 10 LIMIT 
20 10] 
1343     } {{a b
} {c d e
} {c d e
} {}} 
1345     test 
{ZREMRANGE basics
} { 
1352         list [$r zremrangebyscore zset 
2 4] [$r zrange zset 
0 -1] 
1355     test 
{ZREMRANGE from 
-inf to 
+inf
} { 
1362         list [$r zremrangebyscore zset 
-inf +inf
] [$r zrange zset 
0 -1] 
1365     test 
{SORT against sorted sets
} { 
1372         $r sort zset alpha desc
 
1375     test 
{Sorted sets 
+inf and 
-inf handling
} { 
1380         $r zadd zset 
1000000 d
 
1381         $r zadd zset 
+inf max
 
1382         $r zadd zset 
-inf min
 
1386     test 
{EXPIRE 
- don't 
set timeouts multiple times
} { 
1388         set v1 
[$r expire x 
5] 
1390         set v3 
[$r expire x 
10] 
1392         list $v1 $v2 $v3 $v4 
1395     test 
{EXPIRE 
- It should be still possible to 
read 'x'
} { 
1399     test 
{EXPIRE 
- After 
6 seconds the key should no longer be here
} { 
1401         list [$r get x
] [$r exists x
] 
1404     test 
{EXPIRE 
- Delete on write policy
} { 
1412     test 
{EXPIREAT 
- Check 
for EXPIRE alike behavior
} { 
1415         $r expireat x 
[expr [clock seconds
]+15] 
1419     test 
{ZSETs skiplist implementation backlink consistency test
} { 
1422         for {set j 
0} {$j < $elements} {incr j
} { 
1423             $r zadd myzset 
[expr rand
()] "Element-$j" 
1424             $r zrem myzset 
"Element-[expr int(rand()*$elements)]" 
1426         set l1 
[$r zrange myzset 
0 -1] 
1427         set l2 
[$r zrevrange myzset 
0 -1] 
1428         for {set j 
0} {$j < [llength $l1]} {incr j
} { 
1429             if {[lindex $l1 $j] ne 
[lindex $l2 end-
$j]} { 
1436     foreach fuzztype 
{binary alpha compr
} { 
1437         test 
"FUZZ stresser with data model $fuzztype" { 
1439             for {set i 
0} {$i < 10000} {incr i
} { 
1440                 set fuzz 
[randstring 
0 512 $fuzztype] 
1442                 set got 
[$r get foo
] 
1443                 if {$got ne 
$fuzz} { 
1444                     set err 
[list $fuzz $got] 
1462     test 
{Handle an empty query well
} { 
1464         puts -nonewline $fd "\r\n" 
1469     test 
{Negative multi bulk command does not create problems
} { 
1471         puts -nonewline $fd "*-10\r\n" 
1476     test 
{Negative multi bulk payload
} { 
1478         puts -nonewline $fd "SET x -10\r\n" 
1483     test 
{Too big bulk payload
} { 
1485         puts -nonewline $fd "SET x 2000000000\r\n" 
1488     } {*invalid bulk
*count
*} 
1490     test 
{Multi bulk request not followed by bulk args
} { 
1492         puts -nonewline $fd "*1\r\nfoo\r\n" 
1495     } {*protocol 
error*} 
1497     test 
{Generic wrong number of args
} { 
1498         catch {$r ping x y z
} err
 
1500     } {*wrong
*arguments
*ping
*} 
1502     test 
{SELECT an out of range DB
} { 
1503         catch {$r select 
1000000} err
 
1507     if {![catch {package require sha1
}]} { 
1508         test 
{Check consistency of different data types 
after a reload
} { 
1510             createComplexDataset 
$r 10000 
1511             set sha1 
[datasetDigest 
$r] 
1513             set sha1_after 
[datasetDigest 
$r] 
1514             expr {$sha1 eq 
$sha1_after} 
1517         test 
{Same dataset digest 
if saving
/reloading as AOF?
} { 
1519             waitForBgrewriteaof 
$r 
1521             set sha1_after 
[datasetDigest 
$r] 
1522             expr {$sha1 eq 
$sha1_after} 
1526     test 
{EXPIRES 
after a reload 
(snapshot 
+ append only 
file)} { 
1533         set e1 
[expr {$ttl > 900 && $ttl <= 1000}] 
1535         waitForBgrewriteaof 
$r 
1537         set e2 
[expr {$ttl > 900 && $ttl <= 1000}] 
1541     test 
{PIPELINING stresser 
(also a regression 
for the old epoll bug
)} { 
1542         set fd2 
[socket 127.0.0.1 6379] 
1543         fconfigure $fd2 -encoding binary -translation binary 
1544         puts -nonewline $fd2 "SELECT 9\r\n" 
1548         for {set i 
0} {$i < 100000} {incr i
} { 
1550             set val 
"0000${i}0000" 
1551             append q 
"SET key:$i [string length $val]\r\n$val\r\n" 
1552             puts -nonewline $fd2 $q 
1554             append q 
"GET key:$i\r\n" 
1555             puts -nonewline $fd2 $q 
1559         for {set i 
0} {$i < 100000} {incr i
} { 
1562             set count 
[string range 
$count 1 end
] 
1563             set val 
[read $fd2 $count] 
1570     test 
{MUTLI 
/ EXEC basics
} { 
1576         set v1 
[$r lrange mylist 
0 -1] 
1580     } {QUEUED QUEUED 
{{a b c
} PONG
}} 
1582     # Leave the user with a clean DB before to exit 
1587         lappend aux 
[$r dbsize
] 
1590         lappend aux 
[$r dbsize
] 
1593     test 
{Perform a final SAVE to leave a clean DB on disk
} { 
1598         if {[string match 
{*Darwin
*} [exec uname 
-a]]} { 
1599             test 
{Check 
for memory leaks
} { 
1600                 exec leaks redis-server
 
1605     puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed" 
1606     if {$::failed > 0} { 
1607         puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n" 
1616         set randkey 
[expr int
(rand
()*10000)] 
1617         set randval 
[expr int
(rand
()*10000)] 
1618         set randidx0 
[expr int
(rand
()*10)] 
1619         set randidx1 
[expr int
(rand
()*10)] 
1620         set cmd 
[expr int
(rand
()*20)] 
1622             if {$cmd == 0} {$r set $randkey $randval} 
1623             if {$cmd == 1} {$r get 
$randkey} 
1624             if {$cmd == 2} {$r incr $randkey} 
1625             if {$cmd == 3} {$r lpush 
$randkey $randval} 
1626             if {$cmd == 4} {$r rpop 
$randkey} 
1627             if {$cmd == 5} {$r del 
$randkey} 
1628             if {$cmd == 6} {$r llen 
$randkey} 
1629             if {$cmd == 7} {$r lrange $randkey $randidx0 $randidx1} 
1630             if {$cmd == 8} {$r ltrim 
$randkey $randidx0 $randidx1} 
1631             if {$cmd == 9} {$r lindex $randkey $randidx0} 
1632             if {$cmd == 10} {$r lset $randkey $randidx0 $randval} 
1633             if {$cmd == 11} {$r sadd 
$randkey $randval} 
1634             if {$cmd == 12} {$r srem 
$randkey $randval} 
1635             if {$cmd == 13} {$r smove 
$randkey $randval} 
1636             if {$cmd == 14} {$r scard 
$randkey} 
1637             if {$cmd == 15} {$r expire 
$randkey [expr $randval%60]} 
1645 # Set a few configuration defaults 
1646 set ::host 127.0.0.1 
1654 for {set j 
0} {$j < [llength $argv]} {incr j
} { 
1655     set opt 
[lindex $argv $j] 
1656     set arg 
[lindex $argv [expr $j+1]] 
1657     set lastarg 
[expr {$arg eq 
{}}] 
1658     if {$opt eq 
{-h} && !$lastarg} { 
1661     } elseif 
{$opt eq 
{-p} && !$lastarg} { 
1664     } elseif 
{$opt eq 
{-stress}} { 
1666     } elseif 
{$opt eq 
{--flush}} { 
1668     } elseif 
{$opt eq 
{--first} && !$lastarg} { 
1671     } elseif 
{$opt eq 
{--last} && !$lastarg} { 
1675         puts "Wrong argument: $opt" 
1680 # Before to run the test check if DB 9 and DB 10 are empty 
1688 set db9size 
[$r dbsize
] 
1690 set db10size 
[$r dbsize
] 
1691 if {$db9size != 0 || 
$db10size != 0} { 
1692     puts "Can't run the tests against DB 9 and 10: DBs are not empty." 
1703     main 
$::host $::port