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
} {
131 set d
[expr {rand
()}]
133 set d
[expr {rand
()}]
135 set d
[expr {rand
()}]
137 set d
[expr {rand
()}]
139 set d
[expr {rand
()}]
141 randpath
{set d
+inf
} {set d
-inf}
165 randpath
{$r lpush
$k $v} \
172 randpath
{$r sadd
$k $v} \
176 randpath
{$r zadd
$k $d $v} \
180 randpath
{$r hset
$k $f $v} \
187 proc datasetDigest r
{
188 set keys
[lsort [$r keys
*]]
194 set aux
[::sha1::sha1 -hex [$r get
$k]]
196 if {[$r llen
$k] == 0} {
199 set aux
[::sha1::sha1 -hex [$r lrange $k 0 -1]]
202 if {[$r scard
$k] == 0} {
205 set aux
[::sha1::sha1 -hex [lsort [$r smembers
$k]]]
208 if {[$r zcard
$k] == 0} {
211 set aux
[::sha1::sha1 -hex [$r zrange
$k 0 -1]]
214 if {[$r hlen
$k] == 0} {
217 set aux
[::sha1::sha1 -hex [lsort [$r hgetall
$k]]]
220 error "Type not supported: $t"
223 if {$aux eq
{}} continue
224 set digest
[::sha1::sha1 -hex [join [list $aux $digest $k] "\n"]]
229 proc main
{server port
} {
230 set r
[redis
$server $port]
235 # The following AUTH test should be enabled only when requirepass
236 # <PASSWORD> is set in redis.conf and redis-server was started with
237 # redis.conf as the first argument.
239 #test {AUTH with requirepass in redis.conf} {
243 test
{DEL all keys to start with a clean DB
} {
244 foreach key
[$r keys
*] {$r del
$key}
248 test
{SET and GET an item
} {
253 test
{SET and GET an empty item
} {
258 test
{DEL against a single item
} {
267 list [$r del foo1 foo2 foo3 foo4
] [$r mget foo1 foo2 foo3
]
270 test
{KEYS with pattern
} {
271 foreach key
{key_x key_y key_z foo_a foo_b foo_c
} {
275 } {foo_a foo_b foo_c
}
277 test
{KEYS to get all keys
} {
279 } {foo_a foo_b foo_c key_x key_y key_z
}
285 test
{DEL all keys
} {
286 foreach key
[$r keys
*] {$r del
$key}
290 test
{Very big payload in GET
/SET
} {
291 set buf
[string repeat
"abcd" 1000000]
294 } [string repeat
"abcd" 1000000]
296 test
{Very big payload random access
} {
299 for {set j
0} {$j < 100} {incr j
} {
300 set size
[expr 1+[randomInt
100000]]
301 set buf
[string repeat
"pl-$j" $size]
303 $r set bigpayload_
$j $buf
305 for {set j
0} {$j < 1000} {incr j
} {
306 set index
[randomInt
100]
307 set buf
[$r get bigpayload_
$index]
308 if {$buf != $payload($index)} {
309 set err
"Values differ: I set '$payload($index)' but I read back '$buf'"
317 test
{SET
10000 numeric keys and access all them in reverse order
} {
319 for {set x
0} {$x < 10000} {incr x
} {
323 for {set x
9999} {$x >= 0} {incr x
-1} {
326 set err
"Eleemnt at position $x is $val instead of $x"
333 test
{DBSIZE should be
10101 now
} {
337 test
{INCR against non existing key
} {
339 append res
[$r incr novar
]
340 append res
[$r get novar
]
343 test
{INCR against key created by
incr itself
} {
347 test
{INCR against key originally
set with SET
} {
352 test
{INCR over
32bit value
} {
353 $r set novar
17179869184
357 test
{INCRBY over
32bit value with over
32bit increment
} {
358 $r set novar
17179869184
359 $r incrby novar
17179869184
362 test
{INCR against key with spaces
(no integer encoded
)} {
367 test
{DECRBY over
32bit value with over
32bit increment
, negative res
} {
368 $r set novar
17179869184
369 $r decrby novar
17179869185
372 test
{SETNX target key missing
} {
373 $r setnx novar2 foobared
377 test
{SETNX target key exists
} {
378 $r setnx novar2 blabla
382 test
{SETNX will overwrite EXPIREing key
} {
392 append res
[$r exists newkey
]
394 append res
[$r exists newkey
]
397 test
{Zero length value in key. SET
/GET
/EXISTS
} {
399 set res
[$r get emptykey
]
400 append res
[$r exists emptykey
]
402 append res
[$r exists emptykey
]
405 test
{Commands pipelining
} {
407 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
410 append res
[string match OK
* [::redis::redis_read_reply $fd]]
411 append res
[::redis::redis_read_reply $fd]
412 append res
[string match PONG
* [::redis::redis_read_reply $fd]]
416 test
{Non existing command
} {
417 catch {$r foobaredcommand
} err
418 string match ERR
* $err
421 test
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} {
422 set res
[$r lpush mylist a
]
423 append res
[$r lpush mylist b
]
424 append res
[$r rpush mylist c
]
425 append res
[$r llen mylist
]
426 append res
[$r rpush anotherlist d
]
427 append res
[$r lpush anotherlist e
]
428 append res
[$r llen anotherlist
]
429 append res
[$r lindex mylist
0]
430 append res
[$r lindex mylist
1]
431 append res
[$r lindex mylist
2]
432 append res
[$r lindex anotherlist
0]
433 append res
[$r lindex anotherlist
1]
434 list $res [$r lindex mylist
100]
442 test
{Create a long
list and check every single element with LINDEX
} {
444 for {set i
0} {$i < 1000} {incr i
} {
447 for {set i
0} {$i < 1000} {incr i
} {
448 if {[$r lindex mylist
$i] eq
$i} {incr ok
}
449 if {[$r lindex mylist
[expr (-$i)-1]] eq
[expr 999-$i]} {
456 test
{Test elements with LINDEX in random access
} {
458 for {set i
0} {$i < 1000} {incr i
} {
459 set rint
[expr int
(rand
()*1000)]
460 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
461 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
468 test
{Check
if the
list is still ok
after a DEBUG RELOAD
} {
471 for {set i
0} {$i < 1000} {incr i
} {
472 set rint
[expr int
(rand
()*1000)]
473 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
474 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
481 test
{LLEN against non-list value
error} {
484 catch {$r llen mylist
} err
488 test
{LLEN against non existing key
} {
492 test
{LINDEX against non-list value
error} {
493 catch {$r lindex mylist
0} err
497 test
{LINDEX against non existing key
} {
498 $r lindex not-a-key
10
501 test
{LPUSH against non-list value
error} {
502 catch {$r lpush mylist
0} err
506 test
{RPUSH against non-list value
error} {
507 catch {$r rpush mylist
0} err
511 test
{RPOPLPUSH base case
} {
517 set v1
[$r rpoplpush mylist newlist
]
518 set v2
[$r rpoplpush mylist newlist
]
519 set l1
[$r lrange mylist
0 -1]
520 set l2
[$r lrange newlist
0 -1]
524 test
{RPOPLPUSH with the same
list as src and dst
} {
529 set l1
[$r lrange mylist
0 -1]
530 set v
[$r rpoplpush mylist mylist
]
531 set l2
[$r lrange mylist
0 -1]
533 } {{a b c
} c
{c a b
}}
535 test
{RPOPLPUSH target
list already exists
} {
543 set v1
[$r rpoplpush mylist newlist
]
544 set v2
[$r rpoplpush mylist newlist
]
545 set l1
[$r lrange mylist
0 -1]
546 set l2
[$r lrange newlist
0 -1]
548 } {d c
{a b
} {c d x
}}
550 test
{RPOPLPUSH against non existing key
} {
553 set v1
[$r rpoplpush mylist newlist
]
554 list $v1 [$r exists mylist
] [$r exists newlist
]
557 test
{RPOPLPUSH against non
list src key
} {
561 catch {$r rpoplpush mylist newlist
} err
562 list [$r type mylist
] [$r exists newlist
] [string range
$err 0 2]
565 test
{RPOPLPUSH against non
list dst key
} {
573 catch {$r rpoplpush mylist newlist
} err
574 list [$r lrange mylist
0 -1] [$r type newlist
] [string range
$err 0 2]
575 } {{a b c d
} string ERR
}
577 test
{RPOPLPUSH against non existing src key
} {
580 $r rpoplpush mylist newlist
583 test
{RENAME basic usage
} {
585 $r rename mykey mykey1
586 $r rename mykey1 mykey2
590 test
{RENAME
source key should no longer exist
} {
594 test
{RENAME against already existing key
} {
597 $r rename mykey2 mykey
598 set res
[$r get mykey
]
599 append res
[$r exists mykey2
]
602 test
{RENAMENX basic usage
} {
606 $r renamenx mykey mykey2
607 set res
[$r get mykey2
]
608 append res
[$r exists mykey
]
611 test
{RENAMENX against already existing key
} {
614 $r renamenx mykey mykey2
617 test
{RENAMENX against already existing key
(2)} {
618 set res
[$r get mykey
]
619 append res
[$r get mykey2
]
622 test
{RENAME against non existing
source key
} {
623 catch {$r rename nokey foobar
} err
627 test
{RENAME where
source and dest key is the same
} {
628 catch {$r rename mykey mykey
} err
632 test
{DEL all keys again
(DB
0)} {
633 foreach key
[$r keys
*] {
639 test
{DEL all keys again
(DB
1)} {
641 foreach key
[$r keys
*] {
649 test
{MOVE basic usage
} {
653 lappend res
[$r exists mykey
]
654 lappend res
[$r dbsize
]
656 lappend res
[$r get mykey
]
657 lappend res
[$r dbsize
]
660 } [list 0 0 foobar
1]
662 test
{MOVE against key existing in the target DB
} {
667 test
{SET
/GET keys in different DBs
} {
675 lappend res
[$r get a
]
676 lappend res
[$r get b
]
678 lappend res
[$r get a
]
679 lappend res
[$r get b
]
682 } {hello world foo bared
}
684 test
{Basic LPOP
/RPOP
} {
689 list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
]
692 test
{LPOP
/RPOP against empty
list} {
696 test
{LPOP against non
list value
} {
698 catch {$r lpop notalist
} err
702 test
{Mass LPUSH
/LPOP
} {
704 for {set i
0} {$i < 1000} {incr i
} {
709 for {set i
0} {$i < 500} {incr i
} {
710 incr sum2
[$r lpop mylist
]
711 incr sum2
[$r rpop mylist
]
716 test
{LRANGE basics
} {
717 for {set i
0} {$i < 10} {incr i
} {
720 list [$r lrange mylist
1 -2] \
721 [$r lrange mylist
-3 -1] \
722 [$r lrange mylist
4 4]
723 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
725 test
{LRANGE inverted indexes
} {
729 test
{LRANGE out of range indexes including the full
list} {
730 $r lrange mylist
-1000 1000
731 } {0 1 2 3 4 5 6 7 8 9}
733 test
{LRANGE against non existing key
} {
734 $r lrange nosuchkey
0 1
737 test
{LTRIM basics
} {
739 for {set i
0} {$i < 100} {incr i
} {
743 $r lrange mylist
0 -1
746 test
{LTRIM stress testing
} {
749 for {set i
0} {$i < 20} {incr i
} {
753 for {set j
0} {$j < 100} {incr j
} {
756 for {set i
0} {$i < 20} {incr i
} {
762 $r ltrim mylist
$a $b
763 if {[$r lrange mylist
0 -1] ne
[lrange $mylist $a $b]} {
764 set err
"[$r lrange mylist 0 -1] != [lrange $mylist $a $b]"
773 foreach x
{99 98 97 96 95} {
777 $r lset mylist
-1 bar
778 $r lrange mylist
0 -1
781 test
{LSET out of range index
} {
782 catch {$r lset mylist
10 foo
} err
786 test
{LSET against non existing key
} {
787 catch {$r lset nosuchkey
10 foo
} err
791 test
{LSET against non
list value
} {
793 catch {$r lset nolist
0 foo
} err
797 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} {
800 list [$r scard myset
] [$r sismember myset foo
] \
801 [$r sismember myset bar
] [$r sismember myset bla
] \
802 [lsort [$r smembers myset
]]
803 } {2 1 1 0 {bar foo
}}
805 test
{SADD adding the same element multiple times
} {
812 test
{SADD against non
set} {
813 catch {$r sadd mylist foo
} err
820 lsort [$r smembers myset
]
823 test
{Mass SADD and SINTER with two sets
} {
824 for {set i
0} {$i < 1000} {incr i
} {
826 $r sadd set2
[expr $i+995]
828 lsort [$r sinter set1 set2
]
829 } {995 996 997 998 999}
831 test
{SUNION with two sets
} {
832 lsort [$r sunion set1 set2
]
833 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
835 test
{SINTERSTORE with two sets
} {
836 $r sinterstore setres set1 set2
837 lsort [$r smembers setres
]
838 } {995 996 997 998 999}
840 test
{SINTERSTORE with two sets
, after a DEBUG RELOAD
} {
842 $r sinterstore setres set1 set2
843 lsort [$r smembers setres
]
844 } {995 996 997 998 999}
846 test
{SUNIONSTORE with two sets
} {
847 $r sunionstore setres set1 set2
848 lsort [$r smembers setres
]
849 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
851 test
{SUNIONSTORE against non existing keys
} {
853 list [$r sunionstore setres foo111 bar222
] [$r exists xxx
]
856 test
{SINTER against three sets
} {
861 lsort [$r sinter set1 set2 set3
]
864 test
{SINTERSTORE with three sets
} {
865 $r sinterstore setres set1 set2 set3
866 lsort [$r smembers setres
]
869 test
{SUNION with non existing keys
} {
870 lsort [$r sunion nokey1 set1 set2 nokey2
]
871 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
873 test
{SDIFF with two sets
} {
874 for {set i
5} {$i < 1000} {incr i
} {
877 lsort [$r sdiff set1 set4
]
880 test
{SDIFF with three sets
} {
882 lsort [$r sdiff set1 set4 set5
]
885 test
{SDIFFSTORE with three sets
} {
886 $r sdiffstore sres set1 set4 set5
887 lsort [$r smembers sres
]
895 list [lsort [list [$r spop myset
] [$r spop myset
] [$r spop myset
]]] [$r scard myset
]
898 test
{SAVE
- make sure there are all the types as values
} {
899 # Wait for a background saving in progress to terminate
901 $r lpush mysavelist hello
902 $r lpush mysavelist world
904 $r set mynormalkey
{blablablba
}
905 $r zadd mytestzset a
10
906 $r zadd mytestzset b
20
907 $r zadd mytestzset c
30
916 unset -nocomplain myset
918 for {set i
0} {$i < 100} {incr i
} {
919 set myset
([$r srandmember myset
]) 1
921 lsort [array names myset
]
924 test
{Create a random
list and a random
set} {
926 array set seenrand
{}
927 for {set i
0} {$i < 10000} {incr i
} {
929 # Make sure all the weights are different because
930 # Redis does not use a stable sort but Tcl does.
932 set rint
[expr int
(rand
()*1000000)]
934 set rint
[expr rand
()]
936 if {![info exists seenrand
($rint)]} break
938 set seenrand
($rint) x
940 $r sadd tosort-set
$i
941 $r set weight_
$i $rint
942 lappend tosort
[list $i $rint]
944 set sorted
[lsort -index 1 -real $tosort]
946 for {set i
0} {$i < 10000} {incr i
} {
947 lappend res
[lindex $sorted $i 0]
952 test
{SORT with BY against the newly created
list} {
953 $r sort tosort
{BY weight_
*}
956 test
{the same SORT with BY
, but against the newly created
set} {
957 $r sort tosort-set
{BY weight_
*}
960 test
{SORT with BY and STORE against the newly created
list} {
961 $r sort tosort
{BY weight_
*} store sort-res
962 $r lrange sort-res
0 -1
965 test
{SORT direct
, numeric
, against the newly created
list} {
967 } [lsort -integer $res]
969 test
{SORT decreasing sort
} {
970 $r sort tosort
{DESC
}
971 } [lsort -decreasing -integer $res]
973 test
{SORT speed
, sorting
10000 elements
list using BY
, 100 times
} {
974 set start
[clock clicks
-milliseconds]
975 for {set i
0} {$i < 100} {incr i
} {
976 set sorted
[$r sort tosort
{BY weight_
* LIMIT
0 10}]
978 set elapsed
[expr [clock clicks
-milliseconds]-$start]
979 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
984 test
{SORT speed
, sorting
10000 elements
list directly
, 100 times
} {
985 set start
[clock clicks
-milliseconds]
986 for {set i
0} {$i < 100} {incr i
} {
987 set sorted
[$r sort tosort
{LIMIT
0 10}]
989 set elapsed
[expr [clock clicks
-milliseconds]-$start]
990 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
995 test
{SORT speed
, pseudo-sorting
10000 elements
list, BY
<const
>, 100 times
} {
996 set start
[clock clicks
-milliseconds]
997 for {set i
0} {$i < 100} {incr i
} {
998 set sorted
[$r sort tosort
{BY nokey LIMIT
0 10}]
1000 set elapsed
[expr [clock clicks
-milliseconds]-$start]
1001 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
1006 test
{SORT regression
for issue
#19, sorting floats} {
1008 foreach x
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
1012 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
1014 test
{SORT with GET
#} {
1019 $r mset weight_1
10 weight_2
5 weight_3
30
1020 $r sort mylist BY weight_
* GET
#
1023 test
{SORT with constant GET
} {
1024 $r sort mylist GET foo
1027 test
{LREM
, remove all the occurrences
} {
1031 $r rpush mylist foobar
1032 $r rpush mylist foobared
1035 $r rpush mylist test
1037 set res
[$r lrem mylist
0 bar
]
1038 list [$r lrange mylist
0 -1] $res
1039 } {{foo foobar foobared zap test foo
} 2}
1041 test
{LREM
, remove the first occurrence
} {
1042 set res
[$r lrem mylist
1 foo
]
1043 list [$r lrange mylist
0 -1] $res
1044 } {{foobar foobared zap test foo
} 1}
1046 test
{LREM
, remove non existing element
} {
1047 set res
[$r lrem mylist
1 nosuchelement
]
1048 list [$r lrange mylist
0 -1] $res
1049 } {{foobar foobared zap test foo
} 0}
1051 test
{LREM
, starting from tail with negative count
} {
1055 $r rpush mylist foobar
1056 $r rpush mylist foobared
1059 $r rpush mylist test
1062 set res
[$r lrem mylist
-1 bar
]
1063 list [$r lrange mylist
0 -1] $res
1064 } {{foo bar foobar foobared zap test foo foo
} 1}
1066 test
{LREM
, starting from tail with negative count
(2)} {
1067 set res
[$r lrem mylist
-2 foo
]
1068 list [$r lrange mylist
0 -1] $res
1069 } {{foo bar foobar foobared zap test
} 2}
1071 test
{LREM
, deleting objects that may be encoded as integers
} {
1072 $r lpush myotherlist
1
1073 $r lpush myotherlist
2
1074 $r lpush myotherlist
3
1075 $r lrem myotherlist
1 2
1086 test
{MGET against non existing key
} {
1087 $r mget foo baazz bar
1090 test
{MGET against non-string key
} {
1093 $r mget foo baazz bar myset
1102 for {set i
0} {$i < 100} {incr i
} {
1103 set rkey
[$r randomkey
]
1104 if {$rkey eq
{foo
}} {
1107 if {$rkey eq
{bar
}} {
1111 list $foo_seen $bar_seen
1114 test
{RANDOMKEY against empty DB
} {
1119 test
{RANDOMKEY regression
1} {
1126 test
{GETSET
(set new value
)} {
1127 list [$r getset foo xyz
] [$r get foo
]
1130 test
{GETSET
(replace old value
)} {
1132 list [$r getset foo xyz
] [$r get foo
]
1135 test
{SMOVE basics
} {
1142 $r smove myset1 myset2 a
1143 list [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
1146 test
{SMOVE non existing key
} {
1147 list [$r smove myset1 myset2 foo
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
1148 } {0 {a x y z
} {b c
}}
1150 test
{SMOVE non existing src
set} {
1151 list [$r smove noset myset2 foo
] [lsort [$r smembers myset2
]]
1154 test
{SMOVE non existing dst
set} {
1155 list [$r smove myset2 myset3 y
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset3
]]
1158 test
{SMOVE wrong src key type
} {
1160 catch {$r smove x myset2 foo
} err
1164 test
{SMOVE wrong dst key type
} {
1166 catch {$r smove myset2 x foo
} err
1170 test
{MSET base case
} {
1171 $r mset x
10 y
"foo bar" z
"x x x x x x x\n\n\r\n"
1173 } [list 10 {foo bar
} "x x x x x x x\n\n\r\n"]
1175 test
{MSET wrong number of args
} {
1176 catch {$r mset x
10 y
"foo bar" z
} err
1180 test
{MSETNX with already existent key
} {
1181 list [$r msetnx x1 xxx y2 yyy x
20] [$r exists x1
] [$r exists y2
]
1184 test
{MSETNX with not existing keys
} {
1185 list [$r msetnx x1 xxx y2 yyy
] [$r get x1
] [$r get y2
]
1188 test
{MSETNX should remove all the volatile keys even on
failure} {
1192 list [$r msetnx x A y B z C
] [$r mget x y z
]
1195 test
{ZSET basic ZADD and score
update} {
1199 set aux1
[$r zrange ztmp
0 -1]
1201 set aux2
[$r zrange ztmp
0 -1]
1205 test
{ZCARD basics
} {
1209 test
{ZCARD non existing key
} {
1210 $r zcard ztmp-blabla
1213 test
{ZRANK basics
} {
1214 $r zadd zranktmp
10 x
1215 $r zadd zranktmp
20 y
1216 $r zadd zranktmp
30 z
1217 list [$r zrank zranktmp x
] [$r zrank zranktmp y
] [$r zrank zranktmp z
]
1220 test
{ZREVRANK basics
} {
1221 list [$r zrevrank zranktmp x
] [$r zrevrank zranktmp y
] [$r zrevrank zranktmp z
]
1224 test
{ZRANK
- after deletion
} {
1226 list [$r zrank zranktmp x
] [$r zrank zranktmp z
]
1232 for {set i
0} {$i < 1000} {incr i
} {
1233 set score
[expr rand
()]
1235 $r zadd zscoretest
$score $i
1237 for {set i
0} {$i < 1000} {incr i
} {
1238 if {[$r zscore zscoretest
$i] != [lindex $aux $i]} {
1239 set err
"Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i"
1246 test
{ZSCORE
after a DEBUG RELOAD
} {
1250 for {set i
0} {$i < 1000} {incr i
} {
1251 set score
[expr rand
()]
1253 $r zadd zscoretest
$score $i
1256 for {set i
0} {$i < 1000} {incr i
} {
1257 if {[$r zscore zscoretest
$i] != [lindex $aux $i]} {
1258 set err
"Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i"
1265 test
{ZRANGE and ZREVRANGE basics
} {
1266 list [$r zrange ztmp
0 -1] [$r zrevrange ztmp
0 -1] \
1267 [$r zrange ztmp
1 -1] [$r zrevrange ztmp
1 -1]
1268 } {{y x z
} {z x y
} {x z
} {x y
}}
1270 test
{ZRANGE WITHSCORES
} {
1271 $r zrange ztmp
0 -1 withscores
1274 test
{ZSETs stress tester
- sorting is working well?
} {
1276 for {set test
0} {$test < 2} {incr test
} {
1277 unset -nocomplain auxarray
1278 array set auxarray
{}
1281 for {set i
0} {$i < 1000} {incr i
} {
1283 set score
[expr rand
()]
1285 set score
[expr int
(rand
()*10)]
1287 set auxarray
($i) $score
1288 $r zadd myzset
$score $i
1290 if {[expr rand
()] < .2} {
1291 set j
[expr int
(rand
()*1000)]
1293 set score
[expr rand
()]
1295 set score
[expr int
(rand
()*10)]
1297 set auxarray
($j) $score
1298 $r zadd myzset
$score $j
1301 foreach {item score
} [array get auxarray
] {
1302 lappend auxlist
[list $score $item]
1304 set sorted
[lsort -command zlistAlikeSort
$auxlist]
1307 lappend auxlist
[lindex $x 1]
1309 set fromredis
[$r zrange myzset
0 -1]
1311 for {set i
0} {$i < [llength $fromredis]} {incr i
} {
1312 if {[lindex $fromredis $i] != [lindex $auxlist $i]} {
1320 test
{ZINCRBY
- can create a new sorted
set} {
1322 $r zincrby zset
1 foo
1323 list [$r zrange zset
0 -1] [$r zscore zset foo
]
1326 test
{ZINCRBY
- increment and decrement
} {
1327 $r zincrby zset
2 foo
1328 $r zincrby zset
1 bar
1329 set v1
[$r zrange zset
0 -1]
1330 $r zincrby zset
10 bar
1331 $r zincrby zset
-5 foo
1332 $r zincrby zset
-5 bar
1333 set v2
[$r zrange zset
0 -1]
1334 list $v1 $v2 [$r zscore zset foo
] [$r zscore zset bar
]
1335 } {{bar foo
} {foo bar
} -2 6}
1337 test
{ZRANGEBYSCORE and ZCOUNT basics
} {
1344 list [$r zrangebyscore zset
2 4] [$r zrangebyscore zset
(2 (4] \
1345 [$r zcount zset
2 4] [$r zcount zset
(2 (4]
1348 test
{ZRANGEBYSCORE withscores
} {
1355 $r zrangebyscore zset
2 4 withscores
1358 test
{ZRANGEBYSCORE fuzzy test
, 100 ranges in
1000 elements sorted
set} {
1361 for {set i
0} {$i < 1000} {incr i
} {
1362 $r zadd zset
[expr rand
()] $i
1364 for {set i
0} {$i < 100} {incr i
} {
1365 set min
[expr rand
()]
1366 set max
[expr rand
()]
1372 set low
[$r zrangebyscore zset
-inf $min]
1373 set ok
[$r zrangebyscore zset
$min $max]
1374 set high
[$r zrangebyscore zset
$max +inf
]
1375 set lowx
[$r zrangebyscore zset
-inf ($min]
1376 set okx
[$r zrangebyscore zset
($min ($max]
1377 set highx
[$r zrangebyscore zset
($max +inf
]
1379 if {[$r zcount zset
-inf $min] != [llength $low]} {
1380 append err
"Error, len does not match zcount\n"
1382 if {[$r zcount zset
$min $max] != [llength $ok]} {
1383 append err
"Error, len does not match zcount\n"
1385 if {[$r zcount zset
$max +inf
] != [llength $high]} {
1386 append err
"Error, len does not match zcount\n"
1388 if {[$r zcount zset
-inf ($min] != [llength $lowx]} {
1389 append err
"Error, len does not match zcount\n"
1391 if {[$r zcount zset
($min ($max] != [llength $okx]} {
1392 append err
"Error, len does not match zcount\n"
1394 if {[$r zcount zset
($max +inf
] != [llength $highx]} {
1395 append err
"Error, len does not match zcount\n"
1399 set score
[$r zscore zset
$x]
1400 if {$score > $min} {
1401 append err
"Error, score for $x is $score > $min\n"
1405 set score
[$r zscore zset
$x]
1406 if {$score >= $min} {
1407 append err
"Error, score for $x is $score >= $min\n"
1411 set score
[$r zscore zset
$x]
1412 if {$score < $min ||
$score > $max} {
1413 append err
"Error, score for $x is $score outside $min-$max range\n"
1417 set score
[$r zscore zset
$x]
1418 if {$score <= $min ||
$score >= $max} {
1419 append err
"Error, score for $x is $score outside $min-$max open range\n"
1423 set score
[$r zscore zset
$x]
1424 if {$score < $max} {
1425 append err
"Error, score for $x is $score < $max\n"
1429 set score
[$r zscore zset
$x]
1430 if {$score <= $max} {
1431 append err
"Error, score for $x is $score <= $max\n"
1438 test
{ZRANGEBYSCORE with LIMIT
} {
1446 [$r zrangebyscore zset
0 10 LIMIT
0 2] \
1447 [$r zrangebyscore zset
0 10 LIMIT
2 3] \
1448 [$r zrangebyscore zset
0 10 LIMIT
2 10] \
1449 [$r zrangebyscore zset
0 10 LIMIT
20 10]
1450 } {{a b
} {c d e
} {c d e
} {}}
1452 test
{ZRANGEBYSCORE with LIMIT and withscores
} {
1459 $r zrangebyscore zset
20 50 LIMIT
2 3 withscores
1462 test
{ZREMRANGEBYSCORE basics
} {
1469 list [$r zremrangebyscore zset
2 4] [$r zrange zset
0 -1]
1472 test
{ZREMRANGEBYSCORE from
-inf to
+inf
} {
1479 list [$r zremrangebyscore zset
-inf +inf
] [$r zrange zset
0 -1]
1482 test
{ZREMRANGEBYRANK basics
} {
1489 list [$r zremrangebyrank zset
1 3] [$r zrange zset
0 -1]
1492 test
{ZUNION basics
} {
1493 $r del zseta zsetb zsetc
1500 list [$r zunion zsetc
2 zseta zsetb
] [$r zrange zsetc
0 -1 withscores
]
1501 } {4 {a
1 b
3 d
3 c
5}}
1503 test
{ZUNION with weights
} {
1504 list [$r zunion zsetc
2 zseta zsetb weights
2 3] [$r zrange zsetc
0 -1 withscores
]
1505 } {4 {a
2 b
7 d
9 c
12}}
1507 test
{ZUNION with AGGREGATE MIN
} {
1508 list [$r zunion zsetc
2 zseta zsetb aggregate min
] [$r zrange zsetc
0 -1 withscores
]
1509 } {4 {a
1 b
1 c
2 d
3}}
1511 test
{ZUNION with AGGREGATE MAX
} {
1512 list [$r zunion zsetc
2 zseta zsetb aggregate max
] [$r zrange zsetc
0 -1 withscores
]
1513 } {4 {a
1 b
2 c
3 d
3}}
1515 test
{ZINTER basics
} {
1516 list [$r zinter zsetc
2 zseta zsetb
] [$r zrange zsetc
0 -1 withscores
]
1519 test
{ZINTER with weights
} {
1520 list [$r zinter zsetc
2 zseta zsetb weights
2 3] [$r zrange zsetc
0 -1 withscores
]
1523 test
{ZINTER with AGGREGATE MIN
} {
1524 list [$r zinter zsetc
2 zseta zsetb aggregate min
] [$r zrange zsetc
0 -1 withscores
]
1527 test
{ZINTER with AGGREGATE MAX
} {
1528 list [$r zinter zsetc
2 zseta zsetb aggregate max
] [$r zrange zsetc
0 -1 withscores
]
1531 test
{SORT against sorted sets
} {
1538 $r sort zset alpha desc
1541 test
{Sorted sets
+inf and
-inf handling
} {
1546 $r zadd zset
1000000 d
1547 $r zadd zset
+inf max
1548 $r zadd zset
-inf min
1552 test
{HSET
/HLEN
- Small hash creation
} {
1553 array set smallhash
{}
1554 for {set i
0} {$i < 8} {incr i
} {
1555 set key
[randstring
0 8 alpha
]
1556 set val
[randstring
0 8 alpha
]
1557 if {[info exists smallhash
($key)]} {
1561 $r hset smallhash
$key $val
1562 set smallhash
($key) $val
1564 list [$r hlen smallhash
]
1567 test
{Is the small hash encoded with a zipmap?
} {
1568 $r debug object smallhash
1571 test
{HSET
/HLEN
- Big hash creation
} {
1572 array set bighash
{}
1573 for {set i
0} {$i < 1024} {incr i
} {
1574 set key
[randstring
0 8 alpha
]
1575 set val
[randstring
0 8 alpha
]
1576 if {[info exists bighash
($key)]} {
1580 $r hset bighash
$key $val
1581 set bighash
($key) $val
1583 list [$r hlen bighash
]
1586 test
{Is the big hash encoded with a zipmap?
} {
1587 $r debug object bighash
1590 test
{HGET against the small hash
} {
1592 foreach k
[array names smallhash
*] {
1593 if {$smallhash($k) ne
[$r hget smallhash
$k]} {
1594 set err
"$smallhash($k) != [$r hget smallhash $k]"
1601 test
{HGET against the big hash
} {
1603 foreach k
[array names bighash
*] {
1604 if {$bighash($k) ne
[$r hget bighash
$k]} {
1605 set err
"$bighash($k) != [$r hget bighash $k]"
1612 test
{HSET in
update and insert mode
} {
1614 set k
[lindex [array names smallhash
*] 0]
1615 lappend rv
[$r hset smallhash
$k newval1
]
1616 set smallhash
($k) newval1
1617 lappend rv
[$r hget smallhash
$k]
1618 lappend rv
[$r hset smallhash __foobar123__ newval
]
1619 set k
[lindex [array names bighash
*] 0]
1620 lappend rv
[$r hset bighash
$k newval2
]
1621 set bighash
($k) newval2
1622 lappend rv
[$r hget bighash
$k]
1623 lappend rv
[$r hset bighash __foobar123__ newval
]
1624 lappend rv
[$r hdel smallhash __foobar123__
]
1625 lappend rv
[$r hdel bighash __foobar123__
]
1627 } {0 newval1
1 0 newval2
1 1 1}
1629 test
{HGET against non existing key
} {
1631 lappend rv
[$r hget smallhash __123123123__
]
1632 lappend rv
[$r hget bighash __123123123__
]
1636 test
{HKEYS
- small hash
} {
1637 lsort [$r hkeys smallhash
]
1638 } [lsort [array names smallhash
*]]
1640 test
{HKEYS
- big hash
} {
1641 lsort [$r hkeys bighash
]
1642 } [lsort [array names bighash
*]]
1644 test
{HVALS
- small hash
} {
1646 foreach {k v
} [array get smallhash
] {
1650 } [lsort [$r hvals smallhash
]]
1652 test
{HVALS
- big hash
} {
1654 foreach {k v
} [array get bighash
] {
1658 } [lsort [$r hvals bighash
]]
1660 test
{HGETALL
- small hash
} {
1661 lsort [$r hgetall smallhash
]
1662 } [lsort [array get smallhash
]]
1664 test
{HGETALL
- big hash
} {
1665 lsort [$r hgetall bighash
]
1666 } [lsort [array get bighash
]]
1668 test
{HDEL and
return value
} {
1670 lappend rv
[$r hdel smallhash nokey
]
1671 lappend rv
[$r hdel bighash nokey
]
1672 set k
[lindex [array names smallhash
*] 0]
1673 lappend rv
[$r hdel smallhash
$k]
1674 lappend rv
[$r hdel smallhash
$k]
1675 lappend rv
[$r hget smallhash
$k]
1677 set k
[lindex [array names bighash
*] 0]
1678 lappend rv
[$r hdel bighash
$k]
1679 lappend rv
[$r hdel bighash
$k]
1680 lappend rv
[$r hget bighash
$k]
1683 } {0 0 1 0 {} 1 0 {}}
1687 set k
[lindex [array names smallhash
*] 0]
1688 lappend rv
[$r hexists smallhash
$k]
1689 lappend rv
[$r hexists smallhash nokey
]
1690 set k
[lindex [array names bighash
*] 0]
1691 lappend rv
[$r hexists bighash
$k]
1692 lappend rv
[$r hexists bighash nokey
]
1695 test
{Is a zipmap encoded Hash promoted on big payload?
} {
1696 $r hset smallhash foo
[string repeat a
1024]
1697 $r debug object smallhash
1701 # Randomized test, small and big
1702 # .rdb / AOF consistency test should include hashes
1704 test
{EXPIRE
- don't
set timeouts multiple times
} {
1706 set v1
[$r expire x
5]
1708 set v3
[$r expire x
10]
1710 list $v1 $v2 $v3 $v4
1713 test
{EXPIRE
- It should be still possible to
read 'x'
} {
1717 test
{EXPIRE
- After
6 seconds the key should no longer be here
} {
1719 list [$r get x
] [$r exists x
]
1722 test
{EXPIRE
- Delete on write policy
} {
1730 test
{EXPIREAT
- Check
for EXPIRE alike behavior
} {
1733 $r expireat x
[expr [clock seconds
]+15]
1737 test
{ZSETs skiplist implementation backlink consistency test
} {
1740 for {set j
0} {$j < $elements} {incr j
} {
1741 $r zadd myzset
[expr rand
()] "Element-$j"
1742 $r zrem myzset
"Element-[expr int(rand()*$elements)]"
1744 set l1
[$r zrange myzset
0 -1]
1745 set l2
[$r zrevrange myzset
0 -1]
1746 for {set j
0} {$j < [llength $l1]} {incr j
} {
1747 if {[lindex $l1 $j] ne
[lindex $l2 end-
$j]} {
1754 test
{ZSETs ZRANK augmented skip
list stress testing
} {
1757 for {set k
0} {$k < 10000} {incr k
} {
1758 set i
[expr {$k%1000}]
1759 if {[expr rand
()] < .2} {
1762 set score
[expr rand
()]
1763 $r zadd myzset
$score $i
1765 set card
[$r zcard myzset
]
1767 set index
[randomInt
$card]
1768 set ele
[lindex [$r zrange myzset
$index $index] 0]
1769 set rank
[$r zrank myzset
$ele]
1770 if {$rank != $index} {
1771 set err
"$ele RANK is wrong! ($rank != $index)"
1779 foreach fuzztype
{binary alpha compr
} {
1780 test
"FUZZ stresser with data model $fuzztype" {
1782 for {set i
0} {$i < 10000} {incr i
} {
1783 set fuzz
[randstring
0 512 $fuzztype]
1785 set got
[$r get foo
]
1786 if {$got ne
$fuzz} {
1787 set err
[list $fuzz $got]
1806 test
{Handle an empty query well
} {
1808 puts -nonewline $fd "\r\n"
1813 test
{Negative multi bulk command does not create problems
} {
1815 puts -nonewline $fd "*-10\r\n"
1820 test
{Negative multi bulk payload
} {
1822 puts -nonewline $fd "SET x -10\r\n"
1827 test
{Too big bulk payload
} {
1829 puts -nonewline $fd "SET x 2000000000\r\n"
1832 } {*invalid bulk
*count
*}
1834 test
{Multi bulk request not followed by bulk args
} {
1836 puts -nonewline $fd "*1\r\nfoo\r\n"
1839 } {*protocol
error*}
1841 test
{Generic wrong number of args
} {
1842 catch {$r ping x y z
} err
1844 } {*wrong
*arguments
*ping
*}
1846 test
{SELECT an out of range DB
} {
1847 catch {$r select
1000000} err
1851 if {![catch {package require sha1
}]} {
1852 test
{Check consistency of different data types
after a reload
} {
1854 createComplexDataset
$r 10000
1855 set sha1
[datasetDigest
$r]
1857 set sha1_after
[datasetDigest
$r]
1858 expr {$sha1 eq
$sha1_after}
1861 test
{Same dataset digest
if saving
/reloading as AOF?
} {
1863 waitForBgrewriteaof
$r
1865 set sha1_after
[datasetDigest
$r]
1866 expr {$sha1 eq
$sha1_after}
1870 test
{EXPIRES
after a reload
(snapshot
+ append only
file)} {
1877 set e1
[expr {$ttl > 900 && $ttl <= 1000}]
1879 waitForBgrewriteaof
$r
1881 set e2
[expr {$ttl > 900 && $ttl <= 1000}]
1885 test
{PIPELINING stresser
(also a regression
for the old epoll bug
)} {
1886 set fd2
[socket 127.0.0.1 6379]
1887 fconfigure $fd2 -encoding binary -translation binary
1888 puts -nonewline $fd2 "SELECT 9\r\n"
1892 for {set i
0} {$i < 100000} {incr i
} {
1894 set val
"0000${i}0000"
1895 append q
"SET key:$i [string length $val]\r\n$val\r\n"
1896 puts -nonewline $fd2 $q
1898 append q
"GET key:$i\r\n"
1899 puts -nonewline $fd2 $q
1903 for {set i
0} {$i < 100000} {incr i
} {
1906 set count
[string range
$count 1 end
]
1907 set val
[read $fd2 $count]
1914 test
{MUTLI
/ EXEC basics
} {
1920 set v1
[$r lrange mylist
0 -1]
1924 } {QUEUED QUEUED
{{a b c
} PONG
}}
1932 set v1
[$r del mylist
]
1934 set v3
[$r lrange mylist
0 -1]
1936 } {QUEUED OK
{a b c
}}
1938 test
{APPEND basics
} {
1939 list [$r append foo bar
] [$r get foo
] \
1940 [$r append foo
100] [$r get foo
]
1943 test
{APPEND fuzzing
} {
1945 foreach type
{binary alpha compr
} {
1948 for {set i
0} {$i < 1000} {incr i
} {
1949 set bin
[randstring
0 10 $type]
1953 if {$buf != [$r get x
]} {
1954 set err
"Expected '$buf' found '[$r get x]'"
1961 # Leave the user with a clean DB before to exit
1966 lappend aux
[$r dbsize
]
1969 lappend aux
[$r dbsize
]
1972 test
{Perform a final SAVE to leave a clean DB on disk
} {
1977 if {[string match
{*Darwin
*} [exec uname
-a]]} {
1978 test
{Check
for memory leaks
} {
1979 exec leaks redis-server
1984 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
1985 if {$::failed > 0} {
1986 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
1995 set randkey
[expr int
(rand
()*10000)]
1996 set randval
[expr int
(rand
()*10000)]
1997 set randidx0
[expr int
(rand
()*10)]
1998 set randidx1
[expr int
(rand
()*10)]
1999 set cmd
[expr int
(rand
()*20)]
2001 if {$cmd == 0} {$r set $randkey $randval}
2002 if {$cmd == 1} {$r get
$randkey}
2003 if {$cmd == 2} {$r incr $randkey}
2004 if {$cmd == 3} {$r lpush
$randkey $randval}
2005 if {$cmd == 4} {$r rpop
$randkey}
2006 if {$cmd == 5} {$r del
$randkey}
2007 if {$cmd == 6} {$r llen
$randkey}
2008 if {$cmd == 7} {$r lrange $randkey $randidx0 $randidx1}
2009 if {$cmd == 8} {$r ltrim
$randkey $randidx0 $randidx1}
2010 if {$cmd == 9} {$r lindex $randkey $randidx0}
2011 if {$cmd == 10} {$r lset $randkey $randidx0 $randval}
2012 if {$cmd == 11} {$r sadd
$randkey $randval}
2013 if {$cmd == 12} {$r srem
$randkey $randval}
2014 if {$cmd == 13} {$r smove
$randkey $randval}
2015 if {$cmd == 14} {$r scard
$randkey}
2016 if {$cmd == 15} {$r expire
$randkey [expr $randval%60]}
2024 # Set a few configuration defaults
2025 set ::host 127.0.0.1
2033 for {set j
0} {$j < [llength $argv]} {incr j
} {
2034 set opt
[lindex $argv $j]
2035 set arg
[lindex $argv [expr $j+1]]
2036 set lastarg
[expr {$arg eq
{}}]
2037 if {$opt eq
{-h} && !$lastarg} {
2040 } elseif
{$opt eq
{-p} && !$lastarg} {
2043 } elseif
{$opt eq
{-stress}} {
2045 } elseif
{$opt eq
{--flush}} {
2047 } elseif
{$opt eq
{--first} && !$lastarg} {
2050 } elseif
{$opt eq
{--last} && !$lastarg} {
2054 puts "Wrong argument: $opt"
2059 # Before to run the test check if DB 9 and DB 10 are empty
2067 set db9size
[$r dbsize
]
2069 set db10size
[$r dbsize
]
2070 if {$db9size != 0 ||
$db10size != 0} {
2071 puts "Can't run the tests against DB 9 and 10: DBs are not empty."
2082 main
$::host $::port