1 # TODO # test pipelining
8 proc test
{name code okpattern
} {
9 puts -nonewline [format "%-70s " $name]
11 set retval
[uplevel 1 $code]
12 if {$okpattern eq
$retval ||
[string match
$okpattern $retval]} {
16 puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'"
21 proc randstring
{min max
{type
binary}} {
22 set len
[expr {$min+int
(rand
()*($max-$min+1))}]
24 if {$type eq
{binary}} {
27 } elseif
{$type eq
{alpha
}} {
30 } elseif
{$type eq
{compr
}} {
35 append output
[format "%c" [expr {$minval+int
(rand
()*($maxval-$minval+1))}]]
41 # Useful for some test
42 proc zlistAlikeSort
{a b
} {
43 if {[lindex $a 0] > [lindex $b 0]} {return 1}
44 if {[lindex $a 0] < [lindex $b 0]} {return -1}
45 string compare
[lindex $a 1] [lindex $b 1]
48 proc main
{server port
} {
49 set r
[redis
$server $port]
53 # The following AUTH test should be enabled only when requirepass
54 # <PASSWORD> is set in redis.conf and redis-server was started with
55 # redis.conf as the first argument.
57 #test {AUTH with requirepass in redis.conf} {
61 test
{DEL all keys to start with a clean DB
} {
62 foreach key
[$r keys
*] {$r del
$key}
66 test
{SET and GET an item
} {
71 test
{DEL against a single item
} {
80 list [$r del foo1 foo2 foo3 foo4
] [$r mget foo1 foo2 foo3
]
83 test
{KEYS with pattern
} {
84 foreach key
{key_x key_y key_z foo_a foo_b foo_c
} {
90 test
{KEYS to get all keys
} {
92 } {foo_a foo_b foo_c key_x key_y key_z
}
99 foreach key
[$r keys
*] {$r del
$key}
103 test
{Very big payload in GET
/SET
} {
104 set buf
[string repeat
"abcd" 1000000]
107 } [string repeat
"abcd" 1000000]
109 test
{SET
10000 numeric keys and access all them in reverse order
} {
110 for {set x
0} {$x < 10000} {incr x
} {
114 for {set x
9999} {$x >= 0} {incr x
-1} {
120 test
{DBSIZE should be
10001 now
} {
124 test
{INCR against non existing key
} {
126 append res
[$r incr novar
]
127 append res
[$r get novar
]
130 test
{INCR against key created by
incr itself
} {
134 test
{INCR against key originally
set with SET
} {
139 test
{INCR over
32bit value
} {
140 $r set novar
17179869184
144 test
{INCRBY over
32bit value with over
32bit increment
} {
145 $r set novar
17179869184
146 $r incrby novar
17179869184
149 test
{DECRBY over
32bit value with over
32bit increment
, negative res
} {
150 $r set novar
17179869184
151 $r decrby novar
17179869185
154 test
{SETNX target key missing
} {
155 $r setnx novar2 foobared
159 test
{SETNX target key exists
} {
160 $r setnx novar2 blabla
167 append res
[$r exists newkey
]
169 append res
[$r exists newkey
]
172 test
{Zero length value in key. SET
/GET
/EXISTS
} {
174 set res
[$r get emptykey
]
175 append res
[$r exists emptykey
]
177 append res
[$r exists emptykey
]
180 test
{Commands pipelining
} {
182 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
185 append res
[string match OK
* [::redis::redis_read_reply $fd]]
186 append res
[::redis::redis_read_reply $fd]
187 append res
[string match PONG
* [::redis::redis_read_reply $fd]]
191 test
{Non existing command
} {
192 catch {$r foobaredcommand
} err
193 string match ERR
* $err
196 test
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} {
200 set res
[$r llen mylist
]
201 append res
[$r lindex mylist
0]
202 append res
[$r lindex mylist
1]
203 append res
[$r lindex mylist
2]
211 test
{Create a long
list and check every single element with LINDEX
} {
213 for {set i
0} {$i < 1000} {incr i
} {
216 for {set i
0} {$i < 1000} {incr i
} {
217 if {[$r lindex mylist
$i] eq
$i} {incr ok
}
218 if {[$r lindex mylist
[expr (-$i)-1]] eq
[expr 999-$i]} {
225 test
{Test elements with LINDEX in random access
} {
227 for {set i
0} {$i < 1000} {incr i
} {
228 set rint
[expr int
(rand
()*1000)]
229 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
230 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
237 test
{LLEN against non-list value
error} {
240 catch {$r llen mylist
} err
244 test
{LINDEX against non-list value
error} {
245 catch {$r lindex mylist
0} err
249 test
{LPUSH against non-list value
error} {
250 catch {$r lpush mylist
0} err
254 test
{RPUSH against non-list value
error} {
255 catch {$r rpush mylist
0} err
259 test
{RENAME basic usage
} {
261 $r rename mykey mykey1
262 $r rename mykey1 mykey2
266 test
{RENAME
source key should no longer exist
} {
270 test
{RENAME against already existing key
} {
273 $r rename mykey2 mykey
274 set res
[$r get mykey
]
275 append res
[$r exists mykey2
]
278 test
{RENAMENX basic usage
} {
282 $r renamenx mykey mykey2
283 set res
[$r get mykey2
]
284 append res
[$r exists mykey
]
287 test
{RENAMENX against already existing key
} {
290 $r renamenx mykey mykey2
293 test
{RENAMENX against already existing key
(2)} {
294 set res
[$r get mykey
]
295 append res
[$r get mykey2
]
298 test
{RENAME against non existing
source key
} {
299 catch {$r rename nokey foobar
} err
303 test
{RENAME where
source and dest key is the same
} {
304 catch {$r rename mykey mykey
} err
308 test
{DEL all keys again
(DB
0)} {
309 foreach key
[$r keys
*] {
315 test
{DEL all keys again
(DB
1)} {
317 foreach key
[$r keys
*] {
325 test
{MOVE basic usage
} {
329 lappend res
[$r exists mykey
]
330 lappend res
[$r dbsize
]
332 lappend res
[$r get mykey
]
333 lappend res
[$r dbsize
]
336 } [list 0 0 foobar
1]
338 test
{MOVE against key existing in the target DB
} {
343 test
{SET
/GET keys in different DBs
} {
351 lappend res
[$r get a
]
352 lappend res
[$r get b
]
354 lappend res
[$r get a
]
355 lappend res
[$r get b
]
358 } {hello world foo bared
}
360 test
{Basic LPOP
/RPOP
} {
365 list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
]
368 test
{LPOP
/RPOP against empty
list} {
372 test
{LPOP against non
list value
} {
374 catch {$r lpop notalist
} err
378 test
{Mass LPUSH
/LPOP
} {
380 for {set i
0} {$i < 1000} {incr i
} {
385 for {set i
0} {$i < 500} {incr i
} {
386 incr sum2
[$r lpop mylist
]
387 incr sum2
[$r rpop mylist
]
392 test
{LRANGE basics
} {
393 for {set i
0} {$i < 10} {incr i
} {
396 list [$r lrange mylist
1 -2] \
397 [$r lrange mylist
-3 -1] \
398 [$r lrange mylist
4 4]
399 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
401 test
{LRANGE inverted indexes
} {
405 test
{LRANGE out of range indexes including the full
list} {
406 $r lrange mylist
-1000 1000
407 } {0 1 2 3 4 5 6 7 8 9}
409 test
{LRANGE against non existing key
} {
410 $r lrange nosuchkey
0 1
413 test
{LTRIM basics
} {
415 for {set i
0} {$i < 100} {incr i
} {
419 $r lrange mylist
0 -1
424 $r lset mylist
-1 bar
425 $r lrange mylist
0 -1
428 test
{LSET out of range index
} {
429 catch {$r lset mylist
10 foo
} err
433 test
{LSET against non existing key
} {
434 catch {$r lset nosuchkey
10 foo
} err
438 test
{LSET against non
list value
} {
440 catch {$r lset nolist
0 foo
} err
444 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} {
447 list [$r scard myset
] [$r sismember myset foo
] \
448 [$r sismember myset bar
] [$r sismember myset bla
] \
449 [lsort [$r smembers myset
]]
450 } {2 1 1 0 {bar foo
}}
452 test
{SADD adding the same element multiple times
} {
459 test
{SADD against non
set} {
460 catch {$r sadd mylist foo
} err
467 lsort [$r smembers myset
]
470 test
{Mass SADD and SINTER with two sets
} {
471 for {set i
0} {$i < 1000} {incr i
} {
473 $r sadd set2
[expr $i+995]
475 lsort [$r sinter set1 set2
]
476 } {995 996 997 998 999}
478 test
{SUNION with two sets
} {
479 lsort [$r sunion set1 set2
]
480 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
482 test
{SINTERSTORE with two sets
} {
483 $r sinterstore setres set1 set2
484 lsort [$r smembers setres
]
485 } {995 996 997 998 999}
487 test
{SUNIONSTORE with two sets
} {
488 $r sunionstore setres set1 set2
489 lsort [$r smembers setres
]
490 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
492 test
{SINTER against three sets
} {
497 lsort [$r sinter set1 set2 set3
]
500 test
{SINTERSTORE with three sets
} {
501 $r sinterstore setres set1 set2 set3
502 lsort [$r smembers setres
]
505 test
{SUNION with non existing keys
} {
506 lsort [$r sunion nokey1 set1 set2 nokey2
]
507 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
509 test
{SDIFF with two sets
} {
510 for {set i
5} {$i < 1000} {incr i
} {
513 lsort [$r sdiff set1 set4
]
516 test
{SDIFF with three sets
} {
518 lsort [$r sdiff set1 set4 set5
]
521 test
{SDIFFSTORE with three sets
} {
522 $r sdiffstore sres set1 set4 set5
523 lsort [$r smembers sres
]
531 list [lsort [list [$r spop myset
] [$r spop myset
] [$r spop myset
]]] [$r scard myset
]
534 test
{SAVE
- make sure there are all the types as values
} {
535 $r lpush mysavelist hello
536 $r lpush mysavelist world
538 $r set mynormalkey
{blablablba
}
539 $r zadd mytestzset a
10
540 $r zadd mytestzset b
20
541 $r zadd mytestzset c
30
545 test
{Create a random
list} {
547 array set seenrand
{}
548 for {set i
0} {$i < 10000} {incr i
} {
550 # Make sure all the weights are different because
551 # Redis does not use a stable sort but Tcl does.
552 set rint
[expr int
(rand
()*1000000)]
553 if {![info exists seenrand
($rint)]} break
555 set seenrand
($rint) x
557 $r set weight_
$i $rint
558 lappend tosort
[list $i $rint]
560 set sorted
[lsort -index 1 -real $tosort]
562 for {set i
0} {$i < 10000} {incr i
} {
563 lappend res
[lindex $sorted $i 0]
568 test
{SORT with BY against the newly created
list} {
569 $r sort tosort
{BY weight_
*}
572 test
{SORT direct
, numeric
, against the newly created
list} {
574 } [lsort -integer $res]
576 test
{SORT decreasing sort
} {
577 $r sort tosort
{DESC
}
578 } [lsort -decreasing -integer $res]
580 test
{SORT speed
, sorting
10000 elements
list using BY
, 100 times
} {
581 set start
[clock clicks
-milliseconds]
582 for {set i
0} {$i < 100} {incr i
} {
583 set sorted
[$r sort tosort
{BY weight_
* LIMIT
0 10}]
585 set elapsed
[expr [clock clicks
-milliseconds]-$start]
586 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
591 test
{SORT speed
, sorting
10000 elements
list directly
, 100 times
} {
592 set start
[clock clicks
-milliseconds]
593 for {set i
0} {$i < 100} {incr i
} {
594 set sorted
[$r sort tosort
{LIMIT
0 10}]
596 set elapsed
[expr [clock clicks
-milliseconds]-$start]
597 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
602 test
{SORT speed
, pseudo-sorting
10000 elements
list, BY
<const
>, 100 times
} {
603 set start
[clock clicks
-milliseconds]
604 for {set i
0} {$i < 100} {incr i
} {
605 set sorted
[$r sort tosort
{BY nokey LIMIT
0 10}]
607 set elapsed
[expr [clock clicks
-milliseconds]-$start]
608 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
613 test
{SORT regression
for issue
#19, sorting floats} {
615 foreach x
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
619 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
621 test
{LREM
, remove all the occurrences
} {
625 $r rpush mylist foobar
626 $r rpush mylist foobared
631 set res
[$r lrem mylist
0 bar
]
632 list [$r lrange mylist
0 -1] $res
633 } {{foo foobar foobared zap test foo
} 2}
635 test
{LREM
, remove the first occurrence
} {
636 set res
[$r lrem mylist
1 foo
]
637 list [$r lrange mylist
0 -1] $res
638 } {{foobar foobared zap test foo
} 1}
640 test
{LREM
, remove non existing element
} {
641 set res
[$r lrem mylist
1 nosuchelement
]
642 list [$r lrange mylist
0 -1] $res
643 } {{foobar foobared zap test foo
} 0}
645 test
{LREM
, starting from tail with negative count
} {
649 $r rpush mylist foobar
650 $r rpush mylist foobared
656 set res
[$r lrem mylist
-1 bar
]
657 list [$r lrange mylist
0 -1] $res
658 } {{foo bar foobar foobared zap test foo foo
} 1}
660 test
{LREM
, starting from tail with negative count
(2)} {
661 set res
[$r lrem mylist
-2 foo
]
662 list [$r lrange mylist
0 -1] $res
663 } {{foo bar foobar foobared zap test
} 2}
665 test
{LREM
, deleting objects that may be encoded as integers
} {
666 $r lpush myotherlist
1
667 $r lpush myotherlist
2
668 $r lpush myotherlist
3
669 $r lrem myotherlist
1 2
680 test
{MGET against non existing key
} {
681 $r mget foo baazz bar
684 test
{MGET against non-string key
} {
687 $r mget foo baazz bar myset
696 for {set i
0} {$i < 100} {incr i
} {
697 set rkey
[$r randomkey
]
698 if {$rkey eq
{foo
}} {
701 if {$rkey eq
{bar
}} {
705 list $foo_seen $bar_seen
708 test
{RANDOMKEY against empty DB
} {
713 test
{RANDOMKEY regression
1} {
720 test
{GETSET
(set new value
)} {
721 list [$r getset foo xyz
] [$r get foo
]
724 test
{GETSET
(replace old value
)} {
726 list [$r getset foo xyz
] [$r get foo
]
729 test
{SMOVE basics
} {
736 $r smove myset1 myset2 a
737 list [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
740 test
{SMOVE non existing key
} {
741 list [$r smove myset1 myset2 foo
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
742 } {0 {a x y z
} {b c
}}
744 test
{SMOVE non existing src
set} {
745 list [$r smove noset myset2 foo
] [lsort [$r smembers myset2
]]
748 test
{SMOVE non existing dst
set} {
749 list [$r smove myset2 myset3 y
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset3
]]
752 test
{SMOVE wrong src key type
} {
754 catch {$r smove x myset2 foo
} err
758 test
{SMOVE wrong dst key type
} {
760 catch {$r smove myset2 x foo
} err
764 test
{MSET base case
} {
765 $r mset x
10 y
"foo bar" z
"x x x x x x x\n\n\r\n"
767 } [list 10 {foo bar
} "x x x x x x x\n\n\r\n"]
769 test
{MSET wrong number of args
} {
770 catch {$r mset x
10 y
"foo bar" z
} err
774 test
{MSETNX with already existent key
} {
775 list [$r msetnx x1 xxx y2 yyy x
20] [$r exists x1
] [$r exists y2
]
778 test
{MSETNX with not existing keys
} {
779 list [$r msetnx x1 xxx y2 yyy
] [$r get x1
] [$r get y2
]
782 test
{ZSET basic ZADD and score
update} {
786 set aux1
[$r zrange ztmp
0 -1]
788 set aux2
[$r zrange ztmp
0 -1]
795 for {set i
0} {$i < 1000} {incr i
} {
796 set score
[expr rand
()]
798 $r zadd zscoretest
$score $i
800 for {set i
0} {$i < 1000} {incr i
} {
801 if {[$r zscore zscoretest
$i] != [lindex $aux $i]} {
802 set err
"Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i"
809 test
{ZRANGE and ZREVRANGE
} {
810 list [$r zrange ztmp
0 -1] [$r zrevrange ztmp
0 -1]
813 test
{ZSETs stress tester
- sorting is working well?
} {
815 for {set test
0} {$test < 2} {incr test
} {
816 unset -nocomplain auxarray
817 array set auxarray
{}
820 for {set i
0} {$i < 1000} {incr i
} {
822 set score
[expr rand
()]
824 set score
[expr int
(rand
()*10)]
826 set auxarray
($i) $score
827 $r zadd myzset
$score $i
829 if {[expr rand
()] < .2} {
830 set j
[expr int
(rand
()*1000)]
832 set score
[expr rand
()]
834 set score
[expr int
(rand
()*10)]
836 set auxarray
($j) $score
837 $r zadd myzset
$score $j
840 foreach {item score
} [array get auxarray
] {
841 lappend auxlist
[list $score $item]
843 set sorted
[lsort -command zlistAlikeSort
$auxlist]
846 lappend auxlist
[lindex $x 1]
848 set fromredis
[$r zrange myzset
0 -1]
850 for {set i
0} {$i < [llength $fromredis]} {incr i
} {
851 if {[lindex $fromredis $i] != [lindex $auxlist $i]} {
859 test
{ZSETs skiplist implementation backlink consistency test
} {
862 for {set j
0} {$j < $elements} {incr j
} {
863 $r zadd myzset
[expr rand
()] "Element-$j"
864 $r zrem myzset
"Element-[expr int(rand()*$elements)]"
866 set l1
[$r zrange myzset
0 -1]
867 set l2
[$r zrevrange myzset
0 -1]
868 for {set j
0} {$j < [llength $l1]} {incr j
} {
869 if {[lindex $l1 $j] ne
[lindex $l2 end-
$j]} {
876 foreach fuzztype
{binary alpha compr
} {
877 test
"FUZZ stresser with data model $fuzztype" {
879 for {set i
0} {$i < 10000} {incr i
} {
880 set fuzz
[randstring
0 512 $fuzztype]
884 set err
[list $fuzz $got]
892 # Leave the user with a clean DB before to exit
897 lappend aux
[$r dbsize
]
900 lappend aux
[$r dbsize
]
903 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
905 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
915 set randkey
[expr int
(rand
()*10000)]
916 set randval
[expr int
(rand
()*10000)]
917 set randidx0
[expr int
(rand
()*10)]
918 set randidx1
[expr int
(rand
()*10)]
919 set cmd
[expr int
(rand
()*10)]
921 if {$cmd == 0} {$r set $randkey $randval}
922 if {$cmd == 1} {$r get
$randkey}
923 if {$cmd == 2} {$r incr $randkey}
924 if {$cmd == 3} {$r lpush
$randkey $randval}
925 if {$cmd == 4} {$r rpop
$randkey}
926 if {$cmd == 5} {$r del
$randkey}
927 if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
928 if {$cmd == 7} {$r ltrim
$randkey $randidx0 $randidx1}
929 if {$cmd == 8} {$r lindex $randkey $randidx0}
930 if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
938 # Before to run the test check if DB 9 and DB 10 are empty
941 set db9size
[$r dbsize
]
943 set db10size
[$r dbsize
]
944 if {$db9size != 0 ||
$db10size != 0} {
945 puts "Can't run the tests against DB 9 and 10: DBs are not empty."
953 if {[llength $argv] == 0} {
955 } elseif
{[llength $argv] == 1 && [lindex $argv 0] eq
{stress
}} {
958 main
[lindex $argv 0] [lindex $argv 1]