]> git.saurik.com Git - redis.git/blame - test-redis.tcl
Erlang client synched with Valentiono's repo
[redis.git] / test-redis.tcl
CommitLineData
ed9b544e 1# TODO # test pipelining
2
43c9dc7b 3source client-libraries/tcl/redis.tcl
4
ed9b544e 5set ::passed 0
6set ::failed 0
7
8proc test {name code okpattern} {
9 puts -nonewline [format "%-70s " $name]
10 flush stdout
11 set retval [uplevel 1 $code]
12 if {$okpattern eq $retval || [string match $okpattern $retval]} {
13 puts "PASSED"
14 incr ::passed
15 } else {
16 puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'"
17 incr ::failed
18 }
19}
20
21proc main {server port} {
43c9dc7b 22 set r [redis $server $port]
23 set err ""
ed9b544e 24
25 test {DEL all keys to start with a clean DB} {
43c9dc7b 26 foreach key [$r keys *] {$r del $key}
27 $r dbsize
ed9b544e 28 } {0}
29
30 test {SET and GET an item} {
43c9dc7b 31 $r set x foobar
32 $r get x
ed9b544e 33 } {foobar}
34
35 test {DEL against a single item} {
43c9dc7b 36 $r del x
37 $r get x
ed9b544e 38 } {}
39
40 test {KEYS with pattern} {
41 foreach key {key_x key_y key_z foo_a foo_b foo_c} {
43c9dc7b 42 $r set $key hello
ed9b544e 43 }
43c9dc7b 44 lsort [$r keys foo*]
ed9b544e 45 } {foo_a foo_b foo_c}
46
47 test {KEYS to get all keys} {
43c9dc7b 48 lsort [$r keys *]
ed9b544e 49 } {foo_a foo_b foo_c key_x key_y key_z}
50
51 test {DBSIZE} {
43c9dc7b 52 $r dbsize
ed9b544e 53 } {6}
54
55 test {DEL all keys} {
43c9dc7b 56 foreach key [$r keys *] {$r del $key}
57 $r dbsize
ed9b544e 58 } {0}
59
60 test {Very big payload in GET/SET} {
61 set buf [string repeat "abcd" 1000000]
43c9dc7b 62 $r set foo $buf
63 $r get foo
ed9b544e 64 } [string repeat "abcd" 1000000]
65
66 test {SET 10000 numeric keys and access all them in reverse order} {
67 for {set x 0} {$x < 10000} {incr x} {
43c9dc7b 68 $r set $x $x
ed9b544e 69 }
70 set sum 0
71 for {set x 9999} {$x >= 0} {incr x -1} {
43c9dc7b 72 incr sum [$r get $x]
ed9b544e 73 }
74 format $sum
75 } {49995000}
76
77 test {DBSIZE should be 10001 now} {
43c9dc7b 78 $r dbsize
ed9b544e 79 } {10001}
80
81 test {INCR against non existing key} {
82 set res {}
43c9dc7b 83 append res [$r incr novar]
84 append res [$r get novar]
ed9b544e 85 } {11}
86
87 test {INCR against key created by incr itself} {
43c9dc7b 88 $r incr novar
ed9b544e 89 } {2}
90
91 test {INCR against key originally set with SET} {
43c9dc7b 92 $r set novar 100
93 $r incr novar
ed9b544e 94 } {101}
95
96 test {SETNX target key missing} {
43c9dc7b 97 $r setnx novar2 foobared
98 $r get novar2
ed9b544e 99 } {foobared}
100
101 test {SETNX target key exists} {
43c9dc7b 102 $r setnx novar2 blabla
103 $r get novar2
ed9b544e 104 } {foobared}
105
106 test {EXISTS} {
107 set res {}
43c9dc7b 108 $r set newkey test
109 append res [$r exists newkey]
110 $r del newkey
111 append res [$r exists newkey]
ed9b544e 112 } {10}
113
114 test {Zero length value in key. SET/GET/EXISTS} {
43c9dc7b 115 $r set emptykey {}
116 set res [$r get emptykey]
117 append res [$r exists emptykey]
118 $r del emptykey
119 append res [$r exists emptykey]
ed9b544e 120 } {10}
121
122 test {Commands pipelining} {
43c9dc7b 123 set fd [$r channel]
ed9b544e 124 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
125 flush $fd
126 set res {}
43c9dc7b 127 append res [string match OK* [::redis::redis_read_reply $fd]]
128 append res [::redis::redis_read_reply $fd]
129 append res [string match PONG* [::redis::redis_read_reply $fd]]
ed9b544e 130 format $res
131 } {1xyzk1}
132
133 test {Non existing command} {
43c9dc7b 134 catch {$r foobaredcommand} err
135 string match ERR* $err
ed9b544e 136 } {1}
137
138 test {Basic LPUSH, RPUSH, LLENGTH, LINDEX} {
43c9dc7b 139 $r lpush mylist a
140 $r lpush mylist b
141 $r rpush mylist c
142 set res [$r llen mylist]
143 append res [$r lindex mylist 0]
144 append res [$r lindex mylist 1]
145 append res [$r lindex mylist 2]
ed9b544e 146 } {3bac}
147
148 test {DEL a list} {
43c9dc7b 149 $r del mylist
150 $r exists mylist
ed9b544e 151 } {0}
152
153 test {Create a long list and check every single element with LINDEX} {
154 set ok 0
155 for {set i 0} {$i < 1000} {incr i} {
43c9dc7b 156 $r rpush mylist $i
ed9b544e 157 }
158 for {set i 0} {$i < 1000} {incr i} {
43c9dc7b 159 if {[$r lindex mylist $i] eq $i} {incr ok}
160 if {[$r lindex mylist [expr (-$i)-1]] eq [expr 999-$i]} {
ed9b544e 161 incr ok
162 }
163 }
164 format $ok
165 } {2000}
166
167 test {Test elements with LINDEX in random access} {
168 set ok 0
169 for {set i 0} {$i < 1000} {incr i} {
43c9dc7b 170 set rint [expr int(rand()*1000)]
171 if {[$r lindex mylist $rint] eq $rint} {incr ok}
172 if {[$r lindex mylist [expr (-$rint)-1]] eq [expr 999-$rint]} {
ed9b544e 173 incr ok
174 }
175 }
176 format $ok
177 } {2000}
178
179 test {LLEN against non-list value error} {
43c9dc7b 180 $r del mylist
181 $r set mylist foobar
182 catch {$r llen mylist} err
183 format $err
c937aa89 184 } {ERR*}
ed9b544e 185
186 test {LINDEX against non-list value error} {
43c9dc7b 187 catch {$r lindex mylist 0} err
188 format $err
c937aa89 189 } {ERR*}
ed9b544e 190
191 test {LPUSH against non-list value error} {
43c9dc7b 192 catch {$r lpush mylist 0} err
193 format $err
c937aa89 194 } {ERR*}
ed9b544e 195
196 test {RPUSH against non-list value error} {
43c9dc7b 197 catch {$r rpush mylist 0} err
198 format $err
c937aa89 199 } {ERR*}
ed9b544e 200
201 test {RENAME basic usage} {
43c9dc7b 202 $r set mykey hello
203 $r rename mykey mykey1
204 $r rename mykey1 mykey2
205 $r get mykey2
ed9b544e 206 } {hello}
207
208 test {RENAME source key should no longer exist} {
43c9dc7b 209 $r exists mykey
ed9b544e 210 } {0}
211
212 test {RENAME against already existing key} {
43c9dc7b 213 $r set mykey a
214 $r set mykey2 b
215 $r rename mykey2 mykey
216 set res [$r get mykey]
217 append res [$r exists mykey2]
ed9b544e 218 } {b0}
219
220 test {RENAMENX basic usage} {
43c9dc7b 221 $r del mykey
222 $r del mykey2
223 $r set mykey foobar
224 $r renamenx mykey mykey2
225 set res [$r get mykey2]
226 append res [$r exists mykey]
ed9b544e 227 } {foobar0}
228
229 test {RENAMENX against already existing key} {
43c9dc7b 230 $r set mykey foo
231 $r set mykey2 bar
232 $r renamenx mykey mykey2
ed9b544e 233 } {0}
234
235 test {RENAMENX against already existing key (2)} {
43c9dc7b 236 set res [$r get mykey]
237 append res [$r get mykey2]
ed9b544e 238 } {foobar}
239
240 test {RENAME against non existing source key} {
43c9dc7b 241 catch {$r rename nokey foobar} err
242 format $err
c937aa89 243 } {ERR*}
ed9b544e 244
245 test {RENAME where source and dest key is the same} {
43c9dc7b 246 catch {$r rename mykey mykey} err
247 format $err
c937aa89 248 } {ERR*}
ed9b544e 249
250 test {DEL all keys again (DB 0)} {
43c9dc7b 251 foreach key [$r keys *] {
252 $r del $key
ed9b544e 253 }
43c9dc7b 254 $r dbsize
ed9b544e 255 } {0}
256
257 test {DEL all keys again (DB 1)} {
43c9dc7b 258 $r select 1
259 foreach key [$r keys *] {
260 $r del $key
ed9b544e 261 }
43c9dc7b 262 set res [$r dbsize]
263 $r select 0
ed9b544e 264 format $res
265 } {0}
266
267 test {MOVE basic usage} {
43c9dc7b 268 $r set mykey foobar
269 $r move mykey 1
ed9b544e 270 set res {}
43c9dc7b 271 lappend res [$r exists mykey]
272 lappend res [$r dbsize]
273 $r select 1
274 lappend res [$r get mykey]
275 lappend res [$r dbsize]
276 $r select 0
ed9b544e 277 format $res
278 } [list 0 0 foobar 1]
279
280 test {MOVE against key existing in the target DB} {
43c9dc7b 281 $r set mykey hello
282 $r move mykey 1
ed9b544e 283 } {0}
284
285 test {SET/GET keys in different DBs} {
43c9dc7b 286 $r set a hello
287 $r set b world
288 $r select 1
289 $r set a foo
290 $r set b bared
291 $r select 0
ed9b544e 292 set res {}
43c9dc7b 293 lappend res [$r get a]
294 lappend res [$r get b]
295 $r select 1
296 lappend res [$r get a]
297 lappend res [$r get b]
298 $r select 0
ed9b544e 299 format $res
300 } {hello world foo bared}
301
302 test {Basic LPOP/RPOP} {
43c9dc7b 303 $r del mylist
304 $r rpush mylist 1
305 $r rpush mylist 2
306 $r lpush mylist 0
307 list [$r lpop mylist] [$r rpop mylist] [$r lpop mylist] [$r llen mylist]
ed9b544e 308 } [list 0 2 1 0]
309
310 test {LPOP/RPOP against empty list} {
43c9dc7b 311 $r lpop mylist
ed9b544e 312 } {}
313
314 test {LPOP against non list value} {
43c9dc7b 315 $r set notalist foo
316 catch {$r lpop notalist} err
317 format $err
c937aa89 318 } {ERR*kind*}
ed9b544e 319
320 test {Mass LPUSH/LPOP} {
321 set sum 0
322 for {set i 0} {$i < 1000} {incr i} {
43c9dc7b 323 $r lpush mylist $i
ed9b544e 324 incr sum $i
325 }
326 set sum2 0
327 for {set i 0} {$i < 500} {incr i} {
43c9dc7b 328 incr sum2 [$r lpop mylist]
329 incr sum2 [$r rpop mylist]
ed9b544e 330 }
331 expr $sum == $sum2
332 } {1}
333
334 test {LRANGE basics} {
335 for {set i 0} {$i < 10} {incr i} {
43c9dc7b 336 $r rpush mylist $i
ed9b544e 337 }
43c9dc7b 338 list [$r lrange mylist 1 -2] \
339 [$r lrange mylist -3 -1] \
340 [$r lrange mylist 4 4]
ed9b544e 341 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
342
343 test {LRANGE inverted indexes} {
43c9dc7b 344 $r lrange mylist 6 2
ed9b544e 345 } {}
346
347 test {LRANGE out of range indexes including the full list} {
43c9dc7b 348 $r lrange mylist -1000 1000
ed9b544e 349 } {0 1 2 3 4 5 6 7 8 9}
350
351 test {LRANGE against non existing key} {
43c9dc7b 352 $r lrange nosuchkey 0 1
ed9b544e 353 } {}
354
355 test {LTRIM basics} {
43c9dc7b 356 $r del mylist
ed9b544e 357 for {set i 0} {$i < 100} {incr i} {
43c9dc7b 358 $r lpush mylist $i
359 $r ltrim mylist 0 4
ed9b544e 360 }
43c9dc7b 361 $r lrange mylist 0 -1
ed9b544e 362 } {99 98 97 96 95}
363
364 test {LSET} {
43c9dc7b 365 $r lset mylist 1 foo
366 $r lset mylist -1 bar
367 $r lrange mylist 0 -1
ed9b544e 368 } {99 foo 97 96 bar}
369
370 test {LSET out of range index} {
43c9dc7b 371 catch {$r lset mylist 10 foo} err
372 format $err
c937aa89 373 } {ERR*range*}
ed9b544e 374
375 test {LSET against non existing key} {
43c9dc7b 376 catch {$r lset nosuchkey 10 foo} err
377 format $err
c937aa89 378 } {ERR*key*}
ed9b544e 379
380 test {LSET against non list value} {
43c9dc7b 381 $r set nolist foobar
382 catch {$r lset nolist 0 foo} err
383 format $err
c937aa89 384 } {ERR*value*}
ed9b544e 385
386 test {SADD, SCARD, SISMEMBER, SMEMBERS basics} {
43c9dc7b 387 $r sadd myset foo
388 $r sadd myset bar
389 list [$r scard myset] [$r sismember myset foo] \
390 [$r sismember myset bar] [$r sismember myset bla] \
391 [lsort [$r smembers myset]]
ed9b544e 392 } {2 1 1 0 {bar foo}}
393
394 test {SADD adding the same element multiple times} {
43c9dc7b 395 $r sadd myset foo
396 $r sadd myset foo
397 $r sadd myset foo
398 $r scard myset
ed9b544e 399 } {2}
400
401 test {SADD against non set} {
43c9dc7b 402 catch {$r sadd mylist foo} err
403 format $err
c937aa89 404 } {ERR*kind*}
ed9b544e 405
406 test {SREM basics} {
43c9dc7b 407 $r sadd myset ciao
408 $r srem myset foo
409 lsort [$r smembers myset]
ed9b544e 410 } {bar ciao}
411
412 test {Mass SADD and SINTER with two sets} {
413 for {set i 0} {$i < 1000} {incr i} {
43c9dc7b 414 $r sadd set1 $i
415 $r sadd set2 [expr $i+995]
ed9b544e 416 }
43c9dc7b 417 lsort [$r sinter set1 set2]
ed9b544e 418 } {995 996 997 998 999}
419
420 test {SINTERSTORE with two sets} {
43c9dc7b 421 $r sinterstore setres set1 set2
422 lsort [$r smembers setres]
ed9b544e 423 } {995 996 997 998 999}
424
425 test {SINTER against three sets} {
43c9dc7b 426 $r sadd set3 999
427 $r sadd set3 995
428 $r sadd set3 1000
429 $r sadd set3 2000
430 lsort [$r sinter set1 set2 set3]
ed9b544e 431 } {995 999}
432
433 test {SINTERSTORE with three sets} {
43c9dc7b 434 $r sinterstore setres set1 set2 set3
435 lsort [$r smembers setres]
ed9b544e 436 } {995 999}
437
438 test {SAVE - make sure there are all the types as values} {
43c9dc7b 439 $r lpush mysavelist hello
440 $r lpush mysavelist world
441 $r set myemptykey {}
442 $r set mynormalkey {blablablba}
443 $r save
c937aa89 444 } {OK}
ed9b544e 445
446 test {Create a random list} {
447 set tosort {}
448 array set seenrand {}
449 for {set i 0} {$i < 10000} {incr i} {
450 while 1 {
451 # Make sure all the weights are different because
452 # Redis does not use a stable sort but Tcl does.
43c9dc7b 453 set rint [expr int(rand()*1000000)]
454 if {![info exists seenrand($rint)]} break
ed9b544e 455 }
43c9dc7b 456 set seenrand($rint) x
457 $r lpush tosort $i
458 $r set weight_$i $rint
459 lappend tosort [list $i $rint]
ed9b544e 460 }
461 set sorted [lsort -index 1 -real $tosort]
462 set res {}
463 for {set i 0} {$i < 10000} {incr i} {
464 lappend res [lindex $sorted $i 0]
465 }
466 format {}
467 } {}
468
469 test {SORT with BY against the newly created list} {
43c9dc7b 470 $r sort tosort {BY weight_*}
ed9b544e 471 } $res
472
473 test {SORT direct, numeric, against the newly created list} {
43c9dc7b 474 $r sort tosort
ed9b544e 475 } [lsort -integer $res]
476
477 test {SORT decreasing sort} {
43c9dc7b 478 $r sort tosort {DESC}
ed9b544e 479 } [lsort -decreasing -integer $res]
480
481 test {SORT speed, sorting 10000 elements list using BY, 100 times} {
482 set start [clock clicks -milliseconds]
483 for {set i 0} {$i < 100} {incr i} {
43c9dc7b 484 set sorted [$r sort tosort {BY weight_* LIMIT 0 10}]
ed9b544e 485 }
486 set elapsed [expr [clock clicks -milliseconds]-$start]
487 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
488 flush stdout
489 format {}
490 } {}
491
492 test {SORT speed, sorting 10000 elements list directly, 100 times} {
493 set start [clock clicks -milliseconds]
494 for {set i 0} {$i < 100} {incr i} {
43c9dc7b 495 set sorted [$r sort tosort {LIMIT 0 10}]
ed9b544e 496 }
497 set elapsed [expr [clock clicks -milliseconds]-$start]
498 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
499 flush stdout
500 format {}
501 } {}
502
503 test {SORT speed, pseudo-sorting 10000 elements list, BY <const>, 100 times} {
504 set start [clock clicks -milliseconds]
505 for {set i 0} {$i < 100} {incr i} {
43c9dc7b 506 set sorted [$r sort tosort {BY nokey LIMIT 0 10}]
ed9b544e 507 }
508 set elapsed [expr [clock clicks -milliseconds]-$start]
509 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
510 flush stdout
511 format {}
512 } {}
513
514 test {SORT regression for issue #19, sorting floats} {
43c9dc7b 515 $r flushdb
ed9b544e 516 foreach x {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
43c9dc7b 517 $r lpush mylist $x
ed9b544e 518 }
43c9dc7b 519 $r sort mylist
ed9b544e 520 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
521
522 test {LREM, remove all the occurrences} {
43c9dc7b 523 $r flushall
524 $r rpush mylist foo
525 $r rpush mylist bar
526 $r rpush mylist foobar
527 $r rpush mylist foobared
528 $r rpush mylist zap
529 $r rpush mylist bar
530 $r rpush mylist test
531 $r rpush mylist foo
532 set res [$r lrem mylist 0 bar]
533 list [$r lrange mylist 0 -1] $res
ed9b544e 534 } {{foo foobar foobared zap test foo} 2}
535
536 test {LREM, remove the first occurrence} {
43c9dc7b 537 set res [$r lrem mylist 1 foo]
538 list [$r lrange mylist 0 -1] $res
ed9b544e 539 } {{foobar foobared zap test foo} 1}
540
541 test {LREM, remove non existing element} {
43c9dc7b 542 set res [$r lrem mylist 1 nosuchelement]
543 list [$r lrange mylist 0 -1] $res
ed9b544e 544 } {{foobar foobared zap test foo} 0}
545
546 test {LREM, starting from tail with negative count} {
43c9dc7b 547 $r flushall
548 $r rpush mylist foo
549 $r rpush mylist bar
550 $r rpush mylist foobar
551 $r rpush mylist foobared
552 $r rpush mylist zap
553 $r rpush mylist bar
554 $r rpush mylist test
555 $r rpush mylist foo
556 $r rpush mylist foo
557 set res [$r lrem mylist -1 bar]
558 list [$r lrange mylist 0 -1] $res
ed9b544e 559 } {{foo bar foobar foobared zap test foo foo} 1}
560
561 test {LREM, starting from tail with negative count (2)} {
43c9dc7b 562 set res [$r lrem mylist -2 foo]
563 list [$r lrange mylist 0 -1] $res
ed9b544e 564 } {{foo bar foobar foobared zap test} 2}
565
5b19bd72 566 test {MGET} {
43c9dc7b 567 $r flushall
568 $r set foo BAR
569 $r set bar FOO
570 $r mget foo bar
5b19bd72 571 } {BAR FOO}
572
573 test {MGET against non existing key} {
43c9dc7b 574 $r mget foo baazz bar
5b19bd72 575 } {BAR {} FOO}
576
577 test {MGET against non-string key} {
43c9dc7b 578 $r sadd myset ciao
579 $r sadd myset bau
580 $r mget foo baazz bar myset
5b19bd72 581 } {BAR {} FOO {}}
582
ed9b544e 583 # Leave the user with a clean DB before to exit
584 test {FLUSHALL} {
43c9dc7b 585 $r flushall
586 $r dbsize
ed9b544e 587 } {0}
588
589 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
590 if {$::failed > 0} {
591 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
592 }
593 close $fd
594}
595
5a6948fb 596proc stress {} {
43c9dc7b 597 set r [redis]
598 $r flushall
5a6948fb 599 while 1 {
600 set randkey [expr int(rand()*10000)]
601 set randval [expr int(rand()*10000)]
602 set randidx0 [expr int(rand()*10)]
603 set randidx1 [expr int(rand()*10)]
604 set cmd [expr int(rand()*10)]
43c9dc7b 605 catch {
606 if {$cmd == 0} {$r set $randkey $randval}
607 if {$cmd == 1} {$r get $randkey}
608 if {$cmd == 2} {$r incr $randkey}
609 if {$cmd == 3} {$r lpush $randkey $randval}
610 if {$cmd == 4} {$r rpop $randkey}
611 if {$cmd == 5} {$r del $randkey}
612 if {$cmd == 6} {$r lrange $randkey $randidx0 $randidx1}
613 if {$cmd == 7} {$r ltrim $randkey $randidx0 $randidx1}
614 if {$cmd == 8} {$r lindex $randkey $randidx0}
615 if {$cmd == 9} {$r lset $randkey $randidx0 $randval}
616 }
5a6948fb 617 flush stdout
618 }
43c9dc7b 619 $r close
5a6948fb 620}
621
ed9b544e 622if {[llength $argv] == 0} {
623 main 127.0.0.1 6379
5a6948fb 624} elseif {[llength $argv] == 1 && [lindex $argv 0] eq {stress}} {
625 stress
ed9b544e 626} else {
627 main [lindex $argv 0] [lindex $argv 1]
628}