1 # TODO # test pipelining
3 source client-libraries
/tcl
/redis.tcl
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 proc main
{server port
} {
42 set r
[redis
$server $port]
45 # The following AUTH test should be enabled only when requirepass
46 # <PASSWORD> is set in redis.conf and redis-server was started with
47 # redis.conf as the first argument.
49 #test {AUTH with requirepass in redis.conf} {
53 test
{DEL all keys to start with a clean DB
} {
54 foreach key
[$r keys
*] {$r del
$key}
58 test
{SET and GET an item
} {
63 test
{DEL against a single item
} {
72 list [$r del foo1 foo2 foo3 foo4
] [$r mget foo1 foo2 foo3
]
75 test
{KEYS with pattern
} {
76 foreach key
{key_x key_y key_z foo_a foo_b foo_c
} {
82 test
{KEYS to get all keys
} {
84 } {foo_a foo_b foo_c key_x key_y key_z
}
91 foreach key
[$r keys
*] {$r del
$key}
95 test
{Very big payload in GET
/SET
} {
96 set buf
[string repeat
"abcd" 1000000]
99 } [string repeat
"abcd" 1000000]
101 test
{SET
10000 numeric keys and access all them in reverse order
} {
102 for {set x
0} {$x < 10000} {incr x
} {
106 for {set x
9999} {$x >= 0} {incr x
-1} {
112 test
{DBSIZE should be
10001 now
} {
116 test
{INCR against non existing key
} {
118 append res
[$r incr novar
]
119 append res
[$r get novar
]
122 test
{INCR against key created by
incr itself
} {
126 test
{INCR against key originally
set with SET
} {
131 test
{INCR over
32bit value
} {
132 $r set novar
17179869184
136 test
{INCRBY over
32bit value with over
32bit increment
} {
137 $r set novar
17179869184
138 $r incrby novar
17179869184
141 test
{DECRBY over
32bit value with over
32bit increment
, negative res
} {
142 $r set novar
17179869184
143 $r decrby novar
17179869185
146 test
{SETNX target key missing
} {
147 $r setnx novar2 foobared
151 test
{SETNX target key exists
} {
152 $r setnx novar2 blabla
159 append res
[$r exists newkey
]
161 append res
[$r exists newkey
]
164 test
{Zero length value in key. SET
/GET
/EXISTS
} {
166 set res
[$r get emptykey
]
167 append res
[$r exists emptykey
]
169 append res
[$r exists emptykey
]
172 test
{Commands pipelining
} {
174 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
177 append res
[string match OK
* [::redis::redis_read_reply $fd]]
178 append res
[::redis::redis_read_reply $fd]
179 append res
[string match PONG
* [::redis::redis_read_reply $fd]]
183 test
{Non existing command
} {
184 catch {$r foobaredcommand
} err
185 string match ERR
* $err
188 test
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} {
192 set res
[$r llen mylist
]
193 append res
[$r lindex mylist
0]
194 append res
[$r lindex mylist
1]
195 append res
[$r lindex mylist
2]
203 test
{Create a long
list and check every single element with LINDEX
} {
205 for {set i
0} {$i < 1000} {incr i
} {
208 for {set i
0} {$i < 1000} {incr i
} {
209 if {[$r lindex mylist
$i] eq
$i} {incr ok
}
210 if {[$r lindex mylist
[expr (-$i)-1]] eq
[expr 999-$i]} {
217 test
{Test elements with LINDEX in random access
} {
219 for {set i
0} {$i < 1000} {incr i
} {
220 set rint
[expr int
(rand
()*1000)]
221 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
222 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
229 test
{LLEN against non-list value
error} {
232 catch {$r llen mylist
} err
236 test
{LINDEX against non-list value
error} {
237 catch {$r lindex mylist
0} err
241 test
{LPUSH against non-list value
error} {
242 catch {$r lpush mylist
0} err
246 test
{RPUSH against non-list value
error} {
247 catch {$r rpush mylist
0} err
251 test
{RENAME basic usage
} {
253 $r rename mykey mykey1
254 $r rename mykey1 mykey2
258 test
{RENAME
source key should no longer exist
} {
262 test
{RENAME against already existing key
} {
265 $r rename mykey2 mykey
266 set res
[$r get mykey
]
267 append res
[$r exists mykey2
]
270 test
{RENAMENX basic usage
} {
274 $r renamenx mykey mykey2
275 set res
[$r get mykey2
]
276 append res
[$r exists mykey
]
279 test
{RENAMENX against already existing key
} {
282 $r renamenx mykey mykey2
285 test
{RENAMENX against already existing key
(2)} {
286 set res
[$r get mykey
]
287 append res
[$r get mykey2
]
290 test
{RENAME against non existing
source key
} {
291 catch {$r rename nokey foobar
} err
295 test
{RENAME where
source and dest key is the same
} {
296 catch {$r rename mykey mykey
} err
300 test
{DEL all keys again
(DB
0)} {
301 foreach key
[$r keys
*] {
307 test
{DEL all keys again
(DB
1)} {
309 foreach key
[$r keys
*] {
317 test
{MOVE basic usage
} {
321 lappend res
[$r exists mykey
]
322 lappend res
[$r dbsize
]
324 lappend res
[$r get mykey
]
325 lappend res
[$r dbsize
]
328 } [list 0 0 foobar
1]
330 test
{MOVE against key existing in the target DB
} {
335 test
{SET
/GET keys in different DBs
} {
343 lappend res
[$r get a
]
344 lappend res
[$r get b
]
346 lappend res
[$r get a
]
347 lappend res
[$r get b
]
350 } {hello world foo bared
}
352 test
{Basic LPOP
/RPOP
} {
357 list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
]
360 test
{LPOP
/RPOP against empty
list} {
364 test
{LPOP against non
list value
} {
366 catch {$r lpop notalist
} err
370 test
{Mass LPUSH
/LPOP
} {
372 for {set i
0} {$i < 1000} {incr i
} {
377 for {set i
0} {$i < 500} {incr i
} {
378 incr sum2
[$r lpop mylist
]
379 incr sum2
[$r rpop mylist
]
384 test
{LRANGE basics
} {
385 for {set i
0} {$i < 10} {incr i
} {
388 list [$r lrange mylist
1 -2] \
389 [$r lrange mylist
-3 -1] \
390 [$r lrange mylist
4 4]
391 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
393 test
{LRANGE inverted indexes
} {
397 test
{LRANGE out of range indexes including the full
list} {
398 $r lrange mylist
-1000 1000
399 } {0 1 2 3 4 5 6 7 8 9}
401 test
{LRANGE against non existing key
} {
402 $r lrange nosuchkey
0 1
405 test
{LTRIM basics
} {
407 for {set i
0} {$i < 100} {incr i
} {
411 $r lrange mylist
0 -1
416 $r lset mylist
-1 bar
417 $r lrange mylist
0 -1
420 test
{LSET out of range index
} {
421 catch {$r lset mylist
10 foo
} err
425 test
{LSET against non existing key
} {
426 catch {$r lset nosuchkey
10 foo
} err
430 test
{LSET against non
list value
} {
432 catch {$r lset nolist
0 foo
} err
436 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} {
439 list [$r scard myset
] [$r sismember myset foo
] \
440 [$r sismember myset bar
] [$r sismember myset bla
] \
441 [lsort [$r smembers myset
]]
442 } {2 1 1 0 {bar foo
}}
444 test
{SADD adding the same element multiple times
} {
451 test
{SADD against non
set} {
452 catch {$r sadd mylist foo
} err
459 lsort [$r smembers myset
]
462 test
{Mass SADD and SINTER with two sets
} {
463 for {set i
0} {$i < 1000} {incr i
} {
465 $r sadd set2
[expr $i+995]
467 lsort [$r sinter set1 set2
]
468 } {995 996 997 998 999}
470 test
{SUNION with two sets
} {
471 lsort [$r sunion set1 set2
]
472 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
474 test
{SINTERSTORE with two sets
} {
475 $r sinterstore setres set1 set2
476 lsort [$r smembers setres
]
477 } {995 996 997 998 999}
479 test
{SUNIONSTORE with two sets
} {
480 $r sunionstore setres set1 set2
481 lsort [$r smembers setres
]
482 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
484 test
{SUNIONSTORE with same src and dest
} {
485 $r sunionstore set1 set1 set1
489 test
{SINTER against three sets
} {
494 lsort [$r sinter set1 set2 set3
]
497 test
{SINTERSTORE with three sets
} {
498 $r sinterstore setres set1 set2 set3
499 lsort [$r smembers setres
]
502 test
{SINTERSTORE with same src and dest
} {
503 $r sinterstore set1 set1 set1
507 test
{SUNION with non existing keys
} {
508 lsort [$r sunion nokey1 set1 set2 nokey2
]
509 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
511 test
{SDIFF with two sets
} {
512 for {set i
5} {$i < 1000} {incr i
} {
515 lsort [$r sdiff set1 set4
]
518 test
{SDIFF with three sets
} {
520 lsort [$r sdiff set1 set4 set5
]
523 test
{SDIFFSTORE with three sets
} {
524 $r sdiffstore sres set1 set4 set5
525 lsort [$r smembers sres
]
528 test
{SAVE
- make sure there are all the types as values
} {
529 $r lpush mysavelist hello
530 $r lpush mysavelist world
532 $r set mynormalkey
{blablablba
}
536 test
{Create a random
list} {
538 array set seenrand
{}
539 for {set i
0} {$i < 10000} {incr i
} {
541 # Make sure all the weights are different because
542 # Redis does not use a stable sort but Tcl does.
543 set rint
[expr int
(rand
()*1000000)]
544 if {![info exists seenrand
($rint)]} break
546 set seenrand
($rint) x
548 $r set weight_
$i $rint
549 lappend tosort
[list $i $rint]
551 set sorted
[lsort -index 1 -real $tosort]
553 for {set i
0} {$i < 10000} {incr i
} {
554 lappend res
[lindex $sorted $i 0]
559 test
{SORT with BY against the newly created
list} {
560 $r sort tosort
{BY weight_
*}
563 test
{SORT direct
, numeric
, against the newly created
list} {
565 } [lsort -integer $res]
567 test
{SORT decreasing sort
} {
568 $r sort tosort
{DESC
}
569 } [lsort -decreasing -integer $res]
571 test
{SORT speed
, sorting
10000 elements
list using BY
, 100 times
} {
572 set start
[clock clicks
-milliseconds]
573 for {set i
0} {$i < 100} {incr i
} {
574 set sorted
[$r sort tosort
{BY weight_
* LIMIT
0 10}]
576 set elapsed
[expr [clock clicks
-milliseconds]-$start]
577 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
582 test
{SORT speed
, sorting
10000 elements
list directly
, 100 times
} {
583 set start
[clock clicks
-milliseconds]
584 for {set i
0} {$i < 100} {incr i
} {
585 set sorted
[$r sort tosort
{LIMIT
0 10}]
587 set elapsed
[expr [clock clicks
-milliseconds]-$start]
588 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
593 test
{SORT speed
, pseudo-sorting
10000 elements
list, BY
<const
>, 100 times
} {
594 set start
[clock clicks
-milliseconds]
595 for {set i
0} {$i < 100} {incr i
} {
596 set sorted
[$r sort tosort
{BY nokey LIMIT
0 10}]
598 set elapsed
[expr [clock clicks
-milliseconds]-$start]
599 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
604 test
{SORT regression
for issue
#19, sorting floats} {
606 foreach x
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
610 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
612 test
{LREM
, remove all the occurrences
} {
616 $r rpush mylist foobar
617 $r rpush mylist foobared
622 set res
[$r lrem mylist
0 bar
]
623 list [$r lrange mylist
0 -1] $res
624 } {{foo foobar foobared zap test foo
} 2}
626 test
{LREM
, remove the first occurrence
} {
627 set res
[$r lrem mylist
1 foo
]
628 list [$r lrange mylist
0 -1] $res
629 } {{foobar foobared zap test foo
} 1}
631 test
{LREM
, remove non existing element
} {
632 set res
[$r lrem mylist
1 nosuchelement
]
633 list [$r lrange mylist
0 -1] $res
634 } {{foobar foobared zap test foo
} 0}
636 test
{LREM
, starting from tail with negative count
} {
640 $r rpush mylist foobar
641 $r rpush mylist foobared
647 set res
[$r lrem mylist
-1 bar
]
648 list [$r lrange mylist
0 -1] $res
649 } {{foo bar foobar foobared zap test foo foo
} 1}
651 test
{LREM
, starting from tail with negative count
(2)} {
652 set res
[$r lrem mylist
-2 foo
]
653 list [$r lrange mylist
0 -1] $res
654 } {{foo bar foobar foobared zap test
} 2}
663 test
{MGET against non existing key
} {
664 $r mget foo baazz bar
667 test
{MGET against non-string key
} {
670 $r mget foo baazz bar myset
679 for {set i
0} {$i < 100} {incr i
} {
680 set rkey
[$r randomkey
]
681 if {$rkey eq
{foo
}} {
684 if {$rkey eq
{bar
}} {
688 list $foo_seen $bar_seen
691 test
{RANDOMKEY against empty DB
} {
696 test
{RANDOMKEY regression
1} {
703 test
{GETSET
(set new value
)} {
704 list [$r getset foo xyz
] [$r get foo
]
707 test
{GETSET
(replace old value
)} {
709 list [$r getset foo xyz
] [$r get foo
]
712 test
{SMOVE basics
} {
719 $r smove myset1 myset2 a
720 list [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
723 test
{SMOVE non existing key
} {
724 list [$r smove myset1 myset2 foo
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
725 } {0 {a x y z
} {b c
}}
727 test
{SMOVE non existing src
set} {
728 list [$r smove noset myset2 foo
] [lsort [$r smembers myset2
]]
731 test
{SMOVE non existing dst
set} {
732 list [$r smove myset2 myset3 y
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset3
]]
735 test
{SMOVE wrong src key type
} {
737 catch {$r smove x myset2 foo
} err
741 test
{SMOVE wrong dst key type
} {
743 catch {$r smove myset2 x foo
} err
747 foreach fuzztype
{binary alpha compr
} {
748 test
"FUZZ stresser with data model $fuzztype" {
750 for {set i
0} {$i < 1000} {incr i
} {
751 set fuzz
[randstring
0 512 $fuzztype]
763 # Leave the user with a clean DB before to exit
769 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
771 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
780 set randkey
[expr int
(rand
()*10000)]
781 set randval
[expr int
(rand
()*10000)]
782 set randidx0
[expr int
(rand
()*10)]
783 set randidx1
[expr int
(rand
()*10)]
784 set cmd
[expr int
(rand
()*10)]
786 if {$cmd == 0} {$r set $randkey $randval}
787 if {$cmd == 1} {$r get
$randkey}
788 if {$cmd == 2} {$r incr $randkey}
789 if {$cmd == 3} {$r lpush
$randkey $randval}
790 if {$cmd == 4} {$r rpop
$randkey}
791 if {$cmd == 5} {$r del
$randkey}
792 if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
793 if {$cmd == 7} {$r ltrim
$randkey $randidx0 $randidx1}
794 if {$cmd == 8} {$r lindex $randkey $randidx0}
795 if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
802 if {[llength $argv] == 0} {
804 } elseif
{[llength $argv] == 1 && [lindex $argv 0] eq
{stress
}} {
807 main
[lindex $argv 0] [lindex $argv 1]