From 317c0644ccf108aa23ef3fd8358bd66c2840bfc0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 14 Apr 2024 15:40:54 +0200 Subject: Adding upstream version 5:7.2.4. Signed-off-by: Daniel Baumann --- tests/unit/wait.tcl | 505 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 505 insertions(+) create mode 100644 tests/unit/wait.tcl (limited to 'tests/unit/wait.tcl') diff --git a/tests/unit/wait.tcl b/tests/unit/wait.tcl new file mode 100644 index 0000000..bd0bced --- /dev/null +++ b/tests/unit/wait.tcl @@ -0,0 +1,505 @@ +source tests/support/cli.tcl + +start_server {tags {"wait network external:skip"}} { +start_server {} { + set slave [srv 0 client] + set slave_host [srv 0 host] + set slave_port [srv 0 port] + set slave_pid [srv 0 pid] + set master [srv -1 client] + set master_host [srv -1 host] + set master_port [srv -1 port] + + test {Setup slave} { + $slave slaveof $master_host $master_port + wait_for_condition 50 100 { + [s 0 master_link_status] eq {up} + } else { + fail "Replication not started." + } + } + + test {WAIT out of range timeout (milliseconds)} { + # Timeout is parsed as milliseconds by getLongLongFromObjectOrReply(). + # Verify we get out of range message if value is behind LLONG_MAX + # (decimal value equals to 0x8000000000000000) + assert_error "*or out of range*" {$master wait 2 9223372036854775808} + + # expected to fail by later overflow condition after addition + # of mstime(). (decimal value equals to 0x7FFFFFFFFFFFFFFF) + assert_error "*timeout is out of range*" {$master wait 2 9223372036854775807} + + assert_error "*timeout is negative*" {$master wait 2 -1} + } + + test {WAIT should acknowledge 1 additional copy of the data} { + $master set foo 0 + $master incr foo + $master incr foo + $master incr foo + assert {[$master wait 1 5000] == 1} + assert {[$slave get foo] == 3} + } + + test {WAIT should not acknowledge 2 additional copies of the data} { + $master incr foo + assert {[$master wait 2 1000] <= 1} + } + + test {WAIT should not acknowledge 1 additional copy if slave is blocked} { + pause_process $slave_pid + $master set foo 0 + $master incr foo + $master incr foo + $master incr foo + assert {[$master wait 1 1000] == 0} + resume_process $slave_pid + assert {[$master wait 1 1000] == 1} + } + + test {WAIT implicitly blocks on client pause since ACKs aren't sent} { + pause_process $slave_pid + $master multi + $master incr foo + $master client pause 10000 write + $master exec + assert {[$master wait 1 1000] == 0} + $master client unpause + resume_process $slave_pid + assert {[$master wait 1 1000] == 1} + } + + test {WAIT replica multiple clients unblock - reuse last result} { + set rd [redis_deferring_client -1] + set rd2 [redis_deferring_client -1] + + pause_process $slave_pid + + $rd incr foo + $rd read + + $rd2 incr foo + $rd2 read + + $rd wait 1 0 + $rd2 wait 1 0 + wait_for_blocked_clients_count 2 100 10 -1 + + resume_process $slave_pid + + assert_equal [$rd read] {1} + assert_equal [$rd2 read] {1} + + $rd ping + assert_equal [$rd read] {PONG} + $rd2 ping + assert_equal [$rd2 read] {PONG} + + $rd close + $rd2 close + } +}} + + +tags {"wait aof network external:skip"} { + start_server {overrides {appendonly {yes} auto-aof-rewrite-percentage {0}}} { + set master [srv 0 client] + + test {WAITAOF local copy before fsync} { + r config set appendfsync no + $master incr foo + assert_equal [$master waitaof 1 0 50] {0 0} ;# exits on timeout + r config set appendfsync everysec + } + + test {WAITAOF local copy everysec} { + $master incr foo + assert_equal [$master waitaof 1 0 0] {1 0} + } + + test {WAITAOF local copy with appendfsync always} { + r config set appendfsync always + $master incr foo + assert_equal [$master waitaof 1 0 0] {1 0} + r config set appendfsync everysec + } + + test {WAITAOF local wait and then stop aof} { + set rd [redis_deferring_client] + $rd incr foo + $rd read + $rd waitaof 1 0 0 + wait_for_blocked_client + r config set appendonly no ;# this should release the blocked client as an error + assert_error {ERR WAITAOF cannot be used when numlocal is set but appendonly is disabled.} {$rd read} + $rd close + } + + test {WAITAOF local on server with aof disabled} { + $master incr foo + assert_error {ERR WAITAOF cannot be used when numlocal is set but appendonly is disabled.} {$master waitaof 1 0 0} + } + + test {WAITAOF local if AOFRW was postponed} { + r config set appendfsync everysec + + # turn off AOF + r config set appendonly no + + # create an RDB child that takes a lot of time to run + r set x y + r config set rdb-key-save-delay 100000000 ;# 100 seconds + r bgsave + assert_equal [s rdb_bgsave_in_progress] 1 + + # turn on AOF + r config set appendonly yes + assert_equal [s aof_rewrite_scheduled] 1 + + # create a write command (to increment master_repl_offset) + r set x y + + # reset save_delay and kill RDB child + r config set rdb-key-save-delay 0 + catch {exec kill -9 [get_child_pid 0]} + + # wait for AOF (will unblock after AOFRW finishes) + assert_equal [r waitaof 1 0 10000] {1 0} + + # make sure AOFRW finished + assert_equal [s aof_rewrite_in_progress] 0 + assert_equal [s aof_rewrite_scheduled] 0 + } + + $master config set appendonly yes + waitForBgrewriteaof $master + + start_server {overrides {appendonly {yes} auto-aof-rewrite-percentage {0}}} { + set master_host [srv -1 host] + set master_port [srv -1 port] + set replica [srv 0 client] + set replica_host [srv 0 host] + set replica_port [srv 0 port] + set replica_pid [srv 0 pid] + + # make sure the master always fsyncs first (easier to test) + $master config set appendfsync always + $replica config set appendfsync no + + test {WAITAOF on demoted master gets unblocked with an error} { + set rd [redis_deferring_client] + $rd incr foo + $rd read + $rd waitaof 0 1 0 + wait_for_blocked_client + $replica replicaof $master_host $master_port + assert_error {UNBLOCKED force unblock from blocking operation,*} {$rd read} + $rd close + } + + wait_for_ofs_sync $master $replica + + test {WAITAOF replica copy before fsync} { + $master incr foo + assert_equal [$master waitaof 0 1 50] {1 0} ;# exits on timeout + } + $replica config set appendfsync everysec + + test {WAITAOF replica copy everysec} { + $replica config set appendfsync everysec + waitForBgrewriteaof $replica ;# Make sure there is no AOFRW + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica copy everysec with AOFRW} { + $replica config set appendfsync everysec + + # When we trigger an AOFRW, a fsync is triggered when closing the old INCR file, + # so with the everysec, we will skip that second of fsync, and in the next second + # after that, we will eventually do the fsync. + $replica bgrewriteaof + waitForBgrewriteaof $replica + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica copy everysec with slow AOFRW} { + $replica config set appendfsync everysec + $replica config set rdb-key-save-delay 1000000 ;# 1 sec + + $replica bgrewriteaof + + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + + $replica config set rdb-key-save-delay 0 + waitForBgrewriteaof $replica + } + + test {WAITAOF replica copy everysec->always with AOFRW} { + $replica config set appendfsync everysec + + # Try to fit all of them in the same round second, although there's no way to guarantee + # that, it can be done on fast machine. In any case, the test shouldn't fail either. + $replica bgrewriteaof + $master incr foo + waitForBgrewriteaof $replica + $replica config set appendfsync always + + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica copy appendfsync always} { + $replica config set appendfsync always + $master incr foo + assert_equal [$master waitaof 0 1 0] {1 1} + $replica config set appendfsync everysec + } + + test {WAITAOF replica copy if replica is blocked} { + pause_process $replica_pid + $master incr foo + assert_equal [$master waitaof 0 1 50] {1 0} ;# exits on timeout + resume_process $replica_pid + assert_equal [$master waitaof 0 1 0] {1 1} + } + + test {WAITAOF replica multiple clients unblock - reuse last result} { + set rd [redis_deferring_client -1] + set rd2 [redis_deferring_client -1] + + pause_process $replica_pid + + $rd incr foo + $rd read + + $rd2 incr foo + $rd2 read + + $rd waitaof 0 1 0 + $rd2 waitaof 0 1 0 + wait_for_blocked_clients_count 2 100 10 -1 + + resume_process $replica_pid + + assert_equal [$rd read] {1 1} + assert_equal [$rd2 read] {1 1} + + $rd ping + assert_equal [$rd read] {PONG} + $rd2 ping + assert_equal [$rd2 read] {PONG} + + $rd close + $rd2 close + } + + test {WAITAOF on promoted replica} { + $replica replicaof no one + $replica incr foo + assert_equal [$replica waitaof 1 0 0] {1 0} + } + + test {WAITAOF master that loses a replica and backlog is dropped} { + $master config set repl-backlog-ttl 1 + after 2000 ;# wait for backlog to expire + $master incr foo + assert_equal [$master waitaof 1 0 0] {1 0} + } + + test {WAITAOF master without backlog, wait is released when the replica finishes full-sync} { + set rd [redis_deferring_client -1] + $rd incr foo + $rd read + $rd waitaof 0 1 0 + wait_for_blocked_client -1 + $replica replicaof $master_host $master_port + assert_equal [$rd read] {1 1} + $rd close + } + + test {WAITAOF master isn't configured to do AOF} { + $master config set appendonly no + $master incr foo + assert_equal [$master waitaof 0 1 0] {0 1} + } + + test {WAITAOF replica isn't configured to do AOF} { + $master config set appendonly yes + waitForBgrewriteaof $master + $replica config set appendonly no + $master incr foo + assert_equal [$master waitaof 1 0 0] {1 0} + } + + test {WAITAOF both local and replica got AOF enabled at runtime} { + $replica config set appendonly yes + waitForBgrewriteaof $replica + $master incr foo + assert_equal [$master waitaof 1 1 0] {1 1} + } + + test {WAITAOF master sends PING after last write} { + $master config set repl-ping-replica-period 1 + $master incr foo + after 1200 ;# wait for PING + $master get foo + assert_equal [$master waitaof 1 1 0] {1 1} + $master config set repl-ping-replica-period 10 + } + + test {WAITAOF master client didn't send any write command} { + $master config set repl-ping-replica-period 1 + set client [redis_client -1] + after 1200 ;# wait for PING + assert_equal [$master waitaof 1 1 0] {1 1} + $client close + $master config set repl-ping-replica-period 10 + } + + test {WAITAOF master client didn't send any command} { + $master config set repl-ping-replica-period 1 + set client [redis [srv -1 "host"] [srv -1 "port"] 0 $::tls] + after 1200 ;# wait for PING + assert_equal [$master waitaof 1 1 0] {1 1} + $client close + $master config set repl-ping-replica-period 10 + } + + foreach fsync {no everysec always} { + test "WAITAOF when replica switches between masters, fsync: $fsync" { + # test a case where a replica is moved from one master to the other + # between two replication streams with different offsets that should + # not be mixed. done to smoke-test race conditions with bio thread. + start_server {overrides {appendonly {yes} auto-aof-rewrite-percentage {0}}} { + start_server {overrides {appendonly {yes} auto-aof-rewrite-percentage {0}}} { + set master2 [srv -1 client] + set master2_host [srv -1 host] + set master2_port [srv -1 port] + set replica2 [srv 0 client] + set replica2_host [srv 0 host] + set replica2_port [srv 0 port] + set replica2_pid [srv 0 pid] + + $replica2 replicaof $master2_host $master2_port + wait_for_ofs_sync $master2 $replica2 + + $master config set appendfsync $fsync + $master2 config set appendfsync $fsync + $replica config set appendfsync $fsync + $replica2 config set appendfsync $fsync + if {$fsync eq "no"} { + after 2000 ;# wait for any previous fsync to finish + # can't afford "no" on the masters + $master config set appendfsync always + $master2 config set appendfsync always + } elseif {$fsync eq "everysec"} { + after 990 ;# hoping to hit a race + } + + # add some writes and block a client on each master + set rd [redis_deferring_client -3] + set rd2 [redis_deferring_client -1] + $rd set boo 11 + $rd2 set boo 22 + $rd read + $rd2 read + $rd waitaof 1 1 0 + $rd2 waitaof 1 1 0 + + if {$fsync eq "no"} { + # since appendfsync is disabled in the replicas, the client + # will get released only with full sync + wait_for_blocked_client -1 + wait_for_blocked_client -3 + } + # switch between the two replicas + $replica2 replicaof $master_host $master_port + $replica replicaof $master2_host $master2_port + assert_equal [$rd read] {1 1} + assert_equal [$rd2 read] {1 1} + $rd close + $rd2 close + + assert_equal [$replica get boo] 22 + assert_equal [$replica2 get boo] 11 + } + } + } + } + } + } +} + +start_server {tags {"failover external:skip"}} { +start_server {} { +start_server {} { + set master [srv 0 client] + set master_host [srv 0 host] + set master_port [srv 0 port] + + set replica1 [srv -1 client] + set replica1_pid [srv -1 pid] + + set replica2 [srv -2 client] + + test {setup replication for following tests} { + $replica1 replicaof $master_host $master_port + $replica2 replicaof $master_host $master_port + wait_for_sync $replica1 + wait_for_sync $replica2 + } + + test {WAIT and WAITAOF replica multiple clients unblock - reuse last result} { + set rd [redis_deferring_client] + set rd2 [redis_deferring_client] + + $master config set appendonly yes + $replica1 config set appendonly yes + $replica2 config set appendonly yes + + $master config set appendfsync always + $replica1 config set appendfsync no + $replica2 config set appendfsync no + + waitForBgrewriteaof $master + waitForBgrewriteaof $replica1 + waitForBgrewriteaof $replica2 + + pause_process $replica1_pid + + $rd incr foo + $rd read + $rd waitaof 0 1 0 + + # rd2 has a newer repl_offset + $rd2 incr foo + $rd2 read + $rd2 wait 2 0 + + wait_for_blocked_clients_count 2 + + resume_process $replica1_pid + + # WAIT will unblock the client first. + assert_equal [$rd2 read] {2} + + # Make $replica1 catch up the repl_aof_off, then WAITAOF will unblock the client. + $replica1 config set appendfsync always + $master incr foo + assert_equal [$rd read] {1 1} + + $rd ping + assert_equal [$rd read] {PONG} + $rd2 ping + assert_equal [$rd2 read] {PONG} + + $rd close + $rd2 close + } +} +} +} -- cgit v1.2.3