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
} {
68 test
{KEYS with pattern
} {
69 foreach key
{key_x key_y key_z foo_a foo_b foo_c
} {
75 test
{KEYS to get all keys
} {
77 } {foo_a foo_b foo_c key_x key_y key_z
}
84 foreach key
[$r keys
*] {$r del
$key}
88 test
{Very big payload in GET
/SET
} {
89 set buf
[string repeat
"abcd" 1000000]
92 } [string repeat
"abcd" 1000000]
94 test
{SET
10000 numeric keys and access all them in reverse order
} {
95 for {set x
0} {$x < 10000} {incr x
} {
99 for {set x
9999} {$x >= 0} {incr x
-1} {
105 test
{DBSIZE should be
10001 now
} {
109 test
{INCR against non existing key
} {
111 append res
[$r incr novar
]
112 append res
[$r get novar
]
115 test
{INCR against key created by
incr itself
} {
119 test
{INCR against key originally
set with SET
} {
124 test
{INCR over
32bit value
} {
125 $r set novar
17179869184
129 test
{INCRBY over
32bit value with over
32bit increment
} {
130 $r set novar
17179869184
131 $r incrby novar
17179869184
134 test
{DECRBY over
32bit value with over
32bit increment
, negative res
} {
135 $r set novar
17179869184
136 $r decrby novar
17179869185
139 test
{SETNX target key missing
} {
140 $r setnx novar2 foobared
144 test
{SETNX target key exists
} {
145 $r setnx novar2 blabla
152 append res
[$r exists newkey
]
154 append res
[$r exists newkey
]
157 test
{Zero length value in key. SET
/GET
/EXISTS
} {
159 set res
[$r get emptykey
]
160 append res
[$r exists emptykey
]
162 append res
[$r exists emptykey
]
165 test
{Commands pipelining
} {
167 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
170 append res
[string match OK
* [::redis::redis_read_reply $fd]]
171 append res
[::redis::redis_read_reply $fd]
172 append res
[string match PONG
* [::redis::redis_read_reply $fd]]
176 test
{Non existing command
} {
177 catch {$r foobaredcommand
} err
178 string match ERR
* $err
181 test
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} {
185 set res
[$r llen mylist
]
186 append res
[$r lindex mylist
0]
187 append res
[$r lindex mylist
1]
188 append res
[$r lindex mylist
2]
196 test
{Create a long
list and check every single element with LINDEX
} {
198 for {set i
0} {$i < 1000} {incr i
} {
201 for {set i
0} {$i < 1000} {incr i
} {
202 if {[$r lindex mylist
$i] eq
$i} {incr ok
}
203 if {[$r lindex mylist
[expr (-$i)-1]] eq
[expr 999-$i]} {
210 test
{Test elements with LINDEX in random access
} {
212 for {set i
0} {$i < 1000} {incr i
} {
213 set rint
[expr int
(rand
()*1000)]
214 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
215 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
222 test
{LLEN against non-list value
error} {
225 catch {$r llen mylist
} err
229 test
{LINDEX against non-list value
error} {
230 catch {$r lindex mylist
0} err
234 test
{LPUSH against non-list value
error} {
235 catch {$r lpush mylist
0} err
239 test
{RPUSH against non-list value
error} {
240 catch {$r rpush mylist
0} err
244 test
{RENAME basic usage
} {
246 $r rename mykey mykey1
247 $r rename mykey1 mykey2
251 test
{RENAME
source key should no longer exist
} {
255 test
{RENAME against already existing key
} {
258 $r rename mykey2 mykey
259 set res
[$r get mykey
]
260 append res
[$r exists mykey2
]
263 test
{RENAMENX basic usage
} {
267 $r renamenx mykey mykey2
268 set res
[$r get mykey2
]
269 append res
[$r exists mykey
]
272 test
{RENAMENX against already existing key
} {
275 $r renamenx mykey mykey2
278 test
{RENAMENX against already existing key
(2)} {
279 set res
[$r get mykey
]
280 append res
[$r get mykey2
]
283 test
{RENAME against non existing
source key
} {
284 catch {$r rename nokey foobar
} err
288 test
{RENAME where
source and dest key is the same
} {
289 catch {$r rename mykey mykey
} err
293 test
{DEL all keys again
(DB
0)} {
294 foreach key
[$r keys
*] {
300 test
{DEL all keys again
(DB
1)} {
302 foreach key
[$r keys
*] {
310 test
{MOVE basic usage
} {
314 lappend res
[$r exists mykey
]
315 lappend res
[$r dbsize
]
317 lappend res
[$r get mykey
]
318 lappend res
[$r dbsize
]
321 } [list 0 0 foobar
1]
323 test
{MOVE against key existing in the target DB
} {
328 test
{SET
/GET keys in different DBs
} {
336 lappend res
[$r get a
]
337 lappend res
[$r get b
]
339 lappend res
[$r get a
]
340 lappend res
[$r get b
]
343 } {hello world foo bared
}
345 test
{Basic LPOP
/RPOP
} {
350 list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
]
353 test
{LPOP
/RPOP against empty
list} {
357 test
{LPOP against non
list value
} {
359 catch {$r lpop notalist
} err
363 test
{Mass LPUSH
/LPOP
} {
365 for {set i
0} {$i < 1000} {incr i
} {
370 for {set i
0} {$i < 500} {incr i
} {
371 incr sum2
[$r lpop mylist
]
372 incr sum2
[$r rpop mylist
]
377 test
{LRANGE basics
} {
378 for {set i
0} {$i < 10} {incr i
} {
381 list [$r lrange mylist
1 -2] \
382 [$r lrange mylist
-3 -1] \
383 [$r lrange mylist
4 4]
384 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
386 test
{LRANGE inverted indexes
} {
390 test
{LRANGE out of range indexes including the full
list} {
391 $r lrange mylist
-1000 1000
392 } {0 1 2 3 4 5 6 7 8 9}
394 test
{LRANGE against non existing key
} {
395 $r lrange nosuchkey
0 1
398 test
{LTRIM basics
} {
400 for {set i
0} {$i < 100} {incr i
} {
404 $r lrange mylist
0 -1
409 $r lset mylist
-1 bar
410 $r lrange mylist
0 -1
413 test
{LSET out of range index
} {
414 catch {$r lset mylist
10 foo
} err
418 test
{LSET against non existing key
} {
419 catch {$r lset nosuchkey
10 foo
} err
423 test
{LSET against non
list value
} {
425 catch {$r lset nolist
0 foo
} err
429 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} {
432 list [$r scard myset
] [$r sismember myset foo
] \
433 [$r sismember myset bar
] [$r sismember myset bla
] \
434 [lsort [$r smembers myset
]]
435 } {2 1 1 0 {bar foo
}}
437 test
{SADD adding the same element multiple times
} {
444 test
{SADD against non
set} {
445 catch {$r sadd mylist foo
} err
452 lsort [$r smembers myset
]
455 test
{Mass SADD and SINTER with two sets
} {
456 for {set i
0} {$i < 1000} {incr i
} {
458 $r sadd set2
[expr $i+995]
460 lsort [$r sinter set1 set2
]
461 } {995 996 997 998 999}
463 test
{SUNION with two sets
} {
464 lsort [$r sunion set1 set2
]
465 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
467 test
{SINTERSTORE with two sets
} {
468 $r sinterstore setres set1 set2
469 lsort [$r smembers setres
]
470 } {995 996 997 998 999}
472 test
{SUNIONSTORE with two sets
} {
473 $r sunionstore setres set1 set2
474 lsort [$r smembers setres
]
475 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
477 test
{SINTER against three sets
} {
482 lsort [$r sinter set1 set2 set3
]
485 test
{SINTERSTORE with three sets
} {
486 $r sinterstore setres set1 set2 set3
487 lsort [$r smembers setres
]
490 test
{SUNION with non existing keys
} {
491 lsort [$r sunion nokey1 set1 set2 nokey2
]
492 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
494 test
{SAVE
- make sure there are all the types as values
} {
495 $r lpush mysavelist hello
496 $r lpush mysavelist world
498 $r set mynormalkey
{blablablba
}
502 test
{Create a random
list} {
504 array set seenrand
{}
505 for {set i
0} {$i < 10000} {incr i
} {
507 # Make sure all the weights are different because
508 # Redis does not use a stable sort but Tcl does.
509 set rint
[expr int
(rand
()*1000000)]
510 if {![info exists seenrand
($rint)]} break
512 set seenrand
($rint) x
514 $r set weight_
$i $rint
515 lappend tosort
[list $i $rint]
517 set sorted
[lsort -index 1 -real $tosort]
519 for {set i
0} {$i < 10000} {incr i
} {
520 lappend res
[lindex $sorted $i 0]
525 test
{SORT with BY against the newly created
list} {
526 $r sort tosort
{BY weight_
*}
529 test
{SORT direct
, numeric
, against the newly created
list} {
531 } [lsort -integer $res]
533 test
{SORT decreasing sort
} {
534 $r sort tosort
{DESC
}
535 } [lsort -decreasing -integer $res]
537 test
{SORT speed
, sorting
10000 elements
list using BY
, 100 times
} {
538 set start
[clock clicks
-milliseconds]
539 for {set i
0} {$i < 100} {incr i
} {
540 set sorted
[$r sort tosort
{BY weight_
* LIMIT
0 10}]
542 set elapsed
[expr [clock clicks
-milliseconds]-$start]
543 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
548 test
{SORT speed
, sorting
10000 elements
list directly
, 100 times
} {
549 set start
[clock clicks
-milliseconds]
550 for {set i
0} {$i < 100} {incr i
} {
551 set sorted
[$r sort tosort
{LIMIT
0 10}]
553 set elapsed
[expr [clock clicks
-milliseconds]-$start]
554 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
559 test
{SORT speed
, pseudo-sorting
10000 elements
list, BY
<const
>, 100 times
} {
560 set start
[clock clicks
-milliseconds]
561 for {set i
0} {$i < 100} {incr i
} {
562 set sorted
[$r sort tosort
{BY nokey LIMIT
0 10}]
564 set elapsed
[expr [clock clicks
-milliseconds]-$start]
565 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
570 test
{SORT regression
for issue
#19, sorting floats} {
572 foreach x
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
576 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
578 test
{LREM
, remove all the occurrences
} {
582 $r rpush mylist foobar
583 $r rpush mylist foobared
588 set res
[$r lrem mylist
0 bar
]
589 list [$r lrange mylist
0 -1] $res
590 } {{foo foobar foobared zap test foo
} 2}
592 test
{LREM
, remove the first occurrence
} {
593 set res
[$r lrem mylist
1 foo
]
594 list [$r lrange mylist
0 -1] $res
595 } {{foobar foobared zap test foo
} 1}
597 test
{LREM
, remove non existing element
} {
598 set res
[$r lrem mylist
1 nosuchelement
]
599 list [$r lrange mylist
0 -1] $res
600 } {{foobar foobared zap test foo
} 0}
602 test
{LREM
, starting from tail with negative count
} {
606 $r rpush mylist foobar
607 $r rpush mylist foobared
613 set res
[$r lrem mylist
-1 bar
]
614 list [$r lrange mylist
0 -1] $res
615 } {{foo bar foobar foobared zap test foo foo
} 1}
617 test
{LREM
, starting from tail with negative count
(2)} {
618 set res
[$r lrem mylist
-2 foo
]
619 list [$r lrange mylist
0 -1] $res
620 } {{foo bar foobar foobared zap test
} 2}
629 test
{MGET against non existing key
} {
630 $r mget foo baazz bar
633 test
{MGET against non-string key
} {
636 $r mget foo baazz bar myset
645 for {set i
0} {$i < 100} {incr i
} {
646 set rkey
[$r randomkey
]
647 if {$rkey eq
{foo
}} {
650 if {$rkey eq
{bar
}} {
654 list $foo_seen $bar_seen
657 test
{RANDOMKEY against empty DB
} {
662 test
{RANDOMKEY regression
1} {
669 test
{GETSET
(set new value
)} {
670 list [$r getset foo xyz
] [$r get foo
]
673 test
{GETSET
(replace old value
)} {
675 list [$r getset foo xyz
] [$r get foo
]
678 test
{SMOVE basics
} {
685 $r smove myset1 myset2 a
686 list [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
689 test
{SMOVE non existing key
} {
690 list [$r smove myset1 myset2 foo
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset1
]]
691 } {0 {a x y z
} {b c
}}
693 test
{SMOVE non existing src
set} {
694 list [$r smove noset myset2 foo
] [lsort [$r smembers myset2
]]
697 test
{SMOVE non existing dst
set} {
698 list [$r smove myset2 myset3 y
] [lsort [$r smembers myset2
]] [lsort [$r smembers myset3
]]
701 test
{SMOVE wrong src key type
} {
703 catch {$r smove x myset2 foo
} err
707 test
{SMOVE wrong dst key type
} {
709 catch {$r smove myset2 x foo
} err
713 foreach fuzztype
{binary alpha compr
} {
714 test
"FUZZ stresser with data model $fuzztype" {
716 for {set i
0} {$i < 1000} {incr i
} {
717 set fuzz
[randstring
0 512 $fuzztype]
729 # Leave the user with a clean DB before to exit
735 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
737 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
746 set randkey
[expr int
(rand
()*10000)]
747 set randval
[expr int
(rand
()*10000)]
748 set randidx0
[expr int
(rand
()*10)]
749 set randidx1
[expr int
(rand
()*10)]
750 set cmd
[expr int
(rand
()*10)]
752 if {$cmd == 0} {$r set $randkey $randval}
753 if {$cmd == 1} {$r get
$randkey}
754 if {$cmd == 2} {$r incr $randkey}
755 if {$cmd == 3} {$r lpush
$randkey $randval}
756 if {$cmd == 4} {$r rpop
$randkey}
757 if {$cmd == 5} {$r del
$randkey}
758 if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
759 if {$cmd == 7} {$r ltrim
$randkey $randidx0 $randidx1}
760 if {$cmd == 8} {$r lindex $randkey $randidx0}
761 if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
768 if {[llength $argv] == 0} {
770 } elseif
{[llength $argv] == 1 && [lindex $argv 0] eq
{stress
}} {
773 main
[lindex $argv 0] [lindex $argv 1]