From 82fe4fcfac320fdebd9b11cf84932375897a5cdd Mon Sep 17 00:00:00 2001 From: Warrick <1016weicheng@gmail.com> Date: Fri, 10 Apr 2026 16:43:24 +0800 Subject: [PATCH 1/3] [fix] tests/gtid/xsync.tcl WRONGTYPE --- tests/gtid/xsync.tcl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/gtid/xsync.tcl b/tests/gtid/xsync.tcl index 34d07fff4db..77d72a323c5 100644 --- a/tests/gtid/xsync.tcl +++ b/tests/gtid/xsync.tcl @@ -166,6 +166,18 @@ start_server {tags {"xsync"} overrides {gtid-enabled yes}} { # after fullresync, S SS is consistent with M assert_equal [$M hmget hello f1 f2] {v2 v2} + + # In swap mode servercron (which triggers forced full resync on + # WRONGTYPE) may be delayed. wait_for_sync only + # checks master_link_status=="up", which can still be true before + # the resync fires. Wait explicitly for S to have the correct type. + if {$::swap} { + wait_for_condition 500 100 { + [catch {$S hmget hello f1 f2} _sr] == 0 && $_sr eq {v2 v2} + } else { + fail "S not fixed by forced full resync in swap mode" + } + } assert_equal [$S hmget hello f1 f2] {v2 v2} catch {$SS hmget hello f1 f2} result @@ -1638,4 +1650,4 @@ start_server {tags {"xsync"} overrides {gtid-enabled yes}} { } } -} \ No newline at end of file +} From 4251b3659ee48f4d0f566b0e026ef28c8a32f130 Mon Sep 17 00:00:00 2001 From: Warrick <1016weicheng@gmail.com> Date: Fri, 10 Apr 2026 18:04:03 +0800 Subject: [PATCH 2/3] fix: swap_data_comp set comparison uses hardcoded key and wrong sismember args In swap_data_comp, the {set} branch had two bugs: 1. Used hardcoded 'r smembers k1' instead of '$r1 smembers $key' 2. Called '$r2 sismember $skey' with missing key argument (should be '$r2 sismember $key $skey') Bug 1 causes intermittent WRONGTYPE errors in CI: randstring alpha uses ASCII range 48-122 (includes digits), so randomKey can occasionally generate key 'k1' with a non-set type. With 10000 ops the probability is ~0.09% per run. Bug 2 would cause 'wrong number of arguments' if k1 happened to be a set type. Both bugs only affect swap mode tests (swap_data_comp is only called from swap ported tests). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/swap/support/util.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/swap/support/util.tcl b/tests/swap/support/util.tcl index 3a544fe4d18..c617b965ad7 100644 --- a/tests/swap/support/util.tcl +++ b/tests/swap/support/util.tcl @@ -530,9 +530,9 @@ proc swap_data_comp {r1 r2} { if {$len != $len2} { data_conflict $t $key '' 'SLEN:$len' 'SLEN:$len2' } - set skeys [r smembers k1] + set skeys [$r1 smembers $key] foreach skey $skeys { - if {0 == [$r2 sismember $skey]} { + if {0 == [$r2 sismember $key $skey]} { data_conflict $t $key $skey "1" "0" } } From 96956f463bf1ec3eb8570d0027334d1d7274dc58 Mon Sep 17 00:00:00 2001 From: Warrick <1016weicheng@gmail.com> Date: Sun, 12 Apr 2026 16:36:40 +0800 Subject: [PATCH 3/3] [fix] add dbsize_loadsafe --- tests/gtid/master_restart.tcl | 12 ++++++++---- tests/gtid/sync.tcl | 6 ++++-- tests/integration/psync2-pingoff.tcl | 5 ++++- tests/integration/psync2-reg.tcl | 6 ++++-- tests/integration/replication.tcl | 4 +++- tests/support/util.tcl | 9 +++++++++ .../swap/integration/repro-swapdb-inconsistency.tcl | 5 +++-- tests/swap/ported/integration/block-repl.tcl | 4 +++- tests/swap/ported/integration/psync2-reg.tcl | 13 +++++++++---- tests/swap/ported/integration/replication-3.tcl | 9 ++++++--- tests/swap/ported/integration/replication-psync.tcl | 4 +++- tests/swap/ported/integration/replication.tcl | 11 ++++++++--- tests/swap/unit/select.tcl | 4 +++- 13 files changed, 67 insertions(+), 25 deletions(-) diff --git a/tests/gtid/master_restart.tcl b/tests/gtid/master_restart.tcl index 29abc7a0db3..f96295547e2 100644 --- a/tests/gtid/master_restart.tcl +++ b/tests/gtid/master_restart.tcl @@ -163,11 +163,15 @@ proc restart_test {master_gtid_enabled slave_gtid_enabled restat_master_gtid_ena } wait_for_condition 1000 30 { - [$master dbsize] eq [$slave dbsize] - && [$slave dbsize] eq 0 + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize eq $slave_dbsize && + $slave_dbsize eq 0 } else { - puts [$master dbsize] - puts [$slave dbsize] + puts [dbsize_loadsafe $master master_dbsize] + puts $master_dbsize + puts [dbsize_loadsafe $slave slave_dbsize] + puts $slave_dbsize fail "slave dbszie != 0" } diff --git a/tests/gtid/sync.tcl b/tests/gtid/sync.tcl index 40b1c2dac9f..2d047752a52 100644 --- a/tests/gtid/sync.tcl +++ b/tests/gtid/sync.tcl @@ -21,7 +21,8 @@ start_server {overrides {gtid-enabled yes}} { $R(1) slaveof $R_host(0) $R_port(0) wait_for_condition 50 1000 { [status $R(1) master_link_status] == "up" && - [$R(1) dbsize] == 1 + [dbsize_loadsafe $R(1) replica_dbsize] && + $replica_dbsize == 1 } else { fail "Replicas not replicating from master" } @@ -155,7 +156,8 @@ start_server {overrides {gtid-enabled yes}} { $R(1) slaveof $R_host(0) $R_port(0) wait_for_condition 50 1000 { [status $R(1) master_link_status] == "up" && - [$R(1) dbsize] == 1 + [dbsize_loadsafe $R(1) replica_dbsize] && + $replica_dbsize == 1 } else { fail "Replicas not replicating from master" } diff --git a/tests/integration/psync2-pingoff.tcl b/tests/integration/psync2-pingoff.tcl index 3589d07e75f..ec179635af8 100644 --- a/tests/integration/psync2-pingoff.tcl +++ b/tests/integration/psync2-pingoff.tcl @@ -24,7 +24,10 @@ start_server {} { $R(0) set foo bar wait_for_condition 50 1000 { [status $R(1) master_link_status] == "up" && - [$R(0) dbsize] == 1 && [$R(1) dbsize] == 1 + [dbsize_loadsafe $R(0) master_dbsize] && + [dbsize_loadsafe $R(1) replica_dbsize] && + $master_dbsize == 1 && + $replica_dbsize == 1 } else { fail "Replicas not replicating from master" } diff --git a/tests/integration/psync2-reg.tcl b/tests/integration/psync2-reg.tcl index e20f152babd..4d29b7ba6c3 100644 --- a/tests/integration/psync2-reg.tcl +++ b/tests/integration/psync2-reg.tcl @@ -30,8 +30,10 @@ start_server {} { wait_for_condition 50 1000 { [status $R(1) master_link_status] == "up" && [status $R(2) master_link_status] == "up" && - [$R(1) dbsize] == 1 && - [$R(2) dbsize] == 1 + [dbsize_loadsafe $R(1) replica1_dbsize] && + [dbsize_loadsafe $R(2) replica2_dbsize] && + $replica1_dbsize == 1 && + $replica2_dbsize == 1 } else { fail "Replicas not replicating from master" } diff --git a/tests/integration/replication.tcl b/tests/integration/replication.tcl index 5a0d0ea69d2..7e29944e558 100644 --- a/tests/integration/replication.tcl +++ b/tests/integration/replication.tcl @@ -1037,7 +1037,9 @@ start_server {tags {"repl external:skip tsan:skip"} overrides {save ""}} { # Make sure that replicas and master have same # number of keys wait_for_condition 50 100 { - [$master dbsize] == [$replica dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $replica replica_dbsize] && + $master_dbsize == $replica_dbsize } else { fail "Different number of keys between master and replicas after too long time." } diff --git a/tests/support/util.tcl b/tests/support/util.tcl index 3090b54bc19..a11bb23cefe 100644 --- a/tests/support/util.tcl +++ b/tests/support/util.tcl @@ -100,6 +100,15 @@ proc status {r property} { set _ [getInfoProperty [{*}$r info] $property] } +proc dbsize_loadsafe {r varname} { + upvar 1 $varname dbsize + if {$::swap} { + return [expr {[catch {{*}$r dbsize} dbsize] == 0}] + } + set dbsize [{*}$r dbsize] + return 1 +} + proc waitForBgsave r { while 1 { if {[status $r rdb_bgsave_in_progress] eq 1} { diff --git a/tests/swap/integration/repro-swapdb-inconsistency.tcl b/tests/swap/integration/repro-swapdb-inconsistency.tcl index 87d48e4f1ee..d58d9ab5395 100644 --- a/tests/swap/integration/repro-swapdb-inconsistency.tcl +++ b/tests/swap/integration/repro-swapdb-inconsistency.tcl @@ -100,7 +100,9 @@ start_server {tags {"repl"}} { } wait_for_condition 200 100 { - [$master dbsize] == [$slave dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize == $slave_dbsize } else { # dump key lists (scan-based, works for cold keys too) dump_keylist $master /tmp/replkeys_master.txt @@ -120,4 +122,3 @@ start_server {tags {"repl"}} { } } - diff --git a/tests/swap/ported/integration/block-repl.tcl b/tests/swap/ported/integration/block-repl.tcl index 7aa2758bf82..f42489008e9 100644 --- a/tests/swap/ported/integration/block-repl.tcl +++ b/tests/swap/ported/integration/block-repl.tcl @@ -34,7 +34,9 @@ start_server {tags {"repl"}} { stop_bg_block_op $load_handle1 stop_bg_block_op $load_handle2 wait_for_condition 100 100 { - [$master dbsize] == [$slave dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize == $slave_dbsize } else { set csv1 [csvdump r] set csv2 [csvdump {r -1}] diff --git a/tests/swap/ported/integration/psync2-reg.tcl b/tests/swap/ported/integration/psync2-reg.tcl index 2d1043faa21..e5a94484ef4 100644 --- a/tests/swap/ported/integration/psync2-reg.tcl +++ b/tests/swap/ported/integration/psync2-reg.tcl @@ -30,8 +30,10 @@ start_server {} { wait_for_condition 50 1000 { [status $R(1) master_link_status] == "up" && [status $R(2) master_link_status] == "up" && - [$R(1) dbsize] == 1 && - [$R(2) dbsize] == 1 + [dbsize_loadsafe $R(1) replica1_dbsize] && + [dbsize_loadsafe $R(2) replica2_dbsize] && + $replica1_dbsize == 1 && + $replica2_dbsize == 1 } else { fail "Replicas not replicating from master" } @@ -73,8 +75,11 @@ start_server {} { test "PSYNC2 #3899 regression: verify consistency" { wait_for_condition 50 1000 { - ([$R(0) dbsize] eq [$R(1) dbsize]) && - ([$R(1) dbsize] eq [$R(2) dbsize]) + [dbsize_loadsafe $R(0) master_dbsize] && + [dbsize_loadsafe $R(1) replica1_dbsize] && + [dbsize_loadsafe $R(2) replica2_dbsize] && + ($master_dbsize eq $replica1_dbsize) && + ($replica1_dbsize eq $replica2_dbsize) } else { fail "The three instances have different data sets" } diff --git a/tests/swap/ported/integration/replication-3.tcl b/tests/swap/ported/integration/replication-3.tcl index 9233c12db01..a1e92ad0411 100644 --- a/tests/swap/ported/integration/replication-3.tcl +++ b/tests/swap/ported/integration/replication-3.tcl @@ -17,7 +17,9 @@ start_server {tags {"repl"}} { r keys * ;# Force DEL syntesizing to slave after 1000 ;# Wait another second. Now everything should be fine. wait_for_condition 100 50 { - [r -1 dbsize] == [r dbsize] + [dbsize_loadsafe {r -1} replica_dbsize] && + [dbsize_loadsafe r master_dbsize] && + $replica_dbsize == $master_dbsize } else { fail "wait sync" } @@ -44,7 +46,9 @@ start_server {tags {"repl"}} { test {Slave is able to evict keys created in writable slaves} { # wait createComplexDataset wait_for_condition 500 100 { - [r dbsize] == [r -1 dbsize] + [dbsize_loadsafe r master_dbsize] && + [dbsize_loadsafe {r -1} replica_dbsize] && + $master_dbsize == $replica_dbsize } else { fail "Replicas and master offsets were unable to match *exactly*." } @@ -64,4 +68,3 @@ start_server {tags {"repl"}} { } {0} } } - diff --git a/tests/swap/ported/integration/replication-psync.tcl b/tests/swap/ported/integration/replication-psync.tcl index 717853fbc8e..43355da99b7 100644 --- a/tests/swap/ported/integration/replication-psync.tcl +++ b/tests/swap/ported/integration/replication-psync.tcl @@ -89,7 +89,9 @@ proc test_psync {descr duration backlog_size backlog_ttl delay cond mdl sdl bgsa } wait_for_condition 100 100 { - [$master dbsize] == [$slave dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize == $slave_dbsize } else { set csv1 [csvdump r] set csv2 [csvdump {r -1}] diff --git a/tests/swap/ported/integration/replication.tcl b/tests/swap/ported/integration/replication.tcl index bbeab9d5e9b..25f040025ed 100644 --- a/tests/swap/ported/integration/replication.tcl +++ b/tests/swap/ported/integration/replication.tcl @@ -205,9 +205,12 @@ start_server {tags {"repl"} overrides {repl-backlog-size 10mb}} { # Stop the write load stop_write_load $load_handle0 - # number of keys + # number of keys wait_for_condition 500 100 { - [$master dbsize] eq [$slave dbsize] && [$master dbsize] > 0 + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize eq $slave_dbsize && + $master_dbsize > 0 } else { fail "Different datasets between replica and master" } @@ -450,7 +453,9 @@ start_server {tags {"repl" "nosanitizer"} overrides {swap-repl-rordb-sync no}} { # Make sure that replicas and master have same # number of keys wait_for_condition 50 100 { - [$master dbsize] == [$replica dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $replica replica_dbsize] && + $master_dbsize == $replica_dbsize } else { fail "Different number of keys between master and replicas after too long time." } diff --git a/tests/swap/unit/select.tcl b/tests/swap/unit/select.tcl index cac26164443..72cda8c79fe 100644 --- a/tests/swap/unit/select.tcl +++ b/tests/swap/unit/select.tcl @@ -345,7 +345,9 @@ start_server {overrides {save ""} tags {"swap" "select"}} { $master select $db $slave select $db wait_for_condition 500 10 { - [$master dbsize] eq [$slave dbsize] + [dbsize_loadsafe $master master_dbsize] && + [dbsize_loadsafe $slave slave_dbsize] && + $master_dbsize eq $slave_dbsize } else { fail "db$db dbsize not match" }