summaryrefslogtreecommitdiffstats
path: root/tests/unit/wait.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/wait.tcl
parentInitial commit. (diff)
downloadredis-317c0644ccf108aa23ef3fd8358bd66c2840bfc0.tar.xz
redis-317c0644ccf108aa23ef3fd8358bd66c2840bfc0.zip
Adding upstream version 5:7.2.4.upstream/5%7.2.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/unit/wait.tcl')
-rw-r--r--tests/unit/wait.tcl505
1 files changed, 505 insertions, 0 deletions
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
+ }
+}
+}
+}