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} {
return {}
}
proc createComplexDataset {r ops} {
proc createComplexDataset {r ops {opt {}}} {
for {set j 0} {$j < $ops} {incr j} {
set k [randomKey]
set k2 [randomKey]
set f [randomValue]
set v [randomValue]
if {[lsearch -exact $opt useexpire] != -1} {
if {rand() < 0.1} {
{*}$r expire [randomKey] [randomInt 2]
}
}
randpath {
set d [expr {rand()}]
} {
......
......@@ -25,7 +25,14 @@ proc execute_tests name {
# are nested, use "srv 0 pid" to get the pid of the inner server. To access
# outer servers, use "srv -1 pid" etcetera.
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]
dict get $srv $property
}
......@@ -88,6 +95,7 @@ proc main {} {
execute_tests "unit/cas"
execute_tests "integration/replication"
execute_tests "integration/aof"
# execute_tests "integration/redis-cli"
execute_tests "unit/pubsub"
# run tests with VM enabled
......
......@@ -148,12 +148,11 @@ start_server {tags {"basic"}} {
r get novar2
} {foobared}
test {SETNX will overwrite EXPIREing key} {
test {SETNX against volatile key} {
r set x 10
r expire x 10000
r setnx x 20
r get x
} {20}
list [r setnx x 20] [r get x]
} {0 10}
test {EXISTS} {
set res {}
......@@ -362,13 +361,6 @@ start_server {tags {"basic"}} {
list [r msetnx x1 xxx y2 yyy] [r get x1] [r get y2]
} {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} {
r strlen notakey
} {0}
......
start_server {tags {"expire"}} {
test {EXPIRE - don't set timeouts multiple times} {
test {EXPIRE - set timeouts multiple times} {
r set x foobar
set v1 [r expire x 5]
set v2 [r ttl x]
set v3 [r expire x 10]
set v4 [r ttl x]
r expire x 4
list $v1 $v2 $v3 $v4
} {1 5 0 5}
} {1 5 1 10}
test {EXPIRE - It should be still possible to read 'x'} {
r get x
......@@ -19,13 +20,13 @@ start_server {tags {"expire"}} {
} {{} 0}
}
test {EXPIRE - Delete on write policy} {
test {EXPIRE - write on expire should work} {
r del x
r lpush x foo
r expire x 1000
r lpush x bar
r lrange x 0 -1
} {bar}
} {bar foo}
test {EXPIREAT - Check for EXPIRE alike behavior} {
r del x
......@@ -59,4 +60,15 @@ start_server {tags {"expire"}} {
catch {r setex z -10 foo} e
set _ $e
} {*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} {
# Wait for a background saving in progress to terminate
waitForBgsave r
......
start_server {} {
start_server {tags {"protocol"}} {
test {Handle an empty query well} {
set fd [r channel]
puts -nonewline $fd "\r\n"
......@@ -27,6 +27,13 @@ start_server {} {
gets $fd
} {*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} {
set fd [r channel]
puts -nonewline $fd "*1\r\nfoo\r\n"
......
start_server {tags {"sort"}} {
test {SORT ALPHA against integer encoded strings} {
start_server {
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 lpush mylist 2
r lpush mylist 1
......@@ -8,89 +104,41 @@ start_server {tags {"sort"}} {
r sort mylist alpha
} {1 10 2 3}
tags {"slow"} {
set res {}
test {Create a random list and a random set} {
set tosort {}
array set seenrand {}
for {set i 0} {$i < 10000} {incr i} {
while 1 {
# Make sure all the weights are different because
# Redis does not use a stable sort but Tcl does.
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 sorted set" {
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 {SORT with BY (hash field) and STORE against the newly created list} {
r sort tosort {BY wobj_*->weight} store sort-res
r lrange sort-res 0 -1
} $res
test "SORT sorted set: +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}
test {SORT direct, numeric, against the newly created list} {
r sort tosort
} [lsort -integer $res]
test "SORT regression for issue #19, sorting floats" {
r flushdb
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} {
r sort tosort {DESC}
} [lsort -decreasing -integer $res]
tags {"slow"} {
set num 100
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]
for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY weight_* LIMIT 0 10}]
......@@ -98,10 +146,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
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]
for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY wobj_*->weight LIMIT 0 10}]
......@@ -109,10 +156,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
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]
for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {LIMIT 0 10}]
......@@ -120,10 +166,9 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
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]
for {set i 0} {$i < 100} {incr i} {
set sorted [r sort tosort {BY nokey LIMIT 0 10}]
......@@ -131,49 +176,6 @@ start_server {tags {"sort"}} {
set elapsed [expr [clock clicks -milliseconds]-$start]
puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
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"}} {
} {8}
test {Is the small hash encoded with a zipmap?} {
r debug object smallhash
} {*zipmap*}
assert_encoding zipmap smallhash
}
test {HSET/HLEN - Big hash creation} {
array set bighash {}
......@@ -34,8 +34,8 @@ start_server {tags {"hash"}} {
} {1024}
test {Is the big hash encoded with a zipmap?} {
r debug object bighash
} {*hashtable*}
assert_encoding hashtable bighash
}
test {HGET against the small hash} {
set err {}
......
......@@ -139,6 +139,28 @@ start_server {
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" {
set rd [redis_deferring_client]
r del blist1 blist2
......@@ -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} {
r del xlist
assert_equal 0 [r lpushx xlist a]
......@@ -570,5 +603,76 @@ start_server {
assert_equal 1 [r lrem myotherlist 1 2]
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"}} {
test {SADD, SCARD, SISMEMBER, SMEMBERS basics} {
r sadd myset foo
r sadd myset bar
list [r scard myset] [r sismember myset foo] \
[r sismember myset bar] [r sismember myset bla] \
[lsort [r smembers myset]]
} {2 1 1 0 {bar foo}}
test {SADD adding the same element multiple times} {
r sadd myset foo
r sadd myset foo
r sadd myset foo
r scard myset
} {2}
start_server {
tags {"set"}
overrides {
"set-max-intset-entries" 512
}
} {
proc create_set {key entries} {
r del $key
foreach entry $entries { r sadd $key $entry }
}
test {SADD, SCARD, SISMEMBER, SMEMBERS basics - regular set} {
create_set myset {foo}
assert_encoding hashtable myset
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} {
r lpush mylist foo
catch {r sadd mylist bar} err
format $err
} {ERR*kind*}
test {SREM basics} {
r sadd myset ciao
r srem myset foo
lsort [r smembers myset]
} {bar ciao}
test {Mass SADD and SINTER with two sets} {
for {set i 0} {$i < 1000} {incr i} {
assert_error ERR*kind* {r sadd mylist bar}
}
test "SADD a non-integer against an intset" {
create_set myset {1 2 3}
assert_encoding intset myset
assert_equal 1 [r sadd myset a]
assert_encoding hashtable myset
}
test "SADD an integer larger than 64 bits" {
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 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]
} {995 996 997 998 999}
r sadd set5 0
test {SUNION with two sets} {
lsort [r sunion set1 set2]
} [lsort -uniq "[r smembers set1] [r smembers set2]"]
# To make sure the sets are encoded as the type we are testing -- also
# when the VM is enabled and the values may be swapped in and out
# 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} {
r sinterstore setres set1 set2
lsort [r smembers setres]
} {995 996 997 998 999}
for {set i 1} {$i <= 5} {incr i} {
r sadd [format "set%d" $i] $large
}
test {SINTERSTORE with two sets, after a DEBUG RELOAD} {
r debug reload
r sinterstore setres set1 set2
lsort [r smembers setres]
} {995 996 997 998 999}
test "Generated sets must be encoded as $type" {
for {set i 1} {$i <= 5} {incr i} {
assert_encoding $type [format "set%d" $i]
}
}
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} {
r sunionstore setres set1 set2
lsort [r smembers setres]
} [lsort -uniq "[r smembers set1] [r smembers set2]"]
test "SINTERSTORE with two sets - $type" {
r sinterstore setres set1 set2
assert_encoding $type setres
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
list [r sunionstore setres foo111 bar222] [r exists xxx]
} {0 0}
test {SINTER against three sets} {
r sadd set3 999
r sadd set3 995
r sadd set3 1000
r sadd set3 2000
lsort [r sinter set1 set2 set3]
} {995 999}
test {SINTERSTORE with three sets} {
r sinterstore setres set1 set2 set3
lsort [r smembers setres]
} {995 999}
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
assert_equal 0 [r sinterstore setres foo111 bar222]
assert_equal 0 [r exists setres]
}
test "SUNIONSTORE against non existing keys should delete dstkey" {
r set setres xxx
assert_equal 0 [r sunionstore setres foo111 bar222]
assert_equal 0 [r exists setres]
}
foreach {type contents} {hashtable {a b c} intset {1 2 3}} {
test "SPOP basics - $type" {
create_set myset $contents
assert_encoding $type myset
assert_equal $contents [lsort [list [r spop myset] [r spop myset] [r spop myset]]]
assert_equal 0 [r scard myset]
}
lsort [r sdiff set1 set4]
} {0 1 2 3 4}
test {SDIFF with three sets} {
r sadd set5 0
lsort [r sdiff set1 set4 set5]
} {1 2 3 4}
test "SRANDMEMBER - $type" {
create_set myset $contents
unset -nocomplain myset
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} {
r sdiffstore sres set1 set4 set5
lsort [r smembers sres]
} {1 2 3 4}
proc setup_move {} {
r del myset3 myset4
create_set myset1 {1 a b}
create_set myset2 {2 3 4}
assert_encoding hashtable myset1
assert_encoding intset myset2
}
test {SPOP basics} {
r del myset
r sadd myset 1
r sadd myset 2
r sadd myset 3
list [lsort [list [r spop myset] [r spop myset] [r spop myset]]] [r scard myset]
} {{1 2 3} 0}
test {SRANDMEMBER} {
r del myset
r sadd myset a
r sadd myset b
r sadd myset c
unset -nocomplain myset
array set myset {}
for {set i 0} {$i < 100} {incr i} {
set myset([r srandmember myset]) 1
}
lsort [array names myset]
} {a b c}
test {SMOVE basics} {
r sadd myset1 a
r sadd myset1 b
r sadd myset1 c
r sadd myset2 x
r sadd myset2 y
r sadd myset2 z
r smove myset1 myset2 a
list [lsort [r smembers myset2]] [lsort [r smembers myset1]]
} {{a x y z} {b c}}
test {SMOVE non existing key} {
list [r smove myset1 myset2 foo] [lsort [r smembers myset2]] [lsort [r smembers myset1]]
} {0 {a x y z} {b c}}
test {SMOVE non existing src set} {
list [r smove noset myset2 foo] [lsort [r smembers myset2]]
} {0 {a x y z}}
test {SMOVE non existing dst set} {
list [r smove myset2 myset3 y] [lsort [r smembers myset2]] [lsort [r smembers myset3]]
} {1 {a x z} y}
test {SMOVE wrong src key type} {
test "SMOVE basics - from regular set to intset" {
# move a non-integer element to an intset should convert encoding
setup_move
assert_equal 1 [r smove myset1 myset2 a]
assert_equal {1 b} [lsort [r smembers myset1]]
assert_equal {2 3 4 a} [lsort [r smembers myset2]]
assert_encoding hashtable myset2
# move an integer element should not convert the encoding
setup_move
assert_equal 1 [r smove myset1 myset2 1]
assert_equal {a b} [lsort [r smembers myset1]]
assert_equal {1 2 3 4} [lsort [r smembers myset2]]
assert_encoding intset myset2
}
test "SMOVE basics - from intset to regular set" {
setup_move
assert_equal 1 [r smove myset2 myset1 2]
assert_equal {1 2 a b} [lsort [r smembers myset1]]
assert_equal {3 4} [lsort [r smembers myset2]]
}
test "SMOVE non existing key" {
setup_move
assert_equal 0 [r smove myset1 myset2 foo]
assert_equal {1 a b} [lsort [r smembers myset1]]
assert_equal {2 3 4} [lsort [r smembers myset2]]
}
test "SMOVE non existing src set" {
setup_move
assert_equal 0 [r smove noset myset2 foo]
assert_equal {2 3 4} [lsort [r smembers myset2]]
}
test "SMOVE from regular set to non existing destination set" {
setup_move
assert_equal 1 [r smove myset1 myset3 a]
assert_equal {1 b} [lsort [r smembers myset1]]
assert_equal {a} [lsort [r smembers myset3]]
assert_encoding hashtable myset3
}
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
catch {r smove x myset2 foo} err
format $err
} {ERR*}
assert_error "ERR*wrong kind*" {r smove x myset2 foo}
}
test {SMOVE wrong dst key type} {
test "SMOVE wrong dst key type" {
r set x 10
catch {r smove myset2 x foo} err
format $err
} {ERR*}
assert_error "ERR*wrong kind*" {r smove myset2 x foo}
}
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.
#
# Performs the SHA1 sum of the whole datset.
# This is useful to spot bugs in persistence related code and to make sure
# Slaves and Masters are in SYNC.
# Copy the whole dataset from one Redis instance to another one
#
# If you hack this code make sure to sort keys and set elements as this are
# unsorted elements. Otherwise the sum may differ with equal dataset.
# WARNING: currently hashes and sorted sets are not supported! This
# program should be updated.
require 'rubygems'
require 'redis'
......
......@@ -21,15 +21,14 @@ case "$1" in
then
echo -n "$PIDFILE does not exist, process is not running\n"
else
PID=$(cat $PIDFILE)
echo -n "Stopping ...\n"
echo -n "Sending SHUTDOWN\r\n" | nc localhost $REDISPORT &
PID=$(cat $PIDFILE)
echo -n "SHUTDOWN\r\n" | nc localhost $REDISPORT &
while [ -x /proc/${PIDFILE} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
rm $PIDFILE
echo "Redis stopped"
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