Unverified Commit ec2d1807 authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

Merge 6.2 RC2

parents b8c67ce4 049f2f08
...@@ -196,6 +196,29 @@ start_server {tags {"multi"}} { ...@@ -196,6 +196,29 @@ start_server {tags {"multi"}} {
r exec r exec
} {PONG} } {PONG}
test {SWAPDB is able to touch the watched keys that exist} {
r flushall
r select 0
r set x 30
r watch x ;# make sure x (set to 30) doesn't change (SWAPDB will "delete" it)
r swapdb 0 1
r multi
r ping
r exec
} {}
test {SWAPDB is able to touch the watched keys that do not exist} {
r flushall
r select 1
r set x 30
r select 0
r watch x ;# make sure the key x (currently missing) doesn't change (SWAPDB will create it)
r swapdb 0 1
r multi
r ping
r exec
} {}
test {WATCH is able to remember the DB a key belongs to} { test {WATCH is able to remember the DB a key belongs to} {
r select 5 r select 5
r set x 30 r set x 30
...@@ -299,10 +322,14 @@ start_server {tags {"multi"}} { ...@@ -299,10 +322,14 @@ start_server {tags {"multi"}} {
r multi r multi
r del foo r del foo
r exec r exec
# add another command so that when we see it we know multi-exec wasn't
# propagated
r incr foo
assert_replication_stream $repl { assert_replication_stream $repl {
{select *} {select *}
{multi} {incr foo}
{exec}
} }
close_replication_stream $repl close_replication_stream $repl
} }
...@@ -521,4 +548,83 @@ start_server {tags {"multi"}} { ...@@ -521,4 +548,83 @@ start_server {tags {"multi"}} {
list $m $res list $m $res
} {OK {{} {} {} {} {} {} {} {}}} } {OK {{} {} {} {} {} {} {} {}}}
test {MULTI propagation of PUBLISH} {
set repl [attach_to_replication_stream]
# make sure that PUBLISH inside MULTI is propagated in a transaction
r multi
r publish bla bla
r exec
assert_replication_stream $repl {
{select *}
{multi}
{publish bla bla}
{exec}
}
close_replication_stream $repl
}
test {MULTI propagation of SCRIPT LOAD} {
set repl [attach_to_replication_stream]
# make sure that SCRIPT LOAD inside MULTI is propagated in a transaction
r multi
r script load {redis.call('set', KEYS[1], 'foo')}
set res [r exec]
set sha [lindex $res 0]
assert_replication_stream $repl {
{select *}
{multi}
{script load *}
{exec}
}
close_replication_stream $repl
}
test {MULTI propagation of SCRIPT LOAD} {
set repl [attach_to_replication_stream]
# make sure that EVAL inside MULTI is propagated in a transaction
r config set lua-replicate-commands no
r multi
r eval {redis.call('set', KEYS[1], 'bar')} 1 bar
r exec
assert_replication_stream $repl {
{select *}
{multi}
{eval *}
{exec}
}
close_replication_stream $repl
}
tags {"stream"} {
test {MULTI propagation of XREADGROUP} {
# stream is a special case because it calls propagate() directly for XREADGROUP
set repl [attach_to_replication_stream]
r XADD mystream * foo bar
r XGROUP CREATE mystream mygroup 0
# make sure the XCALIM (propagated by XREADGROUP) is indeed inside MULTI/EXEC
r multi
r XREADGROUP GROUP mygroup consumer1 STREAMS mystream ">"
r exec
assert_replication_stream $repl {
{select *}
{xadd *}
{xgroup CREATE *}
{multi}
{xclaim *}
{exec}
}
close_replication_stream $repl
}
}
} }
start_server {tags {"pause"}} {
test "Test read commands are not blocked by client pause" {
r client PAUSE 100000000 WRITE
set rd [redis_deferring_client]
$rd GET FOO
$rd PING
$rd INFO
assert_equal [s 0 blocked_clients] 0
r client unpause
$rd close
}
test "Test write commands are paused by RO" {
r client PAUSE 100000000 WRITE
set rd [redis_deferring_client]
$rd SET FOO BAR
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
r client unpause
assert_match "OK" [$rd read]
$rd close
}
test "Test special commands are paused by RO" {
r PFADD pause-hll test
r client PAUSE 100000000 WRITE
# Test that pfcount, which can replicate, is also blocked
set rd [redis_deferring_client]
$rd PFCOUNT pause-hll
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
# Test that publish, which adds the message to the replication
# stream is blocked.
set rd2 [redis_deferring_client]
$rd2 publish foo bar
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {2}
} else {
fail "Clients are not blocked"
}
# Test that SCRIPT LOAD, which is replicated.
set rd3 [redis_deferring_client]
$rd3 script load "return 1"
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {3}
} else {
fail "Clients are not blocked"
}
r client unpause
assert_match "1" [$rd read]
assert_match "0" [$rd2 read]
assert_match "*" [$rd3 read]
$rd close
$rd2 close
$rd3 close
}
test "Test read/admin mutli-execs are not blocked by pause RO" {
r SET FOO BAR
r client PAUSE 100000000 WRITE
set rd [redis_deferring_client]
$rd MULTI
assert_equal [$rd read] "OK"
$rd PING
assert_equal [$rd read] "QUEUED"
$rd GET FOO
assert_equal [$rd read] "QUEUED"
$rd EXEC
assert_equal [s 0 blocked_clients] 0
r client unpause
assert_match "PONG BAR" [$rd read]
$rd close
}
test "Test write mutli-execs are blocked by pause RO" {
set rd [redis_deferring_client]
$rd MULTI
assert_equal [$rd read] "OK"
$rd SET FOO BAR
r client PAUSE 100000000 WRITE
assert_equal [$rd read] "QUEUED"
$rd EXEC
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
r client unpause
assert_match "OK" [$rd read]
$rd close
}
test "Test scripts are blocked by pause RO" {
r client PAUSE 100000000 WRITE
set rd [redis_deferring_client]
$rd EVAL "return 1" 0
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
r client unpause
assert_match "1" [$rd read]
$rd close
}
test "Test multiple clients can be queued up and unblocked" {
r client PAUSE 100000000 WRITE
set clients [list [redis_deferring_client] [redis_deferring_client] [redis_deferring_client]]
foreach client $clients {
$client SET FOO BAR
}
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {3}
} else {
fail "Clients are not blocked"
}
r client unpause
foreach client $clients {
assert_match "OK" [$client read]
$client close
}
}
test "Test clients with syntax errors will get responses immediately" {
r client PAUSE 100000000 WRITE
catch {r set FOO} err
assert_match "ERR wrong number of arguments for *" $err
r client unpause
}
test "Test both active and passive expiries are skipped during client pause" {
set expired_keys [s 0 expired_keys]
r multi
r set foo bar PX 10
r set bar foo PX 10
r client PAUSE 100000000 WRITE
r exec
wait_for_condition 10 100 {
[r get foo] == {} && [r get bar] == {}
} else {
fail "Keys were never logically expired"
}
# No keys should actually have been expired
assert_match $expired_keys [s 0 expired_keys]
r client unpause
# Force the keys to expire
r get foo
r get bar
# Now that clients have been unpaused, expires should go through
assert_match [expr $expired_keys + 2] [s 0 expired_keys]
}
test "Test that client pause starts at the end of a transaction" {
r MULTI
r SET FOO1 BAR
r client PAUSE 100000000 WRITE
r SET FOO2 BAR
r exec
set rd [redis_deferring_client]
$rd SET FOO3 BAR
wait_for_condition 50 100 {
[s 0 blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
assert_match "BAR" [r GET FOO1]
assert_match "BAR" [r GET FOO2]
assert_match "" [r GET FOO3]
r client unpause
assert_match "OK" [$rd read]
$rd close
}
# Make sure we unpause at the end
r client unpause
}
...@@ -563,6 +563,30 @@ start_server {tags {"scripting"}} { ...@@ -563,6 +563,30 @@ start_server {tags {"scripting"}} {
} e } e
set e set e
} {*wrong number*} } {*wrong number*}
test {Script with RESP3 map} {
set expected_dict [dict create field value]
set expected_list [list field value]
# Sanity test for RESP3 without scripts
r HELLO 3
r hset hash field value
set res [r hgetall hash]
assert_equal $res $expected_dict
# Test RESP3 client with script in both RESP2 and RESP3 modes
set res [r eval {redis.setresp(3); return redis.call('hgetall', KEYS[1])} 1 hash]
assert_equal $res $expected_dict
set res [r eval {redis.setresp(2); return redis.call('hgetall', KEYS[1])} 1 hash]
assert_equal $res $expected_list
# Test RESP2 client with script in both RESP2 and RESP3 modes
r HELLO 2
set res [r eval {redis.setresp(3); return redis.call('hgetall', KEYS[1])} 1 hash]
assert_equal $res $expected_list
set res [r eval {redis.setresp(2); return redis.call('hgetall', KEYS[1])} 1 hash]
assert_equal $res $expected_list
}
} }
# Start a new server since the last test in this stanza will kill the # Start a new server since the last test in this stanza will kill the
......
...@@ -132,7 +132,24 @@ start_server {tags {"tracking"}} { ...@@ -132,7 +132,24 @@ start_server {tags {"tracking"}} {
test {HELLO 3 reply is correct} { test {HELLO 3 reply is correct} {
set reply [r HELLO 3] set reply [r HELLO 3]
assert {[lindex $reply 2] eq {proto 3}} assert_equal [dict get $reply proto] 3
}
test {HELLO without protover} {
set reply [r HELLO 3]
assert_equal [dict get $reply proto] 3
set reply [r HELLO]
assert_equal [dict get $reply proto] 3
set reply [r HELLO 2]
assert_equal [dict get $reply proto] 2
set reply [r HELLO]
assert_equal [dict get $reply proto] 2
# restore RESP3 for next test
r HELLO 3
} }
test {RESP3 based basic invalidation} { test {RESP3 based basic invalidation} {
...@@ -306,7 +323,25 @@ start_server {tags {"tracking"}} { ...@@ -306,7 +323,25 @@ start_server {tags {"tracking"}} {
set ping_reply [$rd read] set ping_reply [$rd read]
assert {$inv_msg eq {invalidate key1}} assert {$inv_msg eq {invalidate key1}}
assert {$ping_reply eq {PONG}} assert {$ping_reply eq {PONG}}
} }
test {BCAST with prefix collisions throw errors} {
set r [redis_client]
catch {$r CLIENT TRACKING ON BCAST PREFIX FOOBAR PREFIX FOO} output
assert_match {ERR Prefix 'FOOBAR'*'FOO'*} $output
catch {$r CLIENT TRACKING ON BCAST PREFIX FOO PREFIX FOOBAR} output
assert_match {ERR Prefix 'FOO'*'FOOBAR'*} $output
$r CLIENT TRACKING ON BCAST PREFIX FOO PREFIX BAR
catch {$r CLIENT TRACKING ON BCAST PREFIX FO} output
assert_match {ERR Prefix 'FO'*'FOO'*} $output
catch {$r CLIENT TRACKING ON BCAST PREFIX BARB} output
assert_match {ERR Prefix 'BARB'*'BAR'*} $output
$r CLIENT TRACKING OFF
}
test {Tracking gets notification on tracking table key eviction} { test {Tracking gets notification on tracking table key eviction} {
$rd_redirection HELLO 2 $rd_redirection HELLO 2
...@@ -398,6 +433,85 @@ start_server {tags {"tracking"}} { ...@@ -398,6 +433,85 @@ start_server {tags {"tracking"}} {
assert {$total_prefixes == 1} assert {$total_prefixes == 1}
} }
test {CLIENT TRACKINGINFO provides reasonable results when tracking off} {
r CLIENT TRACKING off
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {off} $flags
set redirect [dict get $res redirect]
assert_equal {-1} $redirect
set prefixes [dict get $res prefixes]
assert_equal {} $prefixes
}
test {CLIENT TRACKINGINFO provides reasonable results when tracking on} {
r CLIENT TRACKING on
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on} $flags
set redirect [dict get $res redirect]
assert_equal {0} $redirect
set prefixes [dict get $res prefixes]
assert_equal {} $prefixes
}
test {CLIENT TRACKINGINFO provides reasonable results when tracking on with options} {
r CLIENT TRACKING on REDIRECT $redir_id noloop
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on noloop} $flags
set redirect [dict get $res redirect]
assert_equal $redir_id $redirect
set prefixes [dict get $res prefixes]
assert_equal {} $prefixes
}
test {CLIENT TRACKINGINFO provides reasonable results when tracking optin} {
r CLIENT TRACKING off
r CLIENT TRACKING on optin
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on optin} $flags
set redirect [dict get $res redirect]
assert_equal {0} $redirect
set prefixes [dict get $res prefixes]
assert_equal {} $prefixes
r CLIENT CACHING yes
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on optin caching-yes} $flags
}
test {CLIENT TRACKINGINFO provides reasonable results when tracking optout} {
r CLIENT TRACKING off
r CLIENT TRACKING on optout
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on optout} $flags
set redirect [dict get $res redirect]
assert_equal {0} $redirect
set prefixes [dict get $res prefixes]
assert_equal {} $prefixes
r CLIENT CACHING no
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on optout caching-no} $flags
}
test {CLIENT TRACKINGINFO provides reasonable results when tracking bcast mode} {
r CLIENT TRACKING off
r CLIENT TRACKING on BCAST PREFIX foo PREFIX bar
set res [r client trackinginfo]
set flags [dict get $res flags]
assert_equal {on bcast} $flags
set redirect [dict get $res redirect]
assert_equal {0} $redirect
set prefixes [lsort [dict get $res prefixes]]
assert_equal {bar foo} $prefixes
}
$rd_redirection close $rd_redirection close
$rd close $rd close
} }
...@@ -123,6 +123,17 @@ start_server { ...@@ -123,6 +123,17 @@ start_server {
test {R/LPOP against empty list} { test {R/LPOP against empty list} {
r lpop non-existing-list r lpop non-existing-list
} {} } {}
test {R/LPOP with the optional count argument} {
assert_equal 7 [r lpush listcount aa bb cc dd ee ff gg]
assert_equal {} [r lpop listcount 0]
assert_equal {gg} [r lpop listcount 1]
assert_equal {ff ee} [r lpop listcount 2]
assert_equal {aa bb} [r rpop listcount 2]
assert_equal {cc} [r rpop listcount 1]
assert_equal {dd} [r rpop listcount 123]
assert_error "*ERR*range*" {r lpop forbarqaz -123}
}
test {Variadic RPUSH/LPUSH} { test {Variadic RPUSH/LPUSH} {
r del mylist r del mylist
...@@ -947,6 +958,12 @@ start_server { ...@@ -947,6 +958,12 @@ start_server {
assert_equal {} [r lrange nosuchkey 0 1] assert_equal {} [r lrange nosuchkey 0 1]
} }
test {LRANGE with start > end yields an empty array for backward compatibility} {
create_list mylist "1 2 3"
assert_equal {} [r lrange mylist 1 0]
assert_equal {} [r lrange mylist -1 -2]
}
foreach {type large} [array get largevalue] { foreach {type large} [array get largevalue] {
proc trim_list {type min max} { proc trim_list {type min max} {
upvar 1 large large upvar 1 large large
......
...@@ -27,7 +27,7 @@ start_server { ...@@ -27,7 +27,7 @@ start_server {
# and not the element "foo bar" which was pre existing in the # and not the element "foo bar" which was pre existing in the
# stream (see previous test) # stream (see previous test)
set reply [ set reply [
r XREADGROUP GROUP mygroup client-1 STREAMS mystream ">" r XREADGROUP GROUP mygroup consumer-1 STREAMS mystream ">"
] ]
assert {[llength [lindex $reply 0 1]] == 2} assert {[llength [lindex $reply 0 1]] == 2}
lindex $reply 0 1 0 1 lindex $reply 0 1 0 1
...@@ -39,13 +39,13 @@ start_server { ...@@ -39,13 +39,13 @@ start_server {
r XADD mystream * d 4 r XADD mystream * d 4
# Read a few elements using a different consumer name # Read a few elements using a different consumer name
set reply [ set reply [
r XREADGROUP GROUP mygroup client-2 STREAMS mystream ">" r XREADGROUP GROUP mygroup consumer-2 STREAMS mystream ">"
] ]
assert {[llength [lindex $reply 0 1]] == 2} assert {[llength [lindex $reply 0 1]] == 2}
assert {[lindex $reply 0 1 0 1] eq {c 3}} assert {[lindex $reply 0 1 0 1] eq {c 3}}
set r1 [r XREADGROUP GROUP mygroup client-1 COUNT 10 STREAMS mystream 0] set r1 [r XREADGROUP GROUP mygroup consumer-1 COUNT 10 STREAMS mystream 0]
set r2 [r XREADGROUP GROUP mygroup client-2 COUNT 10 STREAMS mystream 0] set r2 [r XREADGROUP GROUP mygroup consumer-2 COUNT 10 STREAMS mystream 0]
assert {[lindex $r1 0 1 0 1] eq {a 1}} assert {[lindex $r1 0 1 0 1] eq {a 1}}
assert {[lindex $r2 0 1 0 1] eq {c 3}} assert {[lindex $r2 0 1 0 1] eq {c 3}}
} }
...@@ -56,9 +56,9 @@ start_server { ...@@ -56,9 +56,9 @@ start_server {
for {set j 0} {$j < 4} {incr j} { for {set j 0} {$j < 4} {incr j} {
set item [lindex $pending $j] set item [lindex $pending $j]
if {$j < 2} { if {$j < 2} {
set owner client-1 set owner consumer-1
} else { } else {
set owner client-2 set owner consumer-2
} }
assert {[lindex $item 1] eq $owner} assert {[lindex $item 1] eq $owner}
assert {[lindex $item 1] eq $owner} assert {[lindex $item 1] eq $owner}
...@@ -66,7 +66,7 @@ start_server { ...@@ -66,7 +66,7 @@ start_server {
} }
test {XPENDING can return single consumer items} { test {XPENDING can return single consumer items} {
set pending [r XPENDING mystream mygroup - + 10 client-1] set pending [r XPENDING mystream mygroup - + 10 consumer-1]
assert {[llength $pending] == 2} assert {[llength $pending] == 2}
} }
...@@ -77,9 +77,9 @@ start_server { ...@@ -77,9 +77,9 @@ start_server {
test {XPENDING with IDLE} { test {XPENDING with IDLE} {
after 20 after 20
set pending [r XPENDING mystream mygroup IDLE 99999999 - + 10 client-1] set pending [r XPENDING mystream mygroup IDLE 99999999 - + 10 consumer-1]
assert {[llength $pending] == 0} assert {[llength $pending] == 0}
set pending [r XPENDING mystream mygroup IDLE 1 - + 10 client-1] set pending [r XPENDING mystream mygroup IDLE 1 - + 10 consumer-1]
assert {[llength $pending] == 2} assert {[llength $pending] == 2}
set pending [r XPENDING mystream mygroup IDLE 99999999 - + 10] set pending [r XPENDING mystream mygroup IDLE 99999999 - + 10]
assert {[llength $pending] == 0} assert {[llength $pending] == 0}
...@@ -101,12 +101,12 @@ start_server { ...@@ -101,12 +101,12 @@ start_server {
} }
} }
test {XACK is able to remove items from the client/group PEL} { test {XACK is able to remove items from the consumer/group PEL} {
set pending [r XPENDING mystream mygroup - + 10 client-1] set pending [r XPENDING mystream mygroup - + 10 consumer-1]
set id1 [lindex $pending 0 0] set id1 [lindex $pending 0 0]
set id2 [lindex $pending 1 0] set id2 [lindex $pending 1 0]
assert {[r XACK mystream mygroup $id1] eq 1} assert {[r XACK mystream mygroup $id1] eq 1}
set pending [r XPENDING mystream mygroup - + 10 client-1] set pending [r XPENDING mystream mygroup - + 10 consumer-1]
assert {[llength $pending] == 1} assert {[llength $pending] == 1}
set id [lindex $pending 0 0] set id [lindex $pending 0 0]
assert {$id eq $id2} assert {$id eq $id2}
...@@ -242,52 +242,52 @@ start_server { ...@@ -242,52 +242,52 @@ start_server {
set id3 [r XADD mystream * c 3] set id3 [r XADD mystream * c 3]
r XGROUP CREATE mystream mygroup 0 r XGROUP CREATE mystream mygroup 0
# Client 1 reads item 1 from the stream without acknowledgements. # Consumer 1 reads item 1 from the stream without acknowledgements.
# Client 2 then claims pending item 1 from the PEL of client 1 # Consumer 2 then claims pending item 1 from the PEL of consumer 1
set reply [ set reply [
r XREADGROUP GROUP mygroup client1 count 1 STREAMS mystream > r XREADGROUP GROUP mygroup consumer1 count 1 STREAMS mystream >
] ]
assert {[llength [lindex $reply 0 1 0 1]] == 2} assert {[llength [lindex $reply 0 1 0 1]] == 2}
assert {[lindex $reply 0 1 0 1] eq {a 1}} assert {[lindex $reply 0 1 0 1] eq {a 1}}
# make sure the entry is present in both the gorup, and the right consumer # make sure the entry is present in both the gorup, and the right consumer
assert {[llength [r XPENDING mystream mygroup - + 10]] == 1} assert {[llength [r XPENDING mystream mygroup - + 10]] == 1}
assert {[llength [r XPENDING mystream mygroup - + 10 client1]] == 1} assert {[llength [r XPENDING mystream mygroup - + 10 consumer1]] == 1}
assert {[llength [r XPENDING mystream mygroup - + 10 client2]] == 0} assert {[llength [r XPENDING mystream mygroup - + 10 consumer2]] == 0}
r debug sleep 0.2 after 200
set reply [ set reply [
r XCLAIM mystream mygroup client2 10 $id1 r XCLAIM mystream mygroup consumer2 10 $id1
] ]
assert {[llength [lindex $reply 0 1]] == 2} assert {[llength [lindex $reply 0 1]] == 2}
assert {[lindex $reply 0 1] eq {a 1}} assert {[lindex $reply 0 1] eq {a 1}}
# make sure the entry is present in both the gorup, and the right consumer # make sure the entry is present in both the gorup, and the right consumer
assert {[llength [r XPENDING mystream mygroup - + 10]] == 1} assert {[llength [r XPENDING mystream mygroup - + 10]] == 1}
assert {[llength [r XPENDING mystream mygroup - + 10 client1]] == 0} assert {[llength [r XPENDING mystream mygroup - + 10 consumer1]] == 0}
assert {[llength [r XPENDING mystream mygroup - + 10 client2]] == 1} assert {[llength [r XPENDING mystream mygroup - + 10 consumer2]] == 1}
# Client 1 reads another 2 items from stream # Consumer 1 reads another 2 items from stream
r XREADGROUP GROUP mygroup client1 count 2 STREAMS mystream > r XREADGROUP GROUP mygroup consumer1 count 2 STREAMS mystream >
r debug sleep 0.2 after 200
# Delete item 2 from the stream. Now client 1 has PEL that contains # Delete item 2 from the stream. Now consumer 1 has PEL that contains
# only item 3. Try to use client 2 to claim the deleted item 2 # only item 3. Try to use consumer 2 to claim the deleted item 2
# from the PEL of client 1, this should return nil # from the PEL of consumer 1, this should return nil
r XDEL mystream $id2 r XDEL mystream $id2
set reply [ set reply [
r XCLAIM mystream mygroup client2 10 $id2 r XCLAIM mystream mygroup consumer2 10 $id2
] ]
assert {[llength $reply] == 1} assert {[llength $reply] == 1}
assert_equal "" [lindex $reply 0] assert_equal "" [lindex $reply 0]
# Delete item 3 from the stream. Now client 1 has PEL that is empty. # Delete item 3 from the stream. Now consumer 1 has PEL that is empty.
# Try to use client 2 to claim the deleted item 3 from the PEL # Try to use consumer 2 to claim the deleted item 3 from the PEL
# of client 1, this should return nil # of consumer 1, this should return nil
r debug sleep 0.2 after 200
r XDEL mystream $id3 r XDEL mystream $id3
set reply [ set reply [
r XCLAIM mystream mygroup client2 10 $id3 r XCLAIM mystream mygroup consumer2 10 $id3
] ]
assert {[llength $reply] == 1} assert {[llength $reply] == 1}
assert_equal "" [lindex $reply 0] assert_equal "" [lindex $reply 0]
...@@ -301,16 +301,16 @@ start_server { ...@@ -301,16 +301,16 @@ start_server {
set id3 [r XADD mystream * c 3] set id3 [r XADD mystream * c 3]
r XGROUP CREATE mystream mygroup 0 r XGROUP CREATE mystream mygroup 0
# Client 1 reads item 1 from the stream without acknowledgements. # Consumer 1 reads item 1 from the stream without acknowledgements.
# Client 2 then claims pending item 1 from the PEL of client 1 # Consumer 2 then claims pending item 1 from the PEL of consumer 1
set reply [ set reply [
r XREADGROUP GROUP mygroup client1 count 1 STREAMS mystream > r XREADGROUP GROUP mygroup consumer1 count 1 STREAMS mystream >
] ]
assert {[llength [lindex $reply 0 1 0 1]] == 2} assert {[llength [lindex $reply 0 1 0 1]] == 2}
assert {[lindex $reply 0 1 0 1] eq {a 1}} assert {[lindex $reply 0 1 0 1] eq {a 1}}
r debug sleep 0.2 after 200
set reply [ set reply [
r XCLAIM mystream mygroup client2 10 $id1 r XCLAIM mystream mygroup consumer2 10 $id1
] ]
assert {[llength [lindex $reply 0 1]] == 2} assert {[llength [lindex $reply 0 1]] == 2}
assert {[lindex $reply 0 1] eq {a 1}} assert {[lindex $reply 0 1] eq {a 1}}
...@@ -321,10 +321,10 @@ start_server { ...@@ -321,10 +321,10 @@ start_server {
assert {[llength [lindex $reply 0]] == 4} assert {[llength [lindex $reply 0]] == 4}
assert {[lindex $reply 0 3] == 2} assert {[lindex $reply 0 3] == 2}
# Client 3 then claims pending item 1 from the PEL of client 2 using JUSTID # Consumer 3 then claims pending item 1 from the PEL of consumer 2 using JUSTID
r debug sleep 0.2 after 200
set reply [ set reply [
r XCLAIM mystream mygroup client3 10 $id1 JUSTID r XCLAIM mystream mygroup consumer3 10 $id1 JUSTID
] ]
assert {[llength $reply] == 1} assert {[llength $reply] == 1}
assert {[lindex $reply 0] eq $id1} assert {[lindex $reply 0] eq $id1}
...@@ -344,17 +344,122 @@ start_server { ...@@ -344,17 +344,122 @@ start_server {
set id3 [r XADD mystream * c 3] set id3 [r XADD mystream * c 3]
r XGROUP CREATE mystream mygroup 0 r XGROUP CREATE mystream mygroup 0
set reply [r XREADGROUP GROUP mygroup client1 count 1 STREAMS mystream >] set reply [r XREADGROUP GROUP mygroup consumer1 count 1 STREAMS mystream >]
assert {[llength [lindex $reply 0 1 0 1]] == 2} assert {[llength [lindex $reply 0 1 0 1]] == 2}
assert {[lindex $reply 0 1 0 1] eq {a 1}} assert {[lindex $reply 0 1 0 1] eq {a 1}}
r debug sleep 0.2 after 200
# re-claim with the same consumer that already has it # re-claim with the same consumer that already has it
assert {[llength [r XCLAIM mystream mygroup client1 10 $id1]] == 1} assert {[llength [r XCLAIM mystream mygroup consumer1 10 $id1]] == 1}
# make sure the entry is still in the PEL # make sure the entry is still in the PEL
set reply [r XPENDING mystream mygroup - + 10] set reply [r XPENDING mystream mygroup - + 10]
assert {[llength $reply] == 1} assert {[llength $reply] == 1}
assert {[lindex $reply 0 1] eq {client1}} assert {[lindex $reply 0 1] eq {consumer1}}
}
test {XAUTOCLAIM can claim PEL items from another consumer} {
# Add 3 items into the stream, and create a consumer group
r del mystream
set id1 [r XADD mystream * a 1]
set id2 [r XADD mystream * b 2]
set id3 [r XADD mystream * c 3]
r XGROUP CREATE mystream mygroup 0
# Consumer 1 reads item 1 from the stream without acknowledgements.
# Consumer 2 then claims pending item 1 from the PEL of consumer 1
set reply [r XREADGROUP GROUP mygroup consumer1 count 1 STREAMS mystream >]
assert_equal [llength [lindex $reply 0 1 0 1]] 2
assert_equal [lindex $reply 0 1 0 1] {a 1}
after 200
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 1]
assert_equal [llength $reply] 2
assert_equal [lindex $reply 0] $id1
assert_equal [llength [lindex $reply 1]] 1
assert_equal [llength [lindex $reply 1 0]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {a 1}
# Consumer 1 reads another 2 items from stream
r XREADGROUP GROUP mygroup consumer1 count 2 STREAMS mystream >
# For min-idle-time
after 200
# Delete item 2 from the stream. Now consumer 1 has PEL that contains
# only item 3. Try to use consumer 2 to claim the deleted item 2
# from the PEL of consumer 1, this should return nil
r XDEL mystream $id2
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2]
# id1 is self-claimed here but not id2 ('count' was set to 2)
assert_equal [llength $reply] 2
assert_equal [lindex $reply 0] $id2
assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {a 1}
assert_equal [lindex $reply 1 1] ""
# Delete item 3 from the stream. Now consumer 1 has PEL that is empty.
# Try to use consumer 2 to claim the deleted item 3 from the PEL
# of consumer 1, this should return nil
after 200
r XDEL mystream $id3
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - JUSTID]
# id1 is self-claimed here but not id2 and id3 ('count' is default 100)
# we also test the JUSTID modifier here. note that, when using JUSTID,
# deleted entries are returned in reply (consistent with XCLAIM).
assert_equal [llength $reply] 2
assert_equal [lindex $reply 0] "0-0"
assert_equal [llength [lindex $reply 1]] 3
assert_equal [lindex $reply 1 0] $id1
assert_equal [lindex $reply 1 1] $id2
assert_equal [lindex $reply 1 2] $id3
}
test {XAUTOCLAIM as an iterator} {
# Add 5 items into the stream, and create a consumer group
r del mystream
set id1 [r XADD mystream * a 1]
set id2 [r XADD mystream * b 2]
set id3 [r XADD mystream * c 3]
set id4 [r XADD mystream * d 4]
set id5 [r XADD mystream * e 5]
r XGROUP CREATE mystream mygroup 0
# Read 5 messages into consumer1
r XREADGROUP GROUP mygroup consumer1 count 90 STREAMS mystream >
# For min-idle-time
after 200
# Claim 2 entries
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2]
assert_equal [llength $reply] 2
set cursor [lindex $reply 0]
assert_equal $cursor $id2
assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {a 1}
# Claim 2 more entries
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 ($cursor COUNT 2]
assert_equal [llength $reply] 2
set cursor [lindex $reply 0]
assert_equal $cursor $id4
assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {c 3}
# Claim last entry
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 ($cursor COUNT 2]
assert_equal [llength $reply] 2
set cursor [lindex $reply 0]
assert_equal $cursor {0-0}
assert_equal [llength [lindex $reply 1]] 1
assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {e 5}
} }
test {XINFO FULL output} { test {XINFO FULL output} {
...@@ -477,7 +582,7 @@ start_server { ...@@ -477,7 +582,7 @@ start_server {
assert {$curr_grpinfo == $grpinfo} assert {$curr_grpinfo == $grpinfo}
set n_consumers [lindex $grpinfo 3] set n_consumers [lindex $grpinfo 3]
# Bob should be created only when there will be new data for this client # Bob should be created only when there will be new data for this consumer
assert_equal $n_consumers 2 assert_equal $n_consumers 2
set reply [r xinfo consumers mystream mygroup] set reply [r xinfo consumers mystream mygroup]
set consumer_info [lindex $reply 0] set consumer_info [lindex $reply 0]
......
...@@ -94,6 +94,7 @@ start_server { ...@@ -94,6 +94,7 @@ start_server {
r XADD mystream MAXLEN 5 * yitem $j r XADD mystream MAXLEN 5 * yitem $j
} }
} }
assert {[r xlen mystream] == 5}
set res [r xrange mystream - +] set res [r xrange mystream - +]
set expected 995 set expected 995
foreach r $res { foreach r $res {
...@@ -138,6 +139,39 @@ start_server { ...@@ -138,6 +139,39 @@ start_server {
assert_equal [lindex $items 1 1] {item 2 value b} assert_equal [lindex $items 1 1] {item 2 value b}
} }
test {XADD with MINID option} {
r DEL mystream
for {set j 1} {$j < 1001} {incr j} {
set minid 1000
if {$j >= 5} {
set minid [expr {$j-5}]
}
if {rand() < 0.9} {
r XADD mystream MINID $minid $j xitem $j
} else {
r XADD mystream MINID $minid $j yitem $j
}
}
assert {[r xlen mystream] == 6}
set res [r xrange mystream - +]
set expected 995
foreach r $res {
assert {[lindex $r 1 1] == $expected}
incr expected
}
}
test {XTRIM with MINID option} {
r DEL mystream
r XADD mystream 1-0 f v
r XADD mystream 2-0 f v
r XADD mystream 3-0 f v
r XADD mystream 4-0 f v
r XADD mystream 5-0 f v
r XTRIM mystream MINID = 3-0
assert_equal [r XRANGE mystream - +] {{3-0 {f v}} {4-0 {f v}} {5-0 {f v}}}
}
test {XADD mass insertion and XLEN} { test {XADD mass insertion and XLEN} {
r DEL mystream r DEL mystream
r multi r multi
...@@ -448,7 +482,49 @@ start_server { ...@@ -448,7 +482,49 @@ start_server {
assert {[r XLEN mystream] == 400} assert {[r XLEN mystream] == 400}
} }
test {XADD with LIMIT consecutive calls} {
r del mystream
r config set stream-node-max-entries 10
for {set j 0} {$j < 100} {incr j} {
r XADD mystream * xitem v
}
r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
assert {[r xlen mystream] == 71}
r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
assert {[r xlen mystream] == 62}
r config set stream-node-max-entries 100
}
test {XTRIM with ~ is limited} {
r del mystream
r config set stream-node-max-entries 1
for {set j 0} {$j < 102} {incr j} {
r XADD mystream * xitem v
}
r XTRIM mystream MAXLEN ~ 1
assert {[r xlen mystream] == 2}
r config set stream-node-max-entries 100
}
test {XTRIM without ~ is not limited} {
r del mystream
r config set stream-node-max-entries 1
for {set j 0} {$j < 102} {incr j} {
r XADD mystream * xitem v
}
r XTRIM mystream MAXLEN 1
assert {[r xlen mystream] == 1}
r config set stream-node-max-entries 100
}
test {XTRIM without ~ and with LIMIT} {
r del mystream
r config set stream-node-max-entries 1
for {set j 0} {$j < 102} {incr j} {
r XADD mystream * xitem v
}
assert_error ERR* {r XTRIM mystream MAXLEN 1 LIMIT 30}
}
} }
start_server {tags {"stream"} overrides {appendonly yes}} { start_server {tags {"stream"} overrides {appendonly yes}} {
...@@ -466,6 +542,22 @@ start_server {tags {"stream"} overrides {appendonly yes}} { ...@@ -466,6 +542,22 @@ start_server {tags {"stream"} overrides {appendonly yes}} {
} }
} }
start_server {tags {"stream"} overrides {appendonly yes}} {
test {XADD with MINID > lastid can propagate correctly} {
for {set j 0} {$j < 100} {incr j} {
set id [expr {$j+1}]
r XADD mystream $id xitem v
}
r XADD mystream MINID 1 * xitem v
incr j
assert {[r xlen mystream] == $j}
r debug loadaof
r XADD mystream * xitem v
incr j
assert {[r xlen mystream] == $j}
}
}
start_server {tags {"stream"} overrides {appendonly yes}} { start_server {tags {"stream"} overrides {appendonly yes}} {
test {XADD with ~ MAXLEN can propagate correctly} { test {XADD with ~ MAXLEN can propagate correctly} {
for {set j 0} {$j < 100} {incr j} { for {set j 0} {$j < 100} {incr j} {
...@@ -482,6 +574,52 @@ start_server {tags {"stream"} overrides {appendonly yes}} { ...@@ -482,6 +574,52 @@ start_server {tags {"stream"} overrides {appendonly yes}} {
} }
} }
start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
test {XADD with ~ MAXLEN and LIMIT can propagate correctly} {
for {set j 0} {$j < 100} {incr j} {
r XADD mystream * xitem v
}
r XADD mystream MAXLEN ~ 55 LIMIT 30 * xitem v
assert {[r xlen mystream] == 71}
r config set stream-node-max-entries 1
r debug loadaof
r XADD mystream * xitem v
assert {[r xlen mystream] == 72}
}
}
start_server {tags {"stream"} overrides {appendonly yes}} {
test {XADD with ~ MINID can propagate correctly} {
for {set j 0} {$j < 100} {incr j} {
set id [expr {$j+1}]
r XADD mystream $id xitem v
}
r XADD mystream MINID ~ $j * xitem v
incr j
assert {[r xlen mystream] == $j}
r config set stream-node-max-entries 1
r debug loadaof
r XADD mystream * xitem v
incr j
assert {[r xlen mystream] == $j}
}
}
start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
test {XADD with ~ MINID and LIMIT can propagate correctly} {
for {set j 0} {$j < 100} {incr j} {
set id [expr {$j+1}]
r XADD mystream $id xitem v
}
r XADD mystream MINID ~ 55 LIMIT 30 * xitem v
assert {[r xlen mystream] == 71}
r config set stream-node-max-entries 1
r debug loadaof
r XADD mystream * xitem v
assert {[r xlen mystream] == 72}
}
}
start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} { start_server {tags {"stream"} overrides {appendonly yes stream-node-max-entries 10}} {
test {XTRIM with ~ MAXLEN can propagate correctly} { test {XTRIM with ~ MAXLEN can propagate correctly} {
for {set j 0} {$j < 100} {incr j} { for {set j 0} {$j < 100} {incr j} {
......
...@@ -1472,4 +1472,86 @@ start_server {tags {"zset"}} { ...@@ -1472,4 +1472,86 @@ start_server {tags {"zset"}} {
} }
r config set zset-max-ziplist-entries $original_max r config set zset-max-ziplist-entries $original_max
} }
test {ZRANGESTORE basic} {
r flushall
r zadd z1 1 a 2 b 3 c 4 d
set res [r zrangestore z2 z1 0 -1]
assert_equal $res 4
r zrange z2 0 -1 withscores
} {a 1 b 2 c 3 d 4}
test {ZRANGESTORE range} {
set res [r zrangestore z2 z1 1 2]
assert_equal $res 2
r zrange z2 0 -1 withscores
} {b 2 c 3}
test {ZRANGESTORE BYLEX} {
set res [r zrangestore z2 z1 \[b \[c BYLEX]
assert_equal $res 2
r zrange z2 0 -1 withscores
} {b 2 c 3}
test {ZRANGESTORE BYSCORE} {
set res [r zrangestore z2 z1 1 2 BYSCORE]
assert_equal $res 2
r zrange z2 0 -1 withscores
} {a 1 b 2}
test {ZRANGESTORE BYSCORE LIMIT} {
set res [r zrangestore z2 z1 0 5 BYSCORE LIMIT 0 2]
assert_equal $res 2
r zrange z2 0 -1 withscores
} {a 1 b 2}
test {ZRANGESTORE BYSCORE REV LIMIT} {
set res [r zrangestore z2 z1 5 0 BYSCORE REV LIMIT 0 2]
assert_equal $res 2
r zrange z2 0 -1 withscores
} {c 3 d 4}
test {ZRANGE BYSCORE REV LIMIT} {
r zrange z1 5 0 BYSCORE REV LIMIT 0 2 WITHSCORES
} {d 4 c 3}
test {ZRANGESTORE - empty range} {
set res [r zrangestore z2 z1 5 6]
assert_equal $res 0
r exists z2
} {0}
test {ZRANGESTORE BYLEX - empty range} {
set res [r zrangestore z2 z1 \[f \[g BYLEX]
assert_equal $res 0
r exists z2
} {0}
test {ZRANGESTORE BYSCORE - empty range} {
set res [r zrangestore z2 z1 5 6 BYSCORE]
assert_equal $res 0
r exists z2
} {0}
test {ZRANGE BYLEX} {
r zrange z1 \[b \[c BYLEX
} {b c}
test {ZRANGESTORE invalid syntax} {
catch {r zrangestore z2 z1 0 -1 limit 1 2} err
assert_match "*syntax*" $err
catch {r zrangestore z2 z1 0 -1 WITHSCORES} err
assert_match "*syntax*" $err
}
test {ZRANGE invalid syntax} {
catch {r zrange z1 0 -1 limit 1 2} err
assert_match "*syntax*" $err
catch {r zrange z1 0 -1 BYLEX WITHSCORES} err
assert_match "*syntax*" $err
catch {r zrevrange z1 0 -1 BYSCORE} err
assert_match "*syntax*" $err
catch {r zrangebyscore z1 0 -1 REV} err
assert_match "*syntax*" $err
}
} }
...@@ -5,6 +5,7 @@ start_server {} { ...@@ -5,6 +5,7 @@ start_server {} {
set slave [srv 0 client] set slave [srv 0 client]
set slave_host [srv 0 host] set slave_host [srv 0 host]
set slave_port [srv 0 port] set slave_port [srv 0 port]
set slave_pid [srv 0 pid]
set master [srv -1 client] set master [srv -1 client]
set master_host [srv -1 host] set master_host [srv -1 host]
set master_port [srv -1 port] set master_port [srv -1 port]
...@@ -33,13 +34,25 @@ start_server {} { ...@@ -33,13 +34,25 @@ start_server {} {
} }
test {WAIT should not acknowledge 1 additional copy if slave is blocked} { test {WAIT should not acknowledge 1 additional copy if slave is blocked} {
set cmd [rediscli $slave_host $slave_port "debug sleep 5"] exec kill -SIGSTOP $slave_pid
exec {*}$cmd > /dev/null 2> /dev/null &
after 1000 ;# Give redis-cli the time to execute the command.
$master set foo 0 $master set foo 0
$master incr foo $master incr foo
$master incr foo $master incr foo
$master incr foo $master incr foo
assert {[$master wait 1 3000] == 0} assert {[$master wait 1 1000] == 0}
exec kill -SIGCONT $slave_pid
assert {[$master wait 1 1000] == 1}
}
test {WAIT implicitly blocks on client pause since ACKs aren't sent} {
exec kill -SIGSTOP $slave_pid
$master multi
$master incr foo
$master client pause 10000 write
$master exec
assert {[$master wait 1 1000] == 0}
$master client unpause
exec kill -SIGCONT $slave_pid
assert {[$master wait 1 1000] == 1}
} }
}} }}
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