summaryrefslogtreecommitdiffstats
path: root/tests/unit/pause.tcl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:40:54 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:40:54 +0000
commit317c0644ccf108aa23ef3fd8358bd66c2840bfc0 (patch)
treec417b3d25c86b775989cb5ac042f37611b626c8a /tests/unit/pause.tcl
parentInitial commit. (diff)
downloadredis-317c0644ccf108aa23ef3fd8358bd66c2840bfc0.tar.xz
redis-317c0644ccf108aa23ef3fd8358bd66c2840bfc0.zip
Adding upstream version 5:7.2.4.upstream/5%7.2.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/unit/pause.tcl')
-rw-r--r--tests/unit/pause.tcl364
1 files changed, 364 insertions, 0 deletions
diff --git a/tests/unit/pause.tcl b/tests/unit/pause.tcl
new file mode 100644
index 0000000..e30f922
--- /dev/null
+++ b/tests/unit/pause.tcl
@@ -0,0 +1,364 @@
+start_server {tags {"pause network"}} {
+ test "Test read commands are not blocked by client pause" {
+ r client PAUSE 100000 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 old pause-all takes precedence over new pause-write (less restrictive)" {
+ # Scenario:
+ # 1. Run 'PAUSE ALL' for 200msec
+ # 2. Run 'PAUSE WRITE' for 10 msec
+ # 3. Wait 50msec
+ # 4. 'GET FOO'.
+ # Expected that:
+ # - While the time of the second 'PAUSE' is shorter than first 'PAUSE',
+ # pause-client feature will stick to the longer one, i.e, will be paused
+ # up to 200msec.
+ # - The GET command will be postponed ~200msec, even though last command
+ # paused only WRITE. This is because the first 'PAUSE ALL' command is
+ # more restrictive than the second 'PAUSE WRITE' and pause-client feature
+ # preserve most restrictive configuration among multiple settings.
+ set rd [redis_deferring_client]
+ $rd SET FOO BAR
+
+ set test_start_time [clock milliseconds]
+ r client PAUSE 200 ALL
+ r client PAUSE 20 WRITE
+ after 50
+ $rd get FOO
+ set elapsed [expr {[clock milliseconds]-$test_start_time}]
+ assert_lessthan 200 $elapsed
+ }
+
+ test "Test new pause time is smaller than old one, then old time preserved" {
+ r client PAUSE 60000 WRITE
+ r client PAUSE 10 WRITE
+ after 100
+ set rd [redis_deferring_client]
+ $rd SET FOO BAR
+ wait_for_blocked_clients_count 1 100 10
+
+ r client unpause
+ assert_match "OK" [$rd read]
+ $rd close
+ }
+
+ test "Test write commands are paused by RO" {
+ r client PAUSE 60000 WRITE
+
+ set rd [redis_deferring_client]
+ $rd SET FOO BAR
+ wait_for_blocked_clients_count 1 50 100
+
+ 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 100000 WRITE
+
+ # Test that pfcount, which can replicate, is also blocked
+ set rd [redis_deferring_client]
+ $rd PFCOUNT pause-hll
+ wait_for_blocked_clients_count 1 50 100
+
+ # Test that publish, which adds the message to the replication
+ # stream is blocked.
+ set rd2 [redis_deferring_client]
+ $rd2 publish foo bar
+ wait_for_blocked_clients_count 2 50 100
+
+ r client unpause
+ assert_match "1" [$rd read]
+ assert_match "0" [$rd2 read]
+ $rd close
+ $rd2 close
+ }
+
+ test "Test read/admin multi-execs are not blocked by pause RO" {
+ r SET FOO BAR
+ r client PAUSE 100000 WRITE
+ set rr [redis_client]
+ assert_equal [$rr MULTI] "OK"
+ assert_equal [$rr PING] "QUEUED"
+ assert_equal [$rr GET FOO] "QUEUED"
+ assert_match "PONG BAR" [$rr EXEC]
+ assert_equal [s 0 blocked_clients] 0
+ r client unpause
+ $rr close
+ }
+
+ test "Test write multi-execs are blocked by pause RO" {
+ set rd [redis_deferring_client]
+ $rd MULTI
+ assert_equal [$rd read] "OK"
+ $rd SET FOO BAR
+ assert_equal [$rd read] "QUEUED"
+ r client PAUSE 60000 WRITE
+ $rd EXEC
+ wait_for_blocked_clients_count 1 50 100
+ r client unpause
+ assert_match "OK" [$rd read]
+ $rd close
+ }
+
+ test "Test scripts are blocked by pause RO" {
+ r client PAUSE 60000 WRITE
+ set rd [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+ $rd EVAL "return 1" 0
+
+ # test a script with a shebang and no flags for coverage
+ $rd2 EVAL {#!lua
+ return 1
+ } 0
+
+ wait_for_blocked_clients_count 2 50 100
+ r client unpause
+ assert_match "1" [$rd read]
+ assert_match "1" [$rd2 read]
+ $rd close
+ $rd2 close
+ }
+
+ test "Test RO scripts are not blocked by pause RO" {
+ r set x y
+ # create a function for later
+ r FUNCTION load replace {#!lua name=f1
+ redis.register_function{
+ function_name='f1',
+ callback=function() return "hello" end,
+ flags={'no-writes'}
+ }
+ }
+
+ r client PAUSE 6000000 WRITE
+ set rr [redis_client]
+
+ # test an eval that's for sure not in the script cache
+ assert_equal [$rr EVAL {#!lua flags=no-writes
+ return 'unique script'
+ } 0
+ ] "unique script"
+
+ # for sanity, repeat that EVAL on a script that's already cached
+ assert_equal [$rr EVAL {#!lua flags=no-writes
+ return 'unique script'
+ } 0
+ ] "unique script"
+
+ # test EVAL_RO on a unique script that's for sure not in the cache
+ assert_equal [$rr EVAL_RO {
+ return redis.call('GeT', 'x')..' unique script'
+ } 1 x
+ ] "y unique script"
+
+ # test with evalsha
+ set sha [$rr script load {#!lua flags=no-writes
+ return 2
+ }]
+ assert_equal [$rr EVALSHA $sha 0] 2
+
+ # test with function
+ assert_equal [$rr fcall f1 0] hello
+
+ r client unpause
+ $rr close
+ }
+
+ test "Test read-only scripts in multi-exec are not blocked by pause RO" {
+ r SET FOO BAR
+ r client PAUSE 100000 WRITE
+ set rr [redis_client]
+ assert_equal [$rr MULTI] "OK"
+ assert_equal [$rr EVAL {#!lua flags=no-writes
+ return 12
+ } 0
+ ] QUEUED
+ assert_equal [$rr EVAL {#!lua flags=no-writes
+ return 13
+ } 0
+ ] QUEUED
+ assert_match "12 13" [$rr EXEC]
+ assert_equal [s 0 blocked_clients] 0
+ r client unpause
+ $rr close
+ }
+
+ test "Test write scripts in multi-exec are blocked by pause RO" {
+ set rd [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+
+ # one with a shebang
+ $rd MULTI
+ assert_equal [$rd read] "OK"
+ $rd EVAL {#!lua
+ return 12
+ } 0
+ assert_equal [$rd read] "QUEUED"
+
+ # one without a shebang
+ $rd2 MULTI
+ assert_equal [$rd2 read] "OK"
+ $rd2 EVAL {#!lua
+ return 13
+ } 0
+ assert_equal [$rd2 read] "QUEUED"
+
+ r client PAUSE 60000 WRITE
+ $rd EXEC
+ $rd2 EXEC
+ wait_for_blocked_clients_count 2 50 100
+ r client unpause
+ assert_match "12" [$rd read]
+ assert_match "13" [$rd2 read]
+ $rd close
+ $rd2 close
+ }
+
+ test "Test may-replicate commands are rejected in RO scripts" {
+ # that's specifically important for CLIENT PAUSE WRITE
+ assert_error {ERR Write commands are not allowed from read-only scripts. script:*} {
+ r EVAL_RO "return redis.call('publish','ch','msg')" 0
+ }
+ assert_error {ERR Write commands are not allowed from read-only scripts. script:*} {
+ r EVAL {#!lua flags=no-writes
+ return redis.call('publish','ch','msg')
+ } 0
+ }
+ # make sure that publish isn't blocked from a non-RO script
+ assert_equal [r EVAL "return redis.call('publish','ch','msg')" 0] 0
+ }
+
+ test "Test multiple clients can be queued up and unblocked" {
+ r client PAUSE 60000 WRITE
+ set clients [list [redis_deferring_client] [redis_deferring_client] [redis_deferring_client]]
+ foreach client $clients {
+ $client SET FOO BAR
+ }
+
+ wait_for_blocked_clients_count 3 50 100
+ 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 100000 WRITE
+ catch {r set FOO} err
+ assert_match "ERR wrong number of arguments for 'set' command" $err
+ r client unpause
+ }
+
+ test "Test both active and passive expires are skipped during client pause" {
+ set expired_keys [s 0 expired_keys]
+ r multi
+ r set foo{t} bar{t} PX 10
+ r set bar{t} foo{t} PX 10
+ r client PAUSE 50000 WRITE
+ r exec
+
+ wait_for_condition 10 100 {
+ [r get foo{t}] == {} && [r get bar{t}] == {}
+ } 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{t}
+ r get bar{t}
+
+ # 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{t} BAR
+ r client PAUSE 60000 WRITE
+ r SET FOO2{t} BAR
+ r exec
+
+ set rd [redis_deferring_client]
+ $rd SET FOO3{t} BAR
+
+ wait_for_blocked_clients_count 1 50 100
+
+ assert_match "BAR" [r GET FOO1{t}]
+ assert_match "BAR" [r GET FOO2{t}]
+ assert_match "" [r GET FOO3{t}]
+
+ r client unpause
+ assert_match "OK" [$rd read]
+ $rd close
+ }
+
+ start_server {tags {needs:repl external:skip}} {
+ set master [srv -1 client]
+ set master_host [srv -1 host]
+ set master_port [srv -1 port]
+
+ # Avoid PINGs
+ $master config set repl-ping-replica-period 3600
+ r replicaof $master_host $master_port
+
+ wait_for_condition 50 100 {
+ [s master_link_status] eq {up}
+ } else {
+ fail "Replication not started."
+ }
+
+ test "Test when replica paused, offset would not grow" {
+ $master set foo bar
+ set old_master_offset [status $master master_repl_offset]
+
+ wait_for_condition 50 100 {
+ [s slave_repl_offset] == [status $master master_repl_offset]
+ } else {
+ fail "Replication offset not matched."
+ }
+
+ r client pause 100000 write
+ $master set foo2 bar2
+
+ # Make sure replica received data from master
+ wait_for_condition 50 100 {
+ [s slave_read_repl_offset] == [status $master master_repl_offset]
+ } else {
+ fail "Replication not work."
+ }
+
+ # Replica would not apply the write command
+ assert {[s slave_repl_offset] == $old_master_offset}
+ r get foo2
+ } {}
+
+ test "Test replica offset would grow after unpause" {
+ r client unpause
+ wait_for_condition 50 100 {
+ [s slave_repl_offset] == [status $master master_repl_offset]
+ } else {
+ fail "Replication not continue."
+ }
+ r get foo2
+ } {bar2}
+ }
+
+ # Make sure we unpause at the end
+ r client unpause
+}