mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 08:38:27 -05:00
997fa41e99
The MacOS CI in github actions often hangs without any logs. GH argues that it's due to resource utilization, either running out of disk space, memory, or CPU starvation, and thus the runner is terminated. This PR contains multiple attempts to resolve this: 1. introducing pause_process instead of SIGSTOP, which waits for the process to stop before resuming the test, possibly resolving race conditions in some tests, this was a suspect since there was one test that could result in an infinite loop in that case, in practice this didn't help, but still a good idea to keep. 2. disable the `save` config in many tests that don't need it, specifically ones that use heavy writes and could create large files. 3. change the `populate` proc to use short pipeline rather than an infinite one. 4. use `--clients 1` in the macos CI so that we don't risk running multiple resource demanding tests in parallel. 5. enable `--verbose` to be repeated to elevate verbosity and print more info to stdout when a test or a server starts.
272 lines
10 KiB
Tcl
272 lines
10 KiB
Tcl
start_server {tags {"repl network external:skip singledb:skip"} overrides {save {}}} {
|
|
start_server { overrides {save {}}} {
|
|
|
|
set master [srv -1 client]
|
|
set master_host [srv -1 host]
|
|
set master_port [srv -1 port]
|
|
set slave [srv 0 client]
|
|
|
|
set load_handle0 [start_bg_complex_data $master_host $master_port 9 100000]
|
|
set load_handle1 [start_bg_complex_data $master_host $master_port 11 100000]
|
|
set load_handle2 [start_bg_complex_data $master_host $master_port 12 100000]
|
|
|
|
test {First server should have role slave after SLAVEOF} {
|
|
$slave slaveof $master_host $master_port
|
|
wait_for_condition 50 100 {
|
|
[s 0 role] eq {slave}
|
|
} else {
|
|
fail "Replication not started."
|
|
}
|
|
}
|
|
|
|
test {Test replication with parallel clients writing in different DBs} {
|
|
# Gives the random workloads a chance to add some complex commands.
|
|
after 5000
|
|
|
|
# Make sure all parallel clients have written data.
|
|
wait_for_condition 1000 50 {
|
|
[$master select 9] == {OK} && [$master dbsize] > 0 &&
|
|
[$master select 11] == {OK} && [$master dbsize] > 0 &&
|
|
[$master select 12] == {OK} && [$master dbsize] > 0
|
|
} else {
|
|
fail "Parallel clients are not writing in different DBs."
|
|
}
|
|
|
|
stop_bg_complex_data $load_handle0
|
|
stop_bg_complex_data $load_handle1
|
|
stop_bg_complex_data $load_handle2
|
|
wait_for_condition 100 100 {
|
|
[$master debug digest] == [$slave debug digest]
|
|
} else {
|
|
set csv1 [csvdump r]
|
|
set csv2 [csvdump {r -1}]
|
|
set fd [open /tmp/repldump1.txt w]
|
|
puts -nonewline $fd $csv1
|
|
close $fd
|
|
set fd [open /tmp/repldump2.txt w]
|
|
puts -nonewline $fd $csv2
|
|
close $fd
|
|
fail "Master - Replica inconsistency, Run diff -u against /tmp/repldump*.txt for more info"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
start_server {tags {"repl external:skip"}} {
|
|
start_server {} {
|
|
set master [srv -1 client]
|
|
set master_host [srv -1 host]
|
|
set master_port [srv -1 port]
|
|
set slave [srv 0 client]
|
|
|
|
# Load some functions to be used later
|
|
$master FUNCTION load replace {#!lua name=test
|
|
redis.register_function{function_name='f_default_flags', callback=function(keys, args) return redis.call('get',keys[1]) end, flags={}}
|
|
redis.register_function{function_name='f_no_writes', callback=function(keys, args) return redis.call('get',keys[1]) end, flags={'no-writes'}}
|
|
}
|
|
|
|
test {First server should have role slave after SLAVEOF} {
|
|
$slave slaveof $master_host $master_port
|
|
wait_replica_online $master
|
|
}
|
|
|
|
test {With min-slaves-to-write (1,3): master should be writable} {
|
|
$master config set min-slaves-max-lag 3
|
|
$master config set min-slaves-to-write 1
|
|
assert_equal OK [$master set foo 123]
|
|
assert_equal OK [$master eval "return redis.call('set','foo',12345)" 0]
|
|
}
|
|
|
|
test {With min-slaves-to-write (2,3): master should not be writable} {
|
|
$master config set min-slaves-max-lag 3
|
|
$master config set min-slaves-to-write 2
|
|
assert_error "*NOREPLICAS*" {$master set foo bar}
|
|
assert_error "*NOREPLICAS*" {$master eval "redis.call('set','foo','bar')" 0}
|
|
}
|
|
|
|
test {With min-slaves-to-write function without no-write flag} {
|
|
assert_error "*NOREPLICAS*" {$master fcall f_default_flags 1 foo}
|
|
assert_equal "12345" [$master fcall f_no_writes 1 foo]
|
|
}
|
|
|
|
test {With not enough good slaves, read in Lua script is still accepted} {
|
|
$master config set min-slaves-max-lag 3
|
|
$master config set min-slaves-to-write 1
|
|
$master eval "redis.call('set','foo','bar')" 0
|
|
|
|
$master config set min-slaves-to-write 2
|
|
$master eval "return redis.call('get','foo')" 0
|
|
} {bar}
|
|
|
|
test {With min-slaves-to-write: master not writable with lagged slave} {
|
|
$master config set min-slaves-max-lag 2
|
|
$master config set min-slaves-to-write 1
|
|
assert_equal OK [$master set foo 123]
|
|
assert_equal OK [$master eval "return redis.call('set','foo',12345)" 0]
|
|
# Killing a slave to make it become a lagged slave.
|
|
pause_process [srv 0 pid]
|
|
# Waiting for slave kill.
|
|
wait_for_condition 100 100 {
|
|
[catch {$master set foo 123}] != 0
|
|
} else {
|
|
fail "Master didn't become readonly"
|
|
}
|
|
assert_error "*NOREPLICAS*" {$master set foo 123}
|
|
assert_error "*NOREPLICAS*" {$master eval "return redis.call('set','foo',12345)" 0}
|
|
resume_process [srv 0 pid]
|
|
}
|
|
}
|
|
}
|
|
|
|
start_server {tags {"repl external:skip"}} {
|
|
start_server {} {
|
|
set master [srv -1 client]
|
|
set master_host [srv -1 host]
|
|
set master_port [srv -1 port]
|
|
set slave [srv 0 client]
|
|
|
|
test {First server should have role slave after SLAVEOF} {
|
|
$slave slaveof $master_host $master_port
|
|
wait_for_condition 50 100 {
|
|
[s 0 master_link_status] eq {up}
|
|
} else {
|
|
fail "Replication not started."
|
|
}
|
|
}
|
|
|
|
test {Replication of an expired key does not delete the expired key} {
|
|
# This test is very likely to do a false positive if the wait_for_ofs_sync
|
|
# takes longer than the expiration time, so give it a few more chances.
|
|
# Go with 5 retries of increasing timeout, i.e. start with 500ms, then go
|
|
# to 1000ms, 2000ms, 4000ms, 8000ms.
|
|
set px_ms 500
|
|
for {set i 0} {$i < 5} {incr i} {
|
|
|
|
wait_for_ofs_sync $master $slave
|
|
$master debug set-active-expire 0
|
|
$master set k 1 px $px_ms
|
|
wait_for_ofs_sync $master $slave
|
|
pause_process [srv 0 pid]
|
|
$master incr k
|
|
after [expr $px_ms + 1]
|
|
# Stopping the replica for one second to makes sure the INCR arrives
|
|
# to the replica after the key is logically expired.
|
|
resume_process [srv 0 pid]
|
|
wait_for_ofs_sync $master $slave
|
|
# Check that k is logically expired but is present in the replica.
|
|
set res [$slave exists k]
|
|
set errcode [catch {$slave debug object k} err] ; # Raises exception if k is gone.
|
|
if {$res == 0 && $errcode == 0} { break }
|
|
set px_ms [expr $px_ms * 2]
|
|
|
|
} ;# for
|
|
|
|
if {$::verbose} { puts "Replication of an expired key does not delete the expired key test attempts: $i" }
|
|
assert_equal $res 0
|
|
assert_equal $errcode 0
|
|
}
|
|
}
|
|
}
|
|
|
|
start_server {tags {"repl external:skip"}} {
|
|
start_server {} {
|
|
set master [srv -1 client]
|
|
set master_host [srv -1 host]
|
|
set master_port [srv -1 port]
|
|
set slave [srv 0 client]
|
|
|
|
test {First server should have role slave after SLAVEOF} {
|
|
$slave slaveof $master_host $master_port
|
|
wait_for_condition 50 100 {
|
|
[s 0 role] eq {slave}
|
|
} else {
|
|
fail "Replication not started."
|
|
}
|
|
}
|
|
|
|
test {Replication: commands with many arguments (issue #1221)} {
|
|
# We now issue large MSET commands, that may trigger a specific
|
|
# class of bugs, see issue #1221.
|
|
for {set j 0} {$j < 100} {incr j} {
|
|
set cmd [list mset]
|
|
for {set x 0} {$x < 1000} {incr x} {
|
|
lappend cmd [randomKey] [randomValue]
|
|
}
|
|
$master {*}$cmd
|
|
}
|
|
|
|
set retry 10
|
|
while {$retry && ([$master debug digest] ne [$slave debug digest])}\
|
|
{
|
|
after 1000
|
|
incr retry -1
|
|
}
|
|
assert {[$master dbsize] > 0}
|
|
}
|
|
|
|
test {Replication of SPOP command -- alsoPropagate() API} {
|
|
$master del myset
|
|
set size [expr 1+[randomInt 100]]
|
|
set content {}
|
|
for {set j 0} {$j < $size} {incr j} {
|
|
lappend content [randomValue]
|
|
}
|
|
$master sadd myset {*}$content
|
|
|
|
set count [randomInt 100]
|
|
set result [$master spop myset $count]
|
|
|
|
wait_for_condition 50 100 {
|
|
[$master debug digest] eq [$slave debug digest]
|
|
} else {
|
|
fail "SPOP replication inconsistency"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
start_server {tags {"repl external:skip"}} {
|
|
start_server {} {
|
|
set master [srv -1 client]
|
|
set master_host [srv -1 host]
|
|
set master_port [srv -1 port]
|
|
set replica [srv 0 client]
|
|
|
|
test {First server should have role slave after SLAVEOF} {
|
|
$replica slaveof $master_host $master_port
|
|
wait_for_condition 50 100 {
|
|
[s 0 role] eq {slave}
|
|
} else {
|
|
fail "Replication not started."
|
|
}
|
|
wait_for_sync $replica
|
|
}
|
|
|
|
test {Data divergence can happen under default conditions} {
|
|
$replica config set propagation-error-behavior ignore
|
|
$master debug replicate fake-command-1
|
|
|
|
# Wait for replication to normalize
|
|
$master set foo bar2
|
|
$master wait 1 2000
|
|
|
|
# Make sure we triggered the error, by finding the critical
|
|
# message and the fake command.
|
|
assert_equal [count_log_message 0 "fake-command-1"] 1
|
|
assert_equal [count_log_message 0 "== CRITICAL =="] 1
|
|
}
|
|
|
|
test {Data divergence is allowed on writable replicas} {
|
|
$replica config set replica-read-only no
|
|
$replica set number2 foo
|
|
$master incrby number2 1
|
|
$master wait 1 2000
|
|
|
|
assert_equal [$master get number2] 1
|
|
assert_equal [$replica get number2] foo
|
|
|
|
assert_equal [count_log_message 0 "incrby"] 1
|
|
}
|
|
}
|
|
}
|