Commit b04ce2a3 authored by Pieter Noordhuis's avatar Pieter Noordhuis
Browse files

Merge master with resolved conflict in src/redis-cli.c

parents 4fe83b55 b4f2e412
...@@ -140,12 +140,19 @@ proc findKeyWithType {r type} { ...@@ -140,12 +140,19 @@ proc findKeyWithType {r type} {
return {} return {}
} }
proc createComplexDataset {r ops} { proc createComplexDataset {r ops {opt {}}} {
for {set j 0} {$j < $ops} {incr j} { for {set j 0} {$j < $ops} {incr j} {
set k [randomKey] set k [randomKey]
set k2 [randomKey] set k2 [randomKey]
set f [randomValue] set f [randomValue]
set v [randomValue] set v [randomValue]
if {[lsearch -exact $opt useexpire] != -1} {
if {rand() < 0.1} {
{*}$r expire [randomKey] [randomInt 2]
}
}
randpath { randpath {
set d [expr {rand()}] set d [expr {rand()}]
} { } {
......
...@@ -25,7 +25,14 @@ proc execute_tests name { ...@@ -25,7 +25,14 @@ proc execute_tests name {
# are nested, use "srv 0 pid" to get the pid of the inner server. To access # are nested, use "srv 0 pid" to get the pid of the inner server. To access
# outer servers, use "srv -1 pid" etcetera. # outer servers, use "srv -1 pid" etcetera.
set ::servers {} set ::servers {}
proc srv {level property} { proc srv {args} {
set level 0
if {[string is integer [lindex $args 0]]} {
set level [lindex $args 0]
set property [lindex $args 1]
} else {
set property [lindex $args 0]
}
set srv [lindex $::servers end+$level] set srv [lindex $::servers end+$level]
dict get $srv $property dict get $srv $property
} }
...@@ -88,6 +95,7 @@ proc main {} { ...@@ -88,6 +95,7 @@ proc main {} {
execute_tests "unit/cas" execute_tests "unit/cas"
execute_tests "integration/replication" execute_tests "integration/replication"
execute_tests "integration/aof" execute_tests "integration/aof"
# execute_tests "integration/redis-cli"
execute_tests "unit/pubsub" execute_tests "unit/pubsub"
# run tests with VM enabled # run tests with VM enabled
......
...@@ -148,12 +148,11 @@ start_server {tags {"basic"}} { ...@@ -148,12 +148,11 @@ start_server {tags {"basic"}} {
r get novar2 r get novar2
} {foobared} } {foobared}
test {SETNX will overwrite EXPIREing key} { test {SETNX against volatile key} {
r set x 10 r set x 10
r expire x 10000 r expire x 10000
r setnx x 20 list [r setnx x 20] [r get x]
r get x } {0 10}
} {20}
test {EXISTS} { test {EXISTS} {
set res {} set res {}
...@@ -362,13 +361,6 @@ start_server {tags {"basic"}} { ...@@ -362,13 +361,6 @@ start_server {tags {"basic"}} {
list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2] list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]
} {1 xxx yyy} } {1 xxx yyy}
test {MSETNX should remove all the volatile keys even on failure} {
r mset x 1 y 2 z 3
r expire y 10000
r expire z 10000
list [r msetnx x A y B z C] [r mget x y z]
} {0 {1 {} {}}}
test {STRLEN against non existing key} { test {STRLEN against non existing key} {
r strlen notakey r strlen notakey
} {0} } {0}
......
start_server {tags {"expire"}} { start_server {tags {"expire"}} {
test {EXPIRE - don't set timeouts multiple times} { test {EXPIRE - set timeouts multiple times} {
r set x foobar r set x foobar
set v1 [r expire x 5] set v1 [r expire x 5]
set v2 [r ttl x] set v2 [r ttl x]
set v3 [r expire x 10] set v3 [r expire x 10]
set v4 [r ttl x] set v4 [r ttl x]
r expire x 4
list $v1 $v2 $v3 $v4 list $v1 $v2 $v3 $v4
} {1 5 0 5} } {1 5 1 10}
test {EXPIRE - It should be still possible to read 'x'} { test {EXPIRE - It should be still possible to read 'x'} {
r get x r get x
...@@ -19,13 +20,13 @@ start_server {tags {"expire"}} { ...@@ -19,13 +20,13 @@ start_server {tags {"expire"}} {
} {{} 0} } {{} 0}
} }
test {EXPIRE - Delete on write policy} { test {EXPIRE - write on expire should work} {
r del x r del x
r lpush x foo r lpush x foo
r expire x 1000 r expire x 1000
r lpush x bar r lpush x bar
r lrange x 0 -1 r lrange x 0 -1
} {bar} } {bar foo}
test {EXPIREAT - Check for EXPIRE alike behavior} { test {EXPIREAT - Check for EXPIRE alike behavior} {
r del x r del x
...@@ -59,4 +60,15 @@ start_server {tags {"expire"}} { ...@@ -59,4 +60,15 @@ start_server {tags {"expire"}} {
catch {r setex z -10 foo} e catch {r setex z -10 foo} e
set _ $e set _ $e
} {*invalid expire*} } {*invalid expire*}
test {PERSIST can undo an EXPIRE} {
r set x foo
r expire x 50
list [r ttl x] [r persist x] [r ttl x] [r get x]
} {50 1 -1 foo}
test {PERSIST returns 0 against non existing or non volatile keys} {
r set x foo
list [r persist foo] [r persist nokeyatall]
} {0 0}
} }
start_server {} { start_server {tags {"other"}} {
test {SAVE - make sure there are all the types as values} { test {SAVE - make sure there are all the types as values} {
# Wait for a background saving in progress to terminate # Wait for a background saving in progress to terminate
waitForBgsave r waitForBgsave r
......
start_server {} { start_server {tags {"protocol"}} {
test {Handle an empty query well} { test {Handle an empty query well} {
set fd [r channel] set fd [r channel]
puts -nonewline $fd "\r\n" puts -nonewline $fd "\r\n"
...@@ -27,6 +27,13 @@ start_server {} { ...@@ -27,6 +27,13 @@ start_server {} {
gets $fd gets $fd
} {*invalid bulk*count*} } {*invalid bulk*count*}
test {bulk payload is not a number} {
set fd [r channel]
puts -nonewline $fd "SET x blabla\r\n"
flush $fd
gets $fd
} {*invalid bulk*count*}
test {Multi bulk request not followed by bulk args} { test {Multi bulk request not followed by bulk args} {
set fd [r channel] set fd [r channel]
puts -nonewline $fd "*1\r\nfoo\r\n" puts -nonewline $fd "*1\r\nfoo\r\n"
......
start_server {tags {"sort"}} { start_server {
test {SORT ALPHA against integer encoded strings} { tags {"sort"}
overrides {
"list-max-ziplist-value" 16
"list-max-ziplist-entries" 32
"set-max-intset-entries" 32
}
} {
proc create_random_dataset {num cmd} {
set tosort {}
set result {}
array set seenrand {}
r del tosort
for {set i 0} {$i < $num} {incr i} {
# Make sure all the weights are different because
# Redis does not use a stable sort but Tcl does.
while 1 {
randpath {
set rint [expr int(rand()*1000000)]
} {
set rint [expr rand()]
}
if {![info exists seenrand($rint)]} break
}
set seenrand($rint) x
r $cmd tosort $i
r set weight_$i $rint
r hset wobj_$i weight $rint
lappend tosort [list $i $rint]
}
set sorted [lsort -index 1 -real $tosort]
for {set i 0} {$i < $num} {incr i} {
lappend result [lindex $sorted $i 0]
}
set _ $result
}
foreach {num cmd enc title} {
16 lpush ziplist "Ziplist"
1000 lpush linkedlist "Linked list"
10000 lpush linkedlist "Big Linked list"
16 sadd intset "Intset"
1000 sadd hashtable "Hash table"
10000 sadd hashtable "Big Hash table"
} {
set result [create_random_dataset $num $cmd]
assert_encoding $enc tosort
test "$title: SORT BY key" {
assert_equal $result [r sort tosort {BY weight_*}]
}
test "$title: SORT BY hash field" {
assert_equal $result [r sort tosort {BY wobj_*->weight}]
}
}
set result [create_random_dataset 16 lpush]
test "SORT GET #" {
assert_equal [lsort -integer $result] [r sort tosort GET #]
}
test "SORT GET <const>" {
r del foo
set res [r sort tosort GET foo]
assert_equal 16 [llength $res]
foreach item $res { assert_equal {} $item }
}
test "SORT GET (key and hash) with sanity check" {
set l1 [r sort tosort GET # GET weight_*]
set l2 [r sort tosort GET # GET wobj_*->weight]
foreach {id1 w1} $l1 {id2 w2} $l2 {
assert_equal $id1 $id2
assert_equal $w1 [r get weight_$id1]
assert_equal $w2 [r get weight_$id1]
}
}
test "SORT BY key STORE" {
r sort tosort {BY weight_*} store sort-res
assert_equal $result [r lrange sort-res 0 -1]
assert_equal 16 [r llen sort-res]
assert_encoding ziplist sort-res
}
test "SORT BY hash field STORE" {
r sort tosort {BY wobj_*->weight} store sort-res
assert_equal $result [r lrange sort-res 0 -1]
assert_equal 16 [r llen sort-res]
assert_encoding ziplist sort-res
}
test "SORT DESC" {
assert_equal [lsort -decreasing -integer $result] [r sort tosort {DESC}]
}
test "SORT ALPHA against integer encoded strings" {
r del mylist r del mylist
r lpush mylist 2 r lpush mylist 2
r lpush mylist 1 r lpush mylist 1
...@@ -8,89 +104,41 @@ start_server {tags {"sort"}} { ...@@ -8,89 +104,41 @@ start_server {tags {"sort"}} {
r sort mylist alpha r sort mylist alpha
} {1 10 2 3} } {1 10 2 3}
tags {"slow"} { test "SORT sorted set" {
set res {} r del zset
test {Create a random list and a random set} { r zadd zset 1 a
set tosort {} r zadd zset 5 b
array set seenrand {} r zadd zset 2 c
for {set i 0} {$i < 10000} {incr i} { r zadd zset 10 d
while 1 { r zadd zset 3 e
# Make sure all the weights are different because r sort zset alpha desc
# Redis does not use a stable sort but Tcl does. } {e d c b a}
randpath {
set rint [expr int(rand()*1000000)]
} {
set rint [expr rand()]
}
if {![info exists seenrand($rint)]} break
}
set seenrand($rint) x
r lpush tosort $i
r sadd tosort-set $i
r set weight_$i $rint
r hset wobj_$i weight $rint
lappend tosort [list $i $rint]
}
set sorted [lsort -index 1 -real $tosort]
for {set i 0} {$i < 10000} {incr i} {
lappend res [lindex $sorted $i 0]
}
format {}
} {}
test {SORT with BY against the newly created list} {
r sort tosort {BY weight_*}
} $res
test {SORT with BY (hash field) against the newly created list} {
r sort tosort {BY wobj_*->weight}
} $res
test {SORT with GET (key+hash) with sanity check of each element (list)} {
set err {}
set l1 [r sort tosort GET # GET weight_*]
set l2 [r sort tosort GET # GET wobj_*->weight]
foreach {id1 w1} $l1 {id2 w2} $l2 {
set realweight [r get weight_$id1]
if {$id1 != $id2} {
set err "ID mismatch $id1 != $id2"
break
}
if {$realweight != $w1 || $realweight != $w2} {
set err "Weights mismatch! w1: $w1 w2: $w2 real: $realweight"
break
}
}
set _ $err
} {}
test {SORT with BY, but against the newly created set} {
r sort tosort-set {BY weight_*}
} $res
test {SORT with BY (hash field), but against the newly created set} {
r sort tosort-set {BY wobj_*->weight}
} $res
test {SORT with BY and STORE against the newly created list} {
r sort tosort {BY weight_*} store sort-res
r lrange sort-res 0 -1
} $res
test {SORT with BY (hash field) and STORE against the newly created list} { test "SORT sorted set: +inf and -inf handling" {
r sort tosort {BY wobj_*->weight} store sort-res r del zset
r lrange sort-res 0 -1 r zadd zset -100 a
} $res r zadd zset 200 b
r zadd zset -300 c
r zadd zset 1000000 d
r zadd zset +inf max
r zadd zset -inf min
r zrange zset 0 -1
} {min c a b d max}
test {SORT direct, numeric, against the newly created list} { test "SORT regression for issue #19, sorting floats" {
r sort tosort r flushdb
} [lsort -integer $res] set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}
foreach x $floats {
r lpush mylist $x
}
assert_equal [lsort -real $floats] [r sort mylist]
}
test {SORT decreasing sort} { tags {"slow"} {
r sort tosort {DESC} set num 100
} [lsort -decreasing -integer $res] set res [create_random_dataset $num lpush]
test {SORT speed, sorting 10000 elements list using BY, 100 times} { test "SORT speed, $num element list BY key, 100 times" {
set start [clock clicks -milliseconds] set start [clock clicks -milliseconds]
for {set i 0} {$i < 100} {incr i} { for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY weight_* LIMIT 0 10}] set sorted [r sort tosort {BY weight_* LIMIT 0 10}]
...@@ -98,10 +146,9 @@ start_server {tags {"sort"}} { ...@@ -98,10 +146,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start] set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
flush stdout flush stdout
format {} }
} {}
test {SORT speed, as above but against hash field} { test "SORT speed, $num element list BY hash field, 100 times" {
set start [clock clicks -milliseconds] set start [clock clicks -milliseconds]
for {set i 0} {$i < 100} {incr i} { for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY wobj_*->weight LIMIT 0 10}] set sorted [r sort tosort {BY wobj_*->weight LIMIT 0 10}]
...@@ -109,10 +156,9 @@ start_server {tags {"sort"}} { ...@@ -109,10 +156,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start] set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
flush stdout flush stdout
format {} }
} {}
test {SORT speed, sorting 10000 elements list directly, 100 times} { test "SORT speed, $num element list directly, 100 times" {
set start [clock clicks -milliseconds] set start [clock clicks -milliseconds]
for {set i 0} {$i < 100} {incr i} { for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {LIMIT 0 10}] set sorted [r sort tosort {LIMIT 0 10}]
...@@ -120,10 +166,9 @@ start_server {tags {"sort"}} { ...@@ -120,10 +166,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start] set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
flush stdout flush stdout
format {} }
} {}
test {SORT speed, pseudo-sorting 10000 elements list, BY <const>, 100 times} { test "SORT speed, $num element list BY <const>, 100 times" {
set start [clock clicks -milliseconds] set start [clock clicks -milliseconds]
for {set i 0} {$i < 100} {incr i} { for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY nokey LIMIT 0 10}] set sorted [r sort tosort {BY nokey LIMIT 0 10}]
...@@ -131,49 +176,6 @@ start_server {tags {"sort"}} { ...@@ -131,49 +176,6 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start] set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
flush stdout flush stdout
format {}
} {}
}
test {SORT regression for issue #19, sorting floats} {
r flushdb
foreach x {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} {
r lpush mylist $x
} }
r sort mylist }
} [lsort -real {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}]
test {SORT with GET #} {
r del mylist
r lpush mylist 1
r lpush mylist 2
r lpush mylist 3
r mset weight_1 10 weight_2 5 weight_3 30
r sort mylist BY weight_* GET #
} {2 1 3}
test {SORT with constant GET} {
r sort mylist GET foo
} {{} {} {}}
test {SORT against sorted sets} {
r del zset
r zadd zset 1 a
r zadd zset 5 b
r zadd zset 2 c
r zadd zset 10 d
r zadd zset 3 e
r sort zset alpha desc
} {e d c b a}
test {Sorted sets +inf and -inf handling} {
r del zset
r zadd zset -100 a
r zadd zset 200 b
r zadd zset -300 c
r zadd zset 1000000 d
r zadd zset +inf max
r zadd zset -inf min
r zrange zset 0 -1
} {min c a b d max}
} }
...@@ -15,8 +15,8 @@ start_server {tags {"hash"}} { ...@@ -15,8 +15,8 @@ start_server {tags {"hash"}} {
} {8} } {8}
test {Is the small hash encoded with a zipmap?} { test {Is the small hash encoded with a zipmap?} {
r debug object smallhash assert_encoding zipmap smallhash
} {*zipmap*} }
test {HSET/HLEN - Big hash creation} { test {HSET/HLEN - Big hash creation} {
array set bighash {} array set bighash {}
...@@ -34,8 +34,8 @@ start_server {tags {"hash"}} { ...@@ -34,8 +34,8 @@ start_server {tags {"hash"}} {
} {1024} } {1024}
test {Is the big hash encoded with a zipmap?} { test {Is the big hash encoded with a zipmap?} {
r debug object bighash assert_encoding hashtable bighash
} {*hashtable*} }
test {HGET against the small hash} { test {HGET against the small hash} {
set err {} set err {}
......
...@@ -139,6 +139,28 @@ start_server { ...@@ -139,6 +139,28 @@ start_server {
assert_equal 0 [r exists blist1] assert_equal 0 [r exists blist1]
} }
test "$pop: with negative timeout" {
set rd [redis_deferring_client]
$rd $pop blist1 -1
assert_error "ERR*is negative*" {$rd read}
}
test "$pop: with non-integer timeout" {
set rd [redis_deferring_client]
$rd $pop blist1 1.1
assert_error "ERR*not an integer*" {$rd read}
}
test "$pop: with zero timeout should block indefinitely" {
# To test this, use a timeout of 0 and wait a second.
# The blocking pop should still be waiting for a push.
set rd [redis_deferring_client]
$rd $pop blist1 0
after 1000
r rpush blist1 foo
assert_equal {blist1 foo} [$rd read]
}
test "$pop: second argument is not a list" { test "$pop: second argument is not a list" {
set rd [redis_deferring_client] set rd [redis_deferring_client]
r del blist1 blist2 r del blist1 blist2
...@@ -172,6 +194,17 @@ start_server { ...@@ -172,6 +194,17 @@ start_server {
} }
} }
test {BLPOP inside a transaction} {
r del xlist
r lpush xlist foo
r lpush xlist bar
r multi
r blpop xlist 0
r blpop xlist 0
r blpop xlist 0
r exec
} {{xlist bar} {xlist foo} {}}
test {LPUSHX, RPUSHX - generic} { test {LPUSHX, RPUSHX - generic} {
r del xlist r del xlist
assert_equal 0 [r lpushx xlist a] assert_equal 0 [r lpushx xlist a]
...@@ -570,5 +603,76 @@ start_server { ...@@ -570,5 +603,76 @@ start_server {
assert_equal 1 [r lrem myotherlist 1 2] assert_equal 1 [r lrem myotherlist 1 2]
assert_equal 3 [r llen myotherlist] assert_equal 3 [r llen myotherlist]
} }
}
}
start_server {
tags {list ziplist}
overrides {
"list-max-ziplist-value" 200000
"list-max-ziplist-entries" 256
}
} {
test {Explicit regression for a list bug} {
set mylist {49376042582 {BkG2o\pIC]4YYJa9cJ4GWZalG[4tin;1D2whSkCOW`mX;SFXGyS8sedcff3fQI^tgPCC@^Nu1J6o]meM@Lko]t_jRyo<xSJ1oObDYd`ppZuW6P@fS278YaOx=s6lvdFlMbP0[SbkI^Kr\HBXtuFaA^mDx:yzS4a[skiiPWhT<nNfAf=aQVfclcuwDrfe;iVuKdNvB9kbfq>tK?tH[\EvWqS]b`o2OCtjg:?nUTwdjpcUm]y:pg5q24q7LlCOwQE^}}
r del l
r rpush l [lindex $mylist 0]
r rpush l [lindex $mylist 1]
assert_equal [r lindex l 0] [lindex $mylist 0]
assert_equal [r lindex l 1] [lindex $mylist 1]
}
tags {slow} {
test {ziplist implementation: value encoding and backlink} {
for {set j 0} {$j < 100} {incr j} {
r del l
set l {}
for {set i 0} {$i < 200} {incr i} {
randpath {
set data [string repeat x [randomInt 100000]]
} {
set data [randomInt 65536]
} {
set data [randomInt 4294967296]
} {
set data [randomInt 18446744073709551616]
}
lappend l $data
r rpush l $data
}
assert_equal [llength $l] [r llen l]
# Traverse backward
for {set i 199} {$i >= 0} {incr i -1} {
if {[lindex $l $i] ne [r lindex l $i]} {
assert_equal [lindex $l $i] [r lindex l $i]
}
}
}
}
test {ziplist implementation: encoding stress testing} {
for {set j 0} {$j < 200} {incr j} {
r del l
set l {}
set len [randomInt 400]
for {set i 0} {$i < $len} {incr i} {
set rv [randomValue]
randpath {
lappend l $rv
r rpush l $rv
} {
set l [concat [list $rv] $l]
r lpush l $rv
}
}
assert_equal [llength $l] [r llen l]
for {set i 0} {$i < 200} {incr i} {
if {[lindex $l $i] ne [r lindex l $i]} {
assert_equal [lindex $l $i] [r lindex l $i]
}
}
}
}
} }
} }
start_server {tags {"set"}} { start_server {
test {SADD, SCARD, SISMEMBER, SMEMBERS basics} { tags {"set"}
r sadd myset foo overrides {
r sadd myset bar "set-max-intset-entries" 512
list [r scard myset] [r sismember myset foo] \ }
[r sismember myset bar] [r sismember myset bla] \ } {
[lsort [r smembers myset]] proc create_set {key entries} {
} {2 1 1 0 {bar foo}} r del $key
foreach entry $entries { r sadd $key $entry }
test {SADD adding the same element multiple times} { }
r sadd myset foo
r sadd myset foo test {SADD, SCARD, SISMEMBER, SMEMBERS basics - regular set} {
r sadd myset foo create_set myset {foo}
r scard myset assert_encoding hashtable myset
} {2} assert_equal 1 [r sadd myset bar]
assert_equal 0 [r sadd myset bar]
assert_equal 2 [r scard myset]
assert_equal 1 [r sismember myset foo]
assert_equal 1 [r sismember myset bar]
assert_equal 0 [r sismember myset bla]
assert_equal {bar foo} [lsort [r smembers myset]]
}
test {SADD, SCARD, SISMEMBER, SMEMBERS basics - intset} {
create_set myset {17}
assert_encoding intset myset
assert_equal 1 [r sadd myset 16]
assert_equal 0 [r sadd myset 16]
assert_equal 2 [r scard myset]
assert_equal 1 [r sismember myset 16]
assert_equal 1 [r sismember myset 17]
assert_equal 0 [r sismember myset 18]
assert_equal {16 17} [lsort [r smembers myset]]
}
test {SADD against non set} { test {SADD against non set} {
r lpush mylist foo r lpush mylist foo
catch {r sadd mylist bar} err assert_error ERR*kind* {r sadd mylist bar}
format $err }
} {ERR*kind*}
test "SADD a non-integer against an intset" {
test {SREM basics} { create_set myset {1 2 3}
r sadd myset ciao assert_encoding intset myset
r srem myset foo assert_equal 1 [r sadd myset a]
lsort [r smembers myset] assert_encoding hashtable myset
} {bar ciao} }
test {Mass SADD and SINTER with two sets} { test "SADD an integer larger than 64 bits" {
for {set i 0} {$i < 1000} {incr i} { create_set myset {213244124402402314402033402}
assert_encoding hashtable myset
assert_equal 1 [r sismember myset 213244124402402314402033402]
}
test "SADD overflows the maximum allowed integers in an intset" {
r del myset
for {set i 0} {$i < 512} {incr i} { r sadd myset $i }
assert_encoding intset myset
assert_equal 1 [r sadd myset 512]
assert_encoding hashtable myset
}
test "Set encoding after DEBUG RELOAD" {
r del myintset myhashset mylargeintset
for {set i 0} {$i < 100} {incr i} { r sadd myintset $i }
for {set i 0} {$i < 1280} {incr i} { r sadd mylargeintset $i }
for {set i 0} {$i < 256} {incr i} { r sadd myhashset [format "i%03d" $i] }
assert_encoding intset myintset
assert_encoding hashtable mylargeintset
assert_encoding hashtable myhashset
r debug reload
assert_encoding intset myintset
assert_encoding hashtable mylargeintset
assert_encoding hashtable myhashset
}
test {SREM basics - regular set} {
create_set myset {foo bar ciao}
assert_encoding hashtable myset
assert_equal 0 [r srem myset qux]
assert_equal 1 [r srem myset foo]
assert_equal {bar ciao} [lsort [r smembers myset]]
}
test {SREM basics - intset} {
create_set myset {3 4 5}
assert_encoding intset myset
assert_equal 0 [r srem myset 6]
assert_equal 1 [r srem myset 4]
assert_equal {3 5} [lsort [r smembers myset]]
}
foreach {type} {hashtable intset} {
for {set i 1} {$i <= 5} {incr i} {
r del [format "set%d" $i]
}
for {set i 0} {$i < 200} {incr i} {
r sadd set1 $i r sadd set1 $i
r sadd set2 [expr $i+995] r sadd set2 [expr $i+195]
}
foreach i {199 195 1000 2000} {
r sadd set3 $i
}
for {set i 5} {$i < 200} {incr i} {
r sadd set4 $i
} }
lsort [r sinter set1 set2] r sadd set5 0
} {995 996 997 998 999}
test {SUNION with two sets} { # To make sure the sets are encoded as the type we are testing -- also
lsort [r sunion set1 set2] # when the VM is enabled and the values may be swapped in and out
} [lsort -uniq "[r smembers set1] [r smembers set2]"] # while the tests are running -- an extra element is added to every
# set that determines its encoding.
set large 200
if {$type eq "hashtable"} {
set large foo
}
test {SINTERSTORE with two sets} { for {set i 1} {$i <= 5} {incr i} {
r sinterstore setres set1 set2 r sadd [format "set%d" $i] $large
lsort [r smembers setres] }
} {995 996 997 998 999}
test {SINTERSTORE with two sets, after a DEBUG RELOAD} { test "Generated sets must be encoded as $type" {
r debug reload for {set i 1} {$i <= 5} {incr i} {
r sinterstore setres set1 set2 assert_encoding $type [format "set%d" $i]
lsort [r smembers setres] }
} {995 996 997 998 999} }
test "SINTER with two sets - $type" {
assert_equal [list 195 196 197 198 199 $large] [lsort [r sinter set1 set2]]
}
test {SUNIONSTORE with two sets} { test "SINTERSTORE with two sets - $type" {
r sunionstore setres set1 set2 r sinterstore setres set1 set2
lsort [r smembers setres] assert_encoding $type setres
} [lsort -uniq "[r smembers set1] [r smembers set2]"] assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]
}
test {SUNIONSTORE against non existing keys} { test "SINTERSTORE with two sets, after a DEBUG RELOAD - $type" {
r debug reload
r sinterstore setres set1 set2
assert_encoding $type setres
assert_equal [list 195 196 197 198 199 $large] [lsort [r smembers setres]]
}
test "SUNION with two sets - $type" {
set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
assert_equal $expected [lsort [r sunion set1 set2]]
}
test "SUNIONSTORE with two sets - $type" {
r sunionstore setres set1 set2
assert_encoding $type setres
set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
assert_equal $expected [lsort [r smembers setres]]
}
test "SINTER against three sets - $type" {
assert_equal [list 195 199 $large] [lsort [r sinter set1 set2 set3]]
}
test "SINTERSTORE with three sets - $type" {
r sinterstore setres set1 set2 set3
assert_equal [list 195 199 $large] [lsort [r smembers setres]]
}
test "SUNION with non existing keys - $type" {
set expected [lsort -uniq "[r smembers set1] [r smembers set2]"]
assert_equal $expected [lsort [r sunion nokey1 set1 set2 nokey2]]
}
test "SDIFF with two sets - $type" {
assert_equal {0 1 2 3 4} [lsort [r sdiff set1 set4]]
}
test "SDIFF with three sets - $type" {
assert_equal {1 2 3 4} [lsort [r sdiff set1 set4 set5]]
}
test "SDIFFSTORE with three sets - $type" {
r sdiffstore setres set1 set4 set5
# The type is determined by type of the first key to diff against.
# See the implementation for more information.
assert_encoding $type setres
assert_equal {1 2 3 4} [lsort [r smembers setres]]
}
}
test "SINTER against non-set should throw error" {
r set key1 x
assert_error "ERR*wrong kind*" {r sinter key1 noset}
}
test "SUNION against non-set should throw error" {
r set key1 x
assert_error "ERR*wrong kind*" {r sunion key1 noset}
}
test "SINTERSTORE against non existing keys should delete dstkey" {
r set setres xxx r set setres xxx
list [r sunionstore setres foo111 bar222] [r exists xxx] assert_equal 0 [r sinterstore setres foo111 bar222]
} {0 0} assert_equal 0 [r exists setres]
}
test {SINTER against three sets} {
r sadd set3 999 test "SUNIONSTORE against non existing keys should delete dstkey" {
r sadd set3 995 r set setres xxx
r sadd set3 1000 assert_equal 0 [r sunionstore setres foo111 bar222]
r sadd set3 2000 assert_equal 0 [r exists setres]
lsort [r sinter set1 set2 set3] }
} {995 999}
foreach {type contents} {hashtable {a b c} intset {1 2 3}} {
test {SINTERSTORE with three sets} { test "SPOP basics - $type" {
r sinterstore setres set1 set2 set3 create_set myset $contents
lsort [r smembers setres] assert_encoding $type myset
} {995 999} assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]
assert_equal 0 [r scard myset]
test {SUNION with non existing keys} {
lsort [r sunion nokey1 set1 set2 nokey2]
} [lsort -uniq "[r smembers set1] [r smembers set2]"]
test {SDIFF with two sets} {
for {set i 5} {$i < 1000} {incr i} {
r sadd set4 $i
} }
lsort [r sdiff set1 set4]
} {0 1 2 3 4}
test {SDIFF with three sets} { test "SRANDMEMBER - $type" {
r sadd set5 0 create_set myset $contents
lsort [r sdiff set1 set4 set5] unset -nocomplain myset
} {1 2 3 4} array set myset {}
for {set i 0} {$i < 100} {incr i} {
set myset([r srandmember myset]) 1
}
assert_equal $contents [lsort [array names myset]]
}
}
test {SDIFFSTORE with three sets} { proc setup_move {} {
r sdiffstore sres set1 set4 set5 r del myset3 myset4
lsort [r smembers sres] create_set myset1 {1 a b}
} {1 2 3 4} create_set myset2 {2 3 4}
assert_encoding hashtable myset1
assert_encoding intset myset2
}
test {SPOP basics} { test "SMOVE basics - from regular set to intset" {
r del myset # move a non-integer element to an intset should convert encoding
r sadd myset 1 setup_move
r sadd myset 2 assert_equal 1 [r smove myset1 myset2 a]
r sadd myset 3 assert_equal {1 b} [lsort [r smembers myset1]]
list [lsort [list [r spop myset] [r spop myset] [r spop myset]]] [r scard myset] assert_equal {2 3 4 a} [lsort [r smembers myset2]]
} {{1 2 3} 0} assert_encoding hashtable myset2
test {SRANDMEMBER} { # move an integer element should not convert the encoding
r del myset setup_move
r sadd myset a assert_equal 1 [r smove myset1 myset2 1]
r sadd myset b assert_equal {a b} [lsort [r smembers myset1]]
r sadd myset c assert_equal {1 2 3 4} [lsort [r smembers myset2]]
unset -nocomplain myset assert_encoding intset myset2
array set myset {} }
for {set i 0} {$i < 100} {incr i} {
set myset([r srandmember myset]) 1 test "SMOVE basics - from intset to regular set" {
} setup_move
lsort [array names myset] assert_equal 1 [r smove myset2 myset1 2]
} {a b c} assert_equal {1 2 a b} [lsort [r smembers myset1]]
assert_equal {3 4} [lsort [r smembers myset2]]
test {SMOVE basics} { }
r sadd myset1 a
r sadd myset1 b test "SMOVE non existing key" {
r sadd myset1 c setup_move
r sadd myset2 x assert_equal 0 [r smove myset1 myset2 foo]
r sadd myset2 y assert_equal {1 a b} [lsort [r smembers myset1]]
r sadd myset2 z assert_equal {2 3 4} [lsort [r smembers myset2]]
r smove myset1 myset2 a }
list [lsort [r smembers myset2]] [lsort [r smembers myset1]]
} {{a x y z} {b c}} test "SMOVE non existing src set" {
setup_move
test {SMOVE non existing key} { assert_equal 0 [r smove noset myset2 foo]
list [r smove myset1 myset2 foo] [lsort [r smembers myset2]] [lsort [r smembers myset1]] assert_equal {2 3 4} [lsort [r smembers myset2]]
} {0 {a x y z} {b c}} }
test {SMOVE non existing src set} { test "SMOVE from regular set to non existing destination set" {
list [r smove noset myset2 foo] [lsort [r smembers myset2]] setup_move
} {0 {a x y z}} assert_equal 1 [r smove myset1 myset3 a]
assert_equal {1 b} [lsort [r smembers myset1]]
test {SMOVE non existing dst set} { assert_equal {a} [lsort [r smembers myset3]]
list [r smove myset2 myset3 y] [lsort [r smembers myset2]] [lsort [r smembers myset3]] assert_encoding hashtable myset3
} {1 {a x z} y} }
test {SMOVE wrong src key type} { test "SMOVE from intset to non existing destination set" {
setup_move
assert_equal 1 [r smove myset2 myset3 2]
assert_equal {3 4} [lsort [r smembers myset2]]
assert_equal {2} [lsort [r smembers myset3]]
assert_encoding intset myset3
}
test "SMOVE wrong src key type" {
r set x 10 r set x 10
catch {r smove x myset2 foo} err assert_error "ERR*wrong kind*" {r smove x myset2 foo}
format $err }
} {ERR*}
test {SMOVE wrong dst key type} { test "SMOVE wrong dst key type" {
r set x 10 r set x 10
catch {r smove myset2 x foo} err assert_error "ERR*wrong kind*" {r smove myset2 x foo}
format $err }
} {ERR*}
tags {slow} {
test {intsets implementation stress testing} {
for {set j 0} {$j < 20} {incr j} {
unset -nocomplain s
array set s {}
r del s
set len [randomInt 1024]
for {set i 0} {$i < $len} {incr i} {
randpath {
set data [randomInt 65536]
} {
set data [randomInt 4294967296]
} {
set data [randomInt 18446744073709551616]
}
set s($data) {}
r sadd s $data
}
assert_equal [lsort [r smembers s]] [lsort [array names s]]
set len [array size s]
for {set i 0} {$i < $len} {incr i} {
set e [r spop s]
if {![info exists s($e)]} {
puts "Can't find '$e' on local array"
puts "Local array: [lsort [r smembers s]]"
puts "Remote array: [lsort [array names s]]"
error "exception"
}
array unset s $e
}
assert_equal [r scard s] 0
assert_equal [array size s] 0
}
}
}
} }
# redis-sha1.rb - Copyright (C) 2009 Salvatore Sanfilippo # redis-copy.rb - Copyright (C) 2009-2010 Salvatore Sanfilippo
# BSD license, See the COPYING file for more information. # BSD license, See the COPYING file for more information.
# #
# Performs the SHA1 sum of the whole datset. # Copy the whole dataset from one Redis instance to another one
# This is useful to spot bugs in persistence related code and to make sure
# Slaves and Masters are in SYNC.
# #
# If you hack this code make sure to sort keys and set elements as this are # WARNING: currently hashes and sorted sets are not supported! This
# unsorted elements. Otherwise the sum may differ with equal dataset. # program should be updated.
require 'rubygems' require 'rubygems'
require 'redis' require 'redis'
......
...@@ -21,15 +21,14 @@ case "$1" in ...@@ -21,15 +21,14 @@ case "$1" in
then then
echo -n "$PIDFILE does not exist, process is not running\n" echo -n "$PIDFILE does not exist, process is not running\n"
else else
PID=$(cat $PIDFILE)
echo -n "Stopping ...\n" echo -n "Stopping ...\n"
echo -n "Sending SHUTDOWN\r\n" | nc localhost $REDISPORT & echo -n "SHUTDOWN\r\n" | nc localhost $REDISPORT &
PID=$(cat $PIDFILE)
while [ -x /proc/${PIDFILE} ] while [ -x /proc/${PIDFILE} ]
do do
echo "Waiting for Redis to shutdown ..." echo "Waiting for Redis to shutdown ..."
sleep 1 sleep 1
done done
rm $PIDFILE
echo "Redis stopped" echo "Redis stopped"
fi fi
;; ;;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment