]> git.saurik.com Git - redis.git/blob - test-redis.tcl
737ad06b4cce5aa6c31417464f3878e257e8858f
[redis.git] / test-redis.tcl
1 # TODO # test pipelining
2
3 set tcl_precision 17
4 source redis.tcl
5
6 set ::passed 0
7 set ::failed 0
8
9 proc test {name code okpattern} {
10 puts -nonewline [format "%-70s " $name]
11 flush stdout
12 set retval [uplevel 1 $code]
13 if {$okpattern eq $retval || [string match $okpattern $retval]} {
14 puts "PASSED"
15 incr ::passed
16 } else {
17 puts "!! ERROR expected\n'$okpattern'\nbut got\n'$retval'"
18 incr ::failed
19 }
20 }
21
22 proc randstring {min max {type binary}} {
23 set len [expr {$min+int(rand()*($max-$min+1))}]
24 set output {}
25 if {$type eq {binary}} {
26 set minval 0
27 set maxval 255
28 } elseif {$type eq {alpha}} {
29 set minval 48
30 set maxval 122
31 } elseif {$type eq {compr}} {
32 set minval 48
33 set maxval 52
34 }
35 while {$len} {
36 append output [format "%c" [expr {$minval+int(rand()*($maxval-$minval+1))}]]
37 incr len -1
38 }
39 return $output
40 }
41
42 # Useful for some test
43 proc zlistAlikeSort {a b} {
44 if {[lindex $a 0] > [lindex $b 0]} {return 1}
45 if {[lindex $a 0] < [lindex $b 0]} {return -1}
46 string compare [lindex $a 1] [lindex $b 1]
47 }
48
49 proc main {server port} {
50 set r [redis $server $port]
51 $r select 9
52 set err ""
53
54 # The following AUTH test should be enabled only when requirepass
55 # <PASSWORD> is set in redis.conf and redis-server was started with
56 # redis.conf as the first argument.
57
58 #test {AUTH with requirepass in redis.conf} {
59 # $r auth foobared
60 #} {OK}
61
62 test {DEL all keys to start with a clean DB} {
63 foreach key [$r keys *] {$r del $key}
64 $r dbsize
65 } {0}
66
67 test {SET and GET an item} {
68 $r set x foobar
69 $r get x
70 } {foobar}
71
72 test {DEL against a single item} {
73 $r del x
74 $r get x
75 } {}
76
77 test {Vararg DEL} {
78 $r set foo1 a
79 $r set foo2 b
80 $r set foo3 c
81 list [$r del foo1 foo2 foo3 foo4] [$r mget foo1 foo2 foo3]
82 } {3 {{} {} {}}}
83
84 test {KEYS with pattern} {
85 foreach key {key_x key_y key_z foo_a foo_b foo_c} {
86 $r set $key hello
87 }
88 lsort [$r keys foo*]
89 } {foo_a foo_b foo_c}
90
91 test {KEYS to get all keys} {
92 lsort [$r keys *]
93 } {foo_a foo_b foo_c key_x key_y key_z}
94
95 test {DBSIZE} {
96 $r dbsize
97 } {6}
98
99 test {DEL all keys} {
100 foreach key [$r keys *] {$r del $key}
101 $r dbsize
102 } {0}
103
104 test {Very big payload in GET/SET} {
105 set buf [string repeat "abcd" 1000000]
106 $r set foo $buf
107 $r get foo
108 } [string repeat "abcd" 1000000]
109
110 test {SET 10000 numeric keys and access all them in reverse order} {
111 for {set x 0} {$x < 10000} {incr x} {
112 $r set $x $x
113 }
114 set sum 0
115 for {set x 9999} {$x >= 0} {incr x -1} {
116 incr sum [$r get $x]
117 }
118 format $sum
119 } {49995000}
120
121 test {DBSIZE should be 10001 now} {
122 $r dbsize
123 } {10001}
124
125 test {INCR against non existing key} {
126 set res {}
127 append res [$r incr novar]
128 append res [$r get novar]
129 } {11}
130
131 test {INCR against key created by incr itself} {
132 $r incr novar
133 } {2}
134
135 test {INCR against key originally set with SET} {
136 $r set novar 100
137 $r incr novar
138 } {101}
139
140 test {INCR over 32bit value} {
141 $r set novar 17179869184
142 $r incr novar
143 } {17179869185}
144
145 test {INCRBY over 32bit value with over 32bit increment} {
146 $r set novar 17179869184
147 $r incrby novar 17179869184
148 } {34359738368}
149
150 test {DECRBY over 32bit value with over 32bit increment, negative res} {
151 $r set novar 17179869184
152 $r decrby novar 17179869185
153 } {-1}
154
155 test {SETNX target key missing} {
156 $r setnx novar2 foobared
157 $r get novar2
158 } {foobared}
159
160 test {SETNX target key exists} {
161 $r setnx novar2 blabla
162 $r get novar2
163 } {foobared}
164
165 test {EXISTS} {
166 set res {}
167 $r set newkey test
168 append res [$r exists newkey]
169 $r del newkey
170 append res [$r exists newkey]
171 } {10}
172
173 test {Zero length value in key. SET/GET/EXISTS} {
174 $r set emptykey {}
175 set res [$r get emptykey]
176 append res [$r exists emptykey]
177 $r del emptykey
178 append res [$r exists emptykey]
179 } {10}
180
181 test {Commands pipelining} {
182 set fd [$r channel]
183 puts -nonewline $fd "SET k1 4\r\nxyzk\r\nGET k1\r\nPING\r\n"
184 flush $fd
185 set res {}
186 append res [string match OK* [::redis::redis_read_reply $fd]]
187 append res [::redis::redis_read_reply $fd]
188 append res [string match PONG* [::redis::redis_read_reply $fd]]
189 format $res
190 } {1xyzk1}
191
192 test {Non existing command} {
193 catch {$r foobaredcommand} err
194 string match ERR* $err
195 } {1}
196
197 test {Basic LPUSH, RPUSH, LLENGTH, LINDEX} {
198 $r lpush mylist a
199 $r lpush mylist b
200 $r rpush mylist c
201 set res [$r llen mylist]
202 append res [$r lindex mylist 0]
203 append res [$r lindex mylist 1]
204 append res [$r lindex mylist 2]
205 } {3bac}
206
207 test {DEL a list} {
208 $r del mylist
209 $r exists mylist
210 } {0}
211
212 test {Create a long list and check every single element with LINDEX} {
213 set ok 0
214 for {set i 0} {$i < 1000} {incr i} {
215 $r rpush mylist $i
216 }
217 for {set i 0} {$i < 1000} {incr i} {
218 if {[$r lindex mylist $i] eq $i} {incr ok}
219 if {[$r lindex mylist [expr (-$i)-1]] eq [expr 999-$i]} {
220 incr ok
221 }
222 }
223 format $ok
224 } {2000}
225
226 test {Test elements with LINDEX in random access} {
227 set ok 0
228 for {set i 0} {$i < 1000} {incr i} {
229 set rint [expr int(rand()*1000)]
230 if {[$r lindex mylist $rint] eq $rint} {incr ok}
231 if {[$r lindex mylist [expr (-$rint)-1]] eq [expr 999-$rint]} {
232 incr ok
233 }
234 }
235 format $ok
236 } {2000}
237
238 test {LLEN against non-list value error} {
239 $r del mylist
240 $r set mylist foobar
241 catch {$r llen mylist} err
242 format $err
243 } {ERR*}
244
245 test {LINDEX against non-list value error} {
246 catch {$r lindex mylist 0} err
247 format $err
248 } {ERR*}
249
250 test {LPUSH against non-list value error} {
251 catch {$r lpush mylist 0} err
252 format $err
253 } {ERR*}
254
255 test {RPUSH against non-list value error} {
256 catch {$r rpush mylist 0} err
257 format $err
258 } {ERR*}
259
260 test {RPOPLPUSH base case} {
261 $r del mylist
262 $r rpush mylist a
263 $r rpush mylist b
264 $r rpush mylist c
265 $r rpush mylist d
266 set v1 [$r rpoplpush mylist newlist]
267 set v2 [$r rpoplpush mylist newlist]
268 set l1 [$r lrange mylist 0 -1]
269 set l2 [$r lrange newlist 0 -1]
270 list $v1 $v2 $l1 $l2
271 } {d c {a b} {c d}}
272
273 test {RPOPLPUSH with the same list as src and dst} {
274 $r del mylist
275 $r rpush mylist a
276 $r rpush mylist b
277 $r rpush mylist c
278 set l1 [$r lrange mylist 0 -1]
279 set v [$r rpoplpush mylist mylist]
280 set l2 [$r lrange mylist 0 -1]
281 list $l1 $v $l2
282 } {{a b c} c {c a b}}
283
284 test {RPOPLPUSH target list already exists} {
285 $r del mylist
286 $r del newlist
287 $r rpush mylist a
288 $r rpush mylist b
289 $r rpush mylist c
290 $r rpush mylist d
291 $r rpush newlist x
292 set v1 [$r rpoplpush mylist newlist]
293 set v2 [$r rpoplpush mylist newlist]
294 set l1 [$r lrange mylist 0 -1]
295 set l2 [$r lrange newlist 0 -1]
296 list $v1 $v2 $l1 $l2
297 } {d c {a b} {c d x}}
298
299 test {RENAME basic usage} {
300 $r set mykey hello
301 $r rename mykey mykey1
302 $r rename mykey1 mykey2
303 $r get mykey2
304 } {hello}
305
306 test {RENAME source key should no longer exist} {
307 $r exists mykey
308 } {0}
309
310 test {RENAME against already existing key} {
311 $r set mykey a
312 $r set mykey2 b
313 $r rename mykey2 mykey
314 set res [$r get mykey]
315 append res [$r exists mykey2]
316 } {b0}
317
318 test {RENAMENX basic usage} {
319 $r del mykey
320 $r del mykey2
321 $r set mykey foobar
322 $r renamenx mykey mykey2
323 set res [$r get mykey2]
324 append res [$r exists mykey]
325 } {foobar0}
326
327 test {RENAMENX against already existing key} {
328 $r set mykey foo
329 $r set mykey2 bar
330 $r renamenx mykey mykey2
331 } {0}
332
333 test {RENAMENX against already existing key (2)} {
334 set res [$r get mykey]
335 append res [$r get mykey2]
336 } {foobar}
337
338 test {RENAME against non existing source key} {
339 catch {$r rename nokey foobar} err
340 format $err
341 } {ERR*}
342
343 test {RENAME where source and dest key is the same} {
344 catch {$r rename mykey mykey} err
345 format $err
346 } {ERR*}
347
348 test {DEL all keys again (DB 0)} {
349 foreach key [$r keys *] {
350 $r del $key
351 }
352 $r dbsize
353 } {0}
354
355 test {DEL all keys again (DB 1)} {
356 $r select 10
357 foreach key [$r keys *] {
358 $r del $key
359 }
360 set res [$r dbsize]
361 $r select 9
362 format $res
363 } {0}
364
365 test {MOVE basic usage} {
366 $r set mykey foobar
367 $r move mykey 10
368 set res {}
369 lappend res [$r exists mykey]
370 lappend res [$r dbsize]
371 $r select 10
372 lappend res [$r get mykey]
373 lappend res [$r dbsize]
374 $r select 9
375 format $res
376 } [list 0 0 foobar 1]
377
378 test {MOVE against key existing in the target DB} {
379 $r set mykey hello
380 $r move mykey 10
381 } {0}
382
383 test {SET/GET keys in different DBs} {
384 $r set a hello
385 $r set b world
386 $r select 10
387 $r set a foo
388 $r set b bared
389 $r select 9
390 set res {}
391 lappend res [$r get a]
392 lappend res [$r get b]
393 $r select 10
394 lappend res [$r get a]
395 lappend res [$r get b]
396 $r select 9
397 format $res
398 } {hello world foo bared}
399
400 test {Basic LPOP/RPOP} {
401 $r del mylist
402 $r rpush mylist 1
403 $r rpush mylist 2
404 $r lpush mylist 0
405 list [$r lpop mylist] [$r rpop mylist] [$r lpop mylist] [$r llen mylist]
406 } [list 0 2 1 0]
407
408 test {LPOP/RPOP against empty list} {
409 $r lpop mylist
410 } {}
411
412 test {LPOP against non list value} {
413 $r set notalist foo
414 catch {$r lpop notalist} err
415 format $err
416 } {ERR*kind*}
417
418 test {Mass LPUSH/LPOP} {
419 set sum 0
420 for {set i 0} {$i < 1000} {incr i} {
421 $r lpush mylist $i
422 incr sum $i
423 }
424 set sum2 0
425 for {set i 0} {$i < 500} {incr i} {
426 incr sum2 [$r lpop mylist]
427 incr sum2 [$r rpop mylist]
428 }
429 expr $sum == $sum2
430 } {1}
431
432 test {LRANGE basics} {
433 for {set i 0} {$i < 10} {incr i} {
434 $r rpush mylist $i
435 }
436 list [$r lrange mylist 1 -2] \
437 [$r lrange mylist -3 -1] \
438 [$r lrange mylist 4 4]
439 } {{1 2 3 4 5 6 7 8} {7 8 9} 4}
440
441 test {LRANGE inverted indexes} {
442 $r lrange mylist 6 2
443 } {}
444
445 test {LRANGE out of range indexes including the full list} {
446 $r lrange mylist -1000 1000
447 } {0 1 2 3 4 5 6 7 8 9}
448
449 test {LRANGE against non existing key} {
450 $r lrange nosuchkey 0 1
451 } {}
452
453 test {LTRIM basics} {
454 $r del mylist
455 for {set i 0} {$i < 100} {incr i} {
456 $r lpush mylist $i
457 $r ltrim mylist 0 4
458 }
459 $r lrange mylist 0 -1
460 } {99 98 97 96 95}
461
462 test {LSET} {
463 $r lset mylist 1 foo
464 $r lset mylist -1 bar
465 $r lrange mylist 0 -1
466 } {99 foo 97 96 bar}
467
468 test {LSET out of range index} {
469 catch {$r lset mylist 10 foo} err
470 format $err
471 } {ERR*range*}
472
473 test {LSET against non existing key} {
474 catch {$r lset nosuchkey 10 foo} err
475 format $err
476 } {ERR*key*}
477
478 test {LSET against non list value} {
479 $r set nolist foobar
480 catch {$r lset nolist 0 foo} err
481 format $err
482 } {ERR*value*}
483
484 test {SADD, SCARD, SISMEMBER, SMEMBERS basics} {
485 $r sadd myset foo
486 $r sadd myset bar
487 list [$r scard myset] [$r sismember myset foo] \
488 [$r sismember myset bar] [$r sismember myset bla] \
489 [lsort [$r smembers myset]]
490 } {2 1 1 0 {bar foo}}
491
492 test {SADD adding the same element multiple times} {
493 $r sadd myset foo
494 $r sadd myset foo
495 $r sadd myset foo
496 $r scard myset
497 } {2}
498
499 test {SADD against non set} {
500 catch {$r sadd mylist foo} err
501 format $err
502 } {ERR*kind*}
503
504 test {SREM basics} {
505 $r sadd myset ciao
506 $r srem myset foo
507 lsort [$r smembers myset]
508 } {bar ciao}
509
510 test {Mass SADD and SINTER with two sets} {
511 for {set i 0} {$i < 1000} {incr i} {
512 $r sadd set1 $i
513 $r sadd set2 [expr $i+995]
514 }
515 lsort [$r sinter set1 set2]
516 } {995 996 997 998 999}
517
518 test {SUNION with two sets} {
519 lsort [$r sunion set1 set2]
520 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
521
522 test {SINTERSTORE with two sets} {
523 $r sinterstore setres set1 set2
524 lsort [$r smembers setres]
525 } {995 996 997 998 999}
526
527 test {SUNIONSTORE with two sets} {
528 $r sunionstore setres set1 set2
529 lsort [$r smembers setres]
530 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
531
532 test {SINTER against three sets} {
533 $r sadd set3 999
534 $r sadd set3 995
535 $r sadd set3 1000
536 $r sadd set3 2000
537 lsort [$r sinter set1 set2 set3]
538 } {995 999}
539
540 test {SINTERSTORE with three sets} {
541 $r sinterstore setres set1 set2 set3
542 lsort [$r smembers setres]
543 } {995 999}
544
545 test {SUNION with non existing keys} {
546 lsort [$r sunion nokey1 set1 set2 nokey2]
547 } [lsort -uniq "[$r smembers set1] [$r smembers set2]"]
548
549 test {SDIFF with two sets} {
550 for {set i 5} {$i < 1000} {incr i} {
551 $r sadd set4 $i
552 }
553 lsort [$r sdiff set1 set4]
554 } {0 1 2 3 4}
555
556 test {SDIFF with three sets} {
557 $r sadd set5 0
558 lsort [$r sdiff set1 set4 set5]
559 } {1 2 3 4}
560
561 test {SDIFFSTORE with three sets} {
562 $r sdiffstore sres set1 set4 set5
563 lsort [$r smembers sres]
564 } {1 2 3 4}
565
566 test {SPOP basics} {
567 $r del myset
568 $r sadd myset 1
569 $r sadd myset 2
570 $r sadd myset 3
571 list [lsort [list [$r spop myset] [$r spop myset] [$r spop myset]]] [$r scard myset]
572 } {{1 2 3} 0}
573
574 test {SAVE - make sure there are all the types as values} {
575 # Wait for a background saving in progress to terminate
576 while 1 {
577 set i [$r info]
578 if {[string match {*bgsave_in_progress:1*} $i]} {
579 puts -nonewline "\nWaiting for background save to finish... "
580 flush stdout
581 after 100
582 } else {
583 break
584 }
585 }
586 $r lpush mysavelist hello
587 $r lpush mysavelist world
588 $r set myemptykey {}
589 $r set mynormalkey {blablablba}
590 $r zadd mytestzset a 10
591 $r zadd mytestzset b 20
592 $r zadd mytestzset c 30
593 $r save
594 } {OK}
595
596 test {Create a random list} {
597 set tosort {}
598 array set seenrand {}
599 for {set i 0} {$i < 10000} {incr i} {
600 while 1 {
601 # Make sure all the weights are different because
602 # Redis does not use a stable sort but Tcl does.
603 set rint [expr int(rand()*1000000)]
604 if {![info exists seenrand($rint)]} break
605 }
606 set seenrand($rint) x
607 $r lpush tosort $i
608 $r set weight_$i $rint
609 lappend tosort [list $i $rint]
610 }
611 set sorted [lsort -index 1 -real $tosort]
612 set res {}
613 for {set i 0} {$i < 10000} {incr i} {
614 lappend res [lindex $sorted $i 0]
615 }
616 format {}
617 } {}
618
619 test {SORT with BY against the newly created list} {
620 $r sort tosort {BY weight_*}
621 } $res
622
623 test {SORT direct, numeric, against the newly created list} {
624 $r sort tosort
625 } [lsort -integer $res]
626
627 test {SORT decreasing sort} {
628 $r sort tosort {DESC}
629 } [lsort -decreasing -integer $res]
630
631 test {SORT speed, sorting 10000 elements list using BY, 100 times} {
632 set start [clock clicks -milliseconds]
633 for {set i 0} {$i < 100} {incr i} {
634 set sorted [$r sort tosort {BY weight_* LIMIT 0 10}]
635 }
636 set elapsed [expr [clock clicks -milliseconds]-$start]
637 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
638 flush stdout
639 format {}
640 } {}
641
642 test {SORT speed, sorting 10000 elements list directly, 100 times} {
643 set start [clock clicks -milliseconds]
644 for {set i 0} {$i < 100} {incr i} {
645 set sorted [$r sort tosort {LIMIT 0 10}]
646 }
647 set elapsed [expr [clock clicks -milliseconds]-$start]
648 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
649 flush stdout
650 format {}
651 } {}
652
653 test {SORT speed, pseudo-sorting 10000 elements list, BY <const>, 100 times} {
654 set start [clock clicks -milliseconds]
655 for {set i 0} {$i < 100} {incr i} {
656 set sorted [$r sort tosort {BY nokey LIMIT 0 10}]
657 }
658 set elapsed [expr [clock clicks -milliseconds]-$start]
659 puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
660 flush stdout
661 format {}
662 } {}
663
664 test {SORT regression for issue #19, sorting floats} {
665 $r flushdb
666 foreach x {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
667 $r lpush mylist $x
668 }
669 $r sort mylist
670 } [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
671
672 test {LREM, remove all the occurrences} {
673 $r flushdb
674 $r rpush mylist foo
675 $r rpush mylist bar
676 $r rpush mylist foobar
677 $r rpush mylist foobared
678 $r rpush mylist zap
679 $r rpush mylist bar
680 $r rpush mylist test
681 $r rpush mylist foo
682 set res [$r lrem mylist 0 bar]
683 list [$r lrange mylist 0 -1] $res
684 } {{foo foobar foobared zap test foo} 2}
685
686 test {LREM, remove the first occurrence} {
687 set res [$r lrem mylist 1 foo]
688 list [$r lrange mylist 0 -1] $res
689 } {{foobar foobared zap test foo} 1}
690
691 test {LREM, remove non existing element} {
692 set res [$r lrem mylist 1 nosuchelement]
693 list [$r lrange mylist 0 -1] $res
694 } {{foobar foobared zap test foo} 0}
695
696 test {LREM, starting from tail with negative count} {
697 $r flushdb
698 $r rpush mylist foo
699 $r rpush mylist bar
700 $r rpush mylist foobar
701 $r rpush mylist foobared
702 $r rpush mylist zap
703 $r rpush mylist bar
704 $r rpush mylist test
705 $r rpush mylist foo
706 $r rpush mylist foo
707 set res [$r lrem mylist -1 bar]
708 list [$r lrange mylist 0 -1] $res
709 } {{foo bar foobar foobared zap test foo foo} 1}
710
711 test {LREM, starting from tail with negative count (2)} {
712 set res [$r lrem mylist -2 foo]
713 list [$r lrange mylist 0 -1] $res
714 } {{foo bar foobar foobared zap test} 2}
715
716 test {LREM, deleting objects that may be encoded as integers} {
717 $r lpush myotherlist 1
718 $r lpush myotherlist 2
719 $r lpush myotherlist 3
720 $r lrem myotherlist 1 2
721 $r llen myotherlist
722 } {2}
723
724 test {MGET} {
725 $r flushdb
726 $r set foo BAR
727 $r set bar FOO
728 $r mget foo bar
729 } {BAR FOO}
730
731 test {MGET against non existing key} {
732 $r mget foo baazz bar
733 } {BAR {} FOO}
734
735 test {MGET against non-string key} {
736 $r sadd myset ciao
737 $r sadd myset bau
738 $r mget foo baazz bar myset
739 } {BAR {} FOO {}}
740
741 test {RANDOMKEY} {
742 $r flushdb
743 $r set foo x
744 $r set bar y
745 set foo_seen 0
746 set bar_seen 0
747 for {set i 0} {$i < 100} {incr i} {
748 set rkey [$r randomkey]
749 if {$rkey eq {foo}} {
750 set foo_seen 1
751 }
752 if {$rkey eq {bar}} {
753 set bar_seen 1
754 }
755 }
756 list $foo_seen $bar_seen
757 } {1 1}
758
759 test {RANDOMKEY against empty DB} {
760 $r flushdb
761 $r randomkey
762 } {}
763
764 test {RANDOMKEY regression 1} {
765 $r flushdb
766 $r set x 10
767 $r del x
768 $r randomkey
769 } {}
770
771 test {GETSET (set new value)} {
772 list [$r getset foo xyz] [$r get foo]
773 } {{} xyz}
774
775 test {GETSET (replace old value)} {
776 $r set foo bar
777 list [$r getset foo xyz] [$r get foo]
778 } {bar xyz}
779
780 test {SMOVE basics} {
781 $r sadd myset1 a
782 $r sadd myset1 b
783 $r sadd myset1 c
784 $r sadd myset2 x
785 $r sadd myset2 y
786 $r sadd myset2 z
787 $r smove myset1 myset2 a
788 list [lsort [$r smembers myset2]] [lsort [$r smembers myset1]]
789 } {{a x y z} {b c}}
790
791 test {SMOVE non existing key} {
792 list [$r smove myset1 myset2 foo] [lsort [$r smembers myset2]] [lsort [$r smembers myset1]]
793 } {0 {a x y z} {b c}}
794
795 test {SMOVE non existing src set} {
796 list [$r smove noset myset2 foo] [lsort [$r smembers myset2]]
797 } {0 {a x y z}}
798
799 test {SMOVE non existing dst set} {
800 list [$r smove myset2 myset3 y] [lsort [$r smembers myset2]] [lsort [$r smembers myset3]]
801 } {1 {a x z} y}
802
803 test {SMOVE wrong src key type} {
804 $r set x 10
805 catch {$r smove x myset2 foo} err
806 format $err
807 } {ERR*}
808
809 test {SMOVE wrong dst key type} {
810 $r set x 10
811 catch {$r smove myset2 x foo} err
812 format $err
813 } {ERR*}
814
815 test {MSET base case} {
816 $r mset x 10 y "foo bar" z "x x x x x x x\n\n\r\n"
817 $r mget x y z
818 } [list 10 {foo bar} "x x x x x x x\n\n\r\n"]
819
820 test {MSET wrong number of args} {
821 catch {$r mset x 10 y "foo bar" z} err
822 format $err
823 } {*wrong number*}
824
825 test {MSETNX with already existent key} {
826 list [$r msetnx x1 xxx y2 yyy x 20] [$r exists x1] [$r exists y2]
827 } {0 0 0}
828
829 test {MSETNX with not existing keys} {
830 list [$r msetnx x1 xxx y2 yyy] [$r get x1] [$r get y2]
831 } {1 xxx yyy}
832
833 test {ZSET basic ZADD and score update} {
834 $r zadd ztmp 10 x
835 $r zadd ztmp 20 y
836 $r zadd ztmp 30 z
837 set aux1 [$r zrange ztmp 0 -1]
838 $r zadd ztmp 1 y
839 set aux2 [$r zrange ztmp 0 -1]
840 list $aux1 $aux2
841 } {{x y z} {y x z}}
842
843 test {ZSCORE} {
844 set aux {}
845 set err {}
846 for {set i 0} {$i < 1000} {incr i} {
847 set score [expr rand()]
848 lappend aux $score
849 $r zadd zscoretest $score $i
850 }
851 for {set i 0} {$i < 1000} {incr i} {
852 if {[$r zscore zscoretest $i] != [lindex $aux $i]} {
853 set err "Expected score was [lindex $aux $i] but got [$r zscore zscoretest $i] for element $i"
854 break
855 }
856 }
857 set _ $err
858 } {}
859
860 test {ZRANGE and ZREVRANGE} {
861 list [$r zrange ztmp 0 -1] [$r zrevrange ztmp 0 -1]
862 } {{y x z} {z x y}}
863
864 test {ZSETs stress tester - sorting is working well?} {
865 set delta 0
866 for {set test 0} {$test < 2} {incr test} {
867 unset -nocomplain auxarray
868 array set auxarray {}
869 set auxlist {}
870 $r del myzset
871 for {set i 0} {$i < 1000} {incr i} {
872 if {$test == 0} {
873 set score [expr rand()]
874 } else {
875 set score [expr int(rand()*10)]
876 }
877 set auxarray($i) $score
878 $r zadd myzset $score $i
879 # Random update
880 if {[expr rand()] < .2} {
881 set j [expr int(rand()*1000)]
882 if {$test == 0} {
883 set score [expr rand()]
884 } else {
885 set score [expr int(rand()*10)]
886 }
887 set auxarray($j) $score
888 $r zadd myzset $score $j
889 }
890 }
891 foreach {item score} [array get auxarray] {
892 lappend auxlist [list $score $item]
893 }
894 set sorted [lsort -command zlistAlikeSort $auxlist]
895 set auxlist {}
896 foreach x $sorted {
897 lappend auxlist [lindex $x 1]
898 }
899 set fromredis [$r zrange myzset 0 -1]
900 set delta 0
901 for {set i 0} {$i < [llength $fromredis]} {incr i} {
902 if {[lindex $fromredis $i] != [lindex $auxlist $i]} {
903 incr delta
904 }
905 }
906 }
907 format $delta
908 } {0}
909
910 test {ZSETs skiplist implementation backlink consistency test} {
911 set diff 0
912 set elements 10000
913 for {set j 0} {$j < $elements} {incr j} {
914 $r zadd myzset [expr rand()] "Element-$j"
915 $r zrem myzset "Element-[expr int(rand()*$elements)]"
916 }
917 set l1 [$r zrange myzset 0 -1]
918 set l2 [$r zrevrange myzset 0 -1]
919 for {set j 0} {$j < [llength $l1]} {incr j} {
920 if {[lindex $l1 $j] ne [lindex $l2 end-$j]} {
921 incr diff
922 }
923 }
924 format $diff
925 } {0}
926
927 foreach fuzztype {binary alpha compr} {
928 test "FUZZ stresser with data model $fuzztype" {
929 set err 0
930 for {set i 0} {$i < 10000} {incr i} {
931 set fuzz [randstring 0 512 $fuzztype]
932 $r set foo $fuzz
933 set got [$r get foo]
934 if {$got ne $fuzz} {
935 set err [list $fuzz $got]
936 break
937 }
938 }
939 set _ $err
940 } {0}
941 }
942
943 # Leave the user with a clean DB before to exit
944 test {FLUSHDB} {
945 set aux {}
946 $r select 9
947 $r flushdb
948 lappend aux [$r dbsize]
949 $r select 10
950 $r flushdb
951 lappend aux [$r dbsize]
952 } {0 0}
953
954 test {Perform a final SAVE to leave a clean DB on disk} {
955 $r save
956 } {OK}
957
958 puts "\n[expr $::passed+$::failed] tests, $::passed passed, $::failed failed"
959 if {$::failed > 0} {
960 puts "\n*** WARNING!!! $::failed FAILED TESTS ***\n"
961 }
962 close $fd
963 }
964
965 proc stress {} {
966 set r [redis]
967 $r select 9
968 $r flushdb
969 while 1 {
970 set randkey [expr int(rand()*10000)]
971 set randval [expr int(rand()*10000)]
972 set randidx0 [expr int(rand()*10)]
973 set randidx1 [expr int(rand()*10)]
974 set cmd [expr int(rand()*20)]
975 catch {
976 if {$cmd == 0} {$r set $randkey $randval}
977 if {$cmd == 1} {$r get $randkey}
978 if {$cmd == 2} {$r incr $randkey}
979 if {$cmd == 3} {$r lpush $randkey $randval}
980 if {$cmd == 4} {$r rpop $randkey}
981 if {$cmd == 5} {$r del $randkey}
982 if {$cmd == 6} {$r llen $randkey}
983 if {$cmd == 7} {$r lrange $randkey $randidx0 $randidx1}
984 if {$cmd == 8} {$r ltrim $randkey $randidx0 $randidx1}
985 if {$cmd == 9} {$r lindex $randkey $randidx0}
986 if {$cmd == 10} {$r lset $randkey $randidx0 $randval}
987 if {$cmd == 11} {$r sadd $randkey $randval}
988 if {$cmd == 12} {$r srem $randkey $randval}
989 if {$cmd == 13} {$r smove $randkey $randval}
990 if {$cmd == 14} {$r scard $randkey}
991 if {$cmd == 15} {$r expire $randkey [expr $randval%60]}
992 }
993 flush stdout
994 }
995 $r flushdb
996 $r close
997 }
998
999 # Before to run the test check if DB 9 and DB 10 are empty
1000 set r [redis]
1001 $r select 9
1002 set db9size [$r dbsize]
1003 $r select 10
1004 set db10size [$r dbsize]
1005 if {$db9size != 0 || $db10size != 0} {
1006 puts "Can't run the tests against DB 9 and 10: DBs are not empty."
1007 exit 1
1008 }
1009 $r close
1010 unset r
1011 unset db9size
1012 unset db10size
1013
1014 if {[llength $argv] == 0} {
1015 main 127.0.0.1 6379
1016 } elseif {[llength $argv] == 1 && [lindex $argv 0] eq {stress}} {
1017 stress
1018 } else {
1019 main [lindex $argv 0] [lindex $argv 1]
1020 }