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 main
{server port
} {
22 set r
[redis
$server $port]
25 # The following AUTH test should be enabled only when requirepass
26 # <PASSWORD> is set in redis.conf and redis-server was started with
27 # redis.conf as the first argument.
29 #test {AUTH with requirepass in redis.conf} {
33 test
{DEL all keys to start with a clean DB
} {
34 foreach key
[$r keys
*] {$r del
$key}
38 test
{SET and GET an item
} {
43 test
{DEL against a single item
} {
48 test
{KEYS with pattern
} {
49 foreach key
{key_x key_y key_z foo_a foo_b foo_c
} {
55 test
{KEYS to get all keys
} {
57 } {foo_a foo_b foo_c key_x key_y key_z
}
64 foreach key
[$r keys
*] {$r del
$key}
68 test
{Very big payload in GET
/SET
} {
69 set buf
[string repeat
"abcd" 1000000]
72 } [string repeat
"abcd" 1000000]
74 test
{SET
10000 numeric keys and access all them in reverse order
} {
75 for {set x
0} {$x < 10000} {incr x
} {
79 for {set x
9999} {$x >= 0} {incr x
-1} {
85 test
{DBSIZE should be
10001 now
} {
89 test
{INCR against non existing key
} {
91 append res
[$r incr novar
]
92 append res
[$r get novar
]
95 test
{INCR against key created by
incr itself
} {
99 test
{INCR against key originally
set with SET
} {
104 test
{INCR over
32bit value
} {
105 $r set novar
17179869184
109 test
{INCRBY over
32bit value with over
32bit increment
} {
110 $r set novar
17179869184
111 $r incrby novar
17179869184
114 test
{DECRBY over
32bit value with over
32bit increment
, negative res
} {
115 $r set novar
17179869184
116 $r decrby novar
17179869185
119 test
{SETNX target key missing
} {
120 $r setnx novar2 foobared
124 test
{SETNX target key exists
} {
125 $r setnx novar2 blabla
132 append res
[$r exists newkey
]
134 append res
[$r exists newkey
]
137 test
{Zero length value in key. SET
/GET
/EXISTS
} {
139 set res
[$r get emptykey
]
140 append res
[$r exists emptykey
]
142 append res
[$r exists emptykey
]
145 test
{Commands pipelining
} {
147 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
150 append res
[string match OK
* [::redis::redis_read_reply $fd]]
151 append res
[::redis::redis_read_reply $fd]
152 append res
[string match PONG
* [::redis::redis_read_reply $fd]]
156 test
{Non existing command
} {
157 catch {$r foobaredcommand
} err
158 string match ERR
* $err
161 test
{Basic LPUSH
, RPUSH
, LLENGTH
, LINDEX
} {
165 set res
[$r llen mylist
]
166 append res
[$r lindex mylist
0]
167 append res
[$r lindex mylist
1]
168 append res
[$r lindex mylist
2]
176 test
{Create a long
list and check every single element with LINDEX
} {
178 for {set i
0} {$i < 1000} {incr i
} {
181 for {set i
0} {$i < 1000} {incr i
} {
182 if {[$r lindex mylist
$i] eq
$i} {incr ok
}
183 if {[$r lindex mylist
[expr (-$i)-1]] eq
[expr 999-$i]} {
190 test
{Test elements with LINDEX in random access
} {
192 for {set i
0} {$i < 1000} {incr i
} {
193 set rint
[expr int
(rand
()*1000)]
194 if {[$r lindex mylist
$rint] eq
$rint} {incr ok
}
195 if {[$r lindex mylist
[expr (-$rint)-1]] eq
[expr 999-$rint]} {
202 test
{LLEN against non-list value
error} {
205 catch {$r llen mylist
} err
209 test
{LINDEX against non-list value
error} {
210 catch {$r lindex mylist
0} err
214 test
{LPUSH against non-list value
error} {
215 catch {$r lpush mylist
0} err
219 test
{RPUSH against non-list value
error} {
220 catch {$r rpush mylist
0} err
224 test
{RENAME basic usage
} {
226 $r rename mykey mykey1
227 $r rename mykey1 mykey2
231 test
{RENAME
source key should no longer exist
} {
235 test
{RENAME against already existing key
} {
238 $r rename mykey2 mykey
239 set res
[$r get mykey
]
240 append res
[$r exists mykey2
]
243 test
{RENAMENX basic usage
} {
247 $r renamenx mykey mykey2
248 set res
[$r get mykey2
]
249 append res
[$r exists mykey
]
252 test
{RENAMENX against already existing key
} {
255 $r renamenx mykey mykey2
258 test
{RENAMENX against already existing key
(2)} {
259 set res
[$r get mykey
]
260 append res
[$r get mykey2
]
263 test
{RENAME against non existing
source key
} {
264 catch {$r rename nokey foobar
} err
268 test
{RENAME where
source and dest key is the same
} {
269 catch {$r rename mykey mykey
} err
273 test
{DEL all keys again
(DB
0)} {
274 foreach key
[$r keys
*] {
280 test
{DEL all keys again
(DB
1)} {
282 foreach key
[$r keys
*] {
290 test
{MOVE basic usage
} {
294 lappend res
[$r exists mykey
]
295 lappend res
[$r dbsize
]
297 lappend res
[$r get mykey
]
298 lappend res
[$r dbsize
]
301 } [list 0 0 foobar
1]
303 test
{MOVE against key existing in the target DB
} {
308 test
{SET
/GET keys in different DBs
} {
316 lappend res
[$r get a
]
317 lappend res
[$r get b
]
319 lappend res
[$r get a
]
320 lappend res
[$r get b
]
323 } {hello world foo bared
}
325 test
{Basic LPOP
/RPOP
} {
330 list [$r lpop mylist
] [$r rpop mylist
] [$r lpop mylist
] [$r llen mylist
]
333 test
{LPOP
/RPOP against empty
list} {
337 test
{LPOP against non
list value
} {
339 catch {$r lpop notalist
} err
343 test
{Mass LPUSH
/LPOP
} {
345 for {set i
0} {$i < 1000} {incr i
} {
350 for {set i
0} {$i < 500} {incr i
} {
351 incr sum2
[$r lpop mylist
]
352 incr sum2
[$r rpop mylist
]
357 test
{LRANGE basics
} {
358 for {set i
0} {$i < 10} {incr i
} {
361 list [$r lrange mylist
1 -2] \
362 [$r lrange mylist
-3 -1] \
363 [$r lrange mylist
4 4]
364 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
366 test
{LRANGE inverted indexes
} {
370 test
{LRANGE out of range indexes including the full
list} {
371 $r lrange mylist
-1000 1000
372 } {0 1 2 3 4 5 6 7 8 9}
374 test
{LRANGE against non existing key
} {
375 $r lrange nosuchkey
0 1
378 test
{LTRIM basics
} {
380 for {set i
0} {$i < 100} {incr i
} {
384 $r lrange mylist
0 -1
389 $r lset mylist
-1 bar
390 $r lrange mylist
0 -1
393 test
{LSET out of range index
} {
394 catch {$r lset mylist
10 foo
} err
398 test
{LSET against non existing key
} {
399 catch {$r lset nosuchkey
10 foo
} err
403 test
{LSET against non
list value
} {
405 catch {$r lset nolist
0 foo
} err
409 test
{SADD
, SCARD
, SISMEMBER
, SMEMBERS basics
} {
412 list [$r scard myset
] [$r sismember myset foo
] \
413 [$r sismember myset bar
] [$r sismember myset bla
] \
414 [lsort [$r smembers myset
]]
415 } {2 1 1 0 {bar foo
}}
417 test
{SADD adding the same element multiple times
} {
424 test
{SADD against non
set} {
425 catch {$r sadd mylist foo
} err
432 lsort [$r smembers myset
]
435 test
{Mass SADD and SINTER with two sets
} {
436 for {set i
0} {$i < 1000} {incr i
} {
438 $r sadd set2
[expr $i+995]
440 lsort [$r sinter set1 set2
]
441 } {995 996 997 998 999}
443 test
{SUNION with two sets
} {
444 lsort [$r sunion set1 set2
]
445 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
447 test
{SINTERSTORE with two sets
} {
448 $r sinterstore setres set1 set2
449 lsort [$r smembers setres
]
450 } {995 996 997 998 999}
452 test
{SUNIONSTORE with two sets
} {
453 $r sunionstore setres set1 set2
454 lsort [$r smembers setres
]
455 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
457 test
{SINTER against three sets
} {
462 lsort [$r sinter set1 set2 set3
]
465 test
{SINTERSTORE with three sets
} {
466 $r sinterstore setres set1 set2 set3
467 lsort [$r smembers setres
]
470 test
{SUNION with non existing keys
} {
471 lsort [$r sunion nokey1 set1 set2 nokey2
]
472 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
474 test
{SAVE
- make sure there are all the types as values
} {
475 $r lpush mysavelist hello
476 $r lpush mysavelist world
478 $r set mynormalkey
{blablablba
}
482 test
{Create a random
list} {
484 array set seenrand
{}
485 for {set i
0} {$i < 10000} {incr i
} {
487 # Make sure all the weights are different because
488 # Redis does not use a stable sort but Tcl does.
489 set rint
[expr int
(rand
()*1000000)]
490 if {![info exists seenrand
($rint)]} break
492 set seenrand
($rint) x
494 $r set weight_
$i $rint
495 lappend tosort
[list $i $rint]
497 set sorted
[lsort -index 1 -real $tosort]
499 for {set i
0} {$i < 10000} {incr i
} {
500 lappend res
[lindex $sorted $i 0]
505 test
{SORT with BY against the newly created
list} {
506 $r sort tosort
{BY weight_
*}
509 test
{SORT direct
, numeric
, against the newly created
list} {
511 } [lsort -integer $res]
513 test
{SORT decreasing sort
} {
514 $r sort tosort
{DESC
}
515 } [lsort -decreasing -integer $res]
517 test
{SORT speed
, sorting
10000 elements
list using BY
, 100 times
} {
518 set start
[clock clicks
-milliseconds]
519 for {set i
0} {$i < 100} {incr i
} {
520 set sorted
[$r sort tosort
{BY weight_
* LIMIT
0 10}]
522 set elapsed
[expr [clock clicks
-milliseconds]-$start]
523 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
528 test
{SORT speed
, sorting
10000 elements
list directly
, 100 times
} {
529 set start
[clock clicks
-milliseconds]
530 for {set i
0} {$i < 100} {incr i
} {
531 set sorted
[$r sort tosort
{LIMIT
0 10}]
533 set elapsed
[expr [clock clicks
-milliseconds]-$start]
534 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
539 test
{SORT speed
, pseudo-sorting
10000 elements
list, BY
<const
>, 100 times
} {
540 set start
[clock clicks
-milliseconds]
541 for {set i
0} {$i < 100} {incr i
} {
542 set sorted
[$r sort tosort
{BY nokey LIMIT
0 10}]
544 set elapsed
[expr [clock clicks
-milliseconds]-$start]
545 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
550 test
{SORT regression
for issue
#19, sorting floats} {
552 foreach x
{1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
556 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
558 test
{LREM
, remove all the occurrences
} {
562 $r rpush mylist foobar
563 $r rpush mylist foobared
568 set res
[$r lrem mylist
0 bar
]
569 list [$r lrange mylist
0 -1] $res
570 } {{foo foobar foobared zap test foo
} 2}
572 test
{LREM
, remove the first occurrence
} {
573 set res
[$r lrem mylist
1 foo
]
574 list [$r lrange mylist
0 -1] $res
575 } {{foobar foobared zap test foo
} 1}
577 test
{LREM
, remove non existing element
} {
578 set res
[$r lrem mylist
1 nosuchelement
]
579 list [$r lrange mylist
0 -1] $res
580 } {{foobar foobared zap test foo
} 0}
582 test
{LREM
, starting from tail with negative count
} {
586 $r rpush mylist foobar
587 $r rpush mylist foobared
593 set res
[$r lrem mylist
-1 bar
]
594 list [$r lrange mylist
0 -1] $res
595 } {{foo bar foobar foobared zap test foo foo
} 1}
597 test
{LREM
, starting from tail with negative count
(2)} {
598 set res
[$r lrem mylist
-2 foo
]
599 list [$r lrange mylist
0 -1] $res
600 } {{foo bar foobar foobared zap test
} 2}
609 test
{MGET against non existing key
} {
610 $r mget foo baazz bar
613 test
{MGET against non-string key
} {
616 $r mget foo baazz bar myset
625 for {set i
0} {$i < 100} {incr i
} {
626 set rkey
[$r randomkey
]
627 if {$rkey eq
{foo
}} {
630 if {$rkey eq
{bar
}} {
634 list $foo_seen $bar_seen
637 test
{RANDOMKEY against empty DB
} {
642 test
{RANDOMKEY regression
1} {
649 # Leave the user with a clean DB before to exit
655 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
657 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
666 set randkey
[expr int
(rand
()*10000)]
667 set randval
[expr int
(rand
()*10000)]
668 set randidx0
[expr int
(rand
()*10)]
669 set randidx1
[expr int
(rand
()*10)]
670 set cmd
[expr int
(rand
()*10)]
672 if {$cmd == 0} {$r set $randkey $randval}
673 if {$cmd == 1} {$r get
$randkey}
674 if {$cmd == 2} {$r incr $randkey}
675 if {$cmd == 3} {$r lpush
$randkey $randval}
676 if {$cmd == 4} {$r rpop
$randkey}
677 if {$cmd == 5} {$r del
$randkey}
678 if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
679 if {$cmd == 7} {$r ltrim
$randkey $randidx0 $randidx1}
680 if {$cmd == 8} {$r lindex $randkey $randidx0}
681 if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
688 if {[llength $argv] == 0} {
690 } elseif
{[llength $argv] == 1 && [lindex $argv 0] eq
{stress
}} {
693 main
[lindex $argv 0] [lindex $argv 1]