Cluster test improvements (#10920)
* Restructured testing to allow running cluster tests easily as part of the normal testing
This commit is contained in:
parent
8221d48165
commit
8a4e3bcd8d
@ -63,24 +63,6 @@ test "It is possible to write and read from the cluster" {
|
|||||||
cluster_write_test 0
|
cluster_write_test 0
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Function no-cluster flag" {
|
|
||||||
R 1 function load {#!lua name=test
|
|
||||||
redis.register_function{function_name='f1', callback=function() return 'hello' end, flags={'no-cluster'}}
|
|
||||||
}
|
|
||||||
catch {R 1 fcall f1 0} e
|
|
||||||
assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Script no-cluster flag" {
|
|
||||||
catch {
|
|
||||||
R 1 eval {#!lua flags=no-cluster
|
|
||||||
return 1
|
|
||||||
} 0
|
|
||||||
} e
|
|
||||||
|
|
||||||
assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
|
|
||||||
}
|
|
||||||
|
|
||||||
test "CLUSTER RESET SOFT test" {
|
test "CLUSTER RESET SOFT test" {
|
||||||
set last_epoch_node0 [get_info_field [R 0 cluster info] cluster_current_epoch]
|
set last_epoch_node0 [get_info_field [R 0 cluster info] cluster_current_epoch]
|
||||||
R 0 FLUSHALL
|
R 0 FLUSHALL
|
||||||
@ -92,4 +74,3 @@ test "CLUSTER RESET SOFT test" {
|
|||||||
R 1 CLUSTER RESET SOFT
|
R 1 CLUSTER RESET SOFT
|
||||||
assert {[get_info_field [R 1 cluster info] cluster_current_epoch] eq $last_epoch_node1}
|
assert {[get_info_field [R 1 cluster info] cluster_current_epoch] eq $last_epoch_node1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
tests/support/cluster_helper.tcl
Normal file
96
tests/support/cluster_helper.tcl
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# Helper functions specifically for setting up and configuring redis
|
||||||
|
# clusters.
|
||||||
|
|
||||||
|
# Check if cluster configuration is consistent.
|
||||||
|
proc cluster_config_consistent {} {
|
||||||
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
|
if {$j == 0} {
|
||||||
|
set base_cfg [R $j cluster slots]
|
||||||
|
} else {
|
||||||
|
if {[R $j cluster slots] != $base_cfg} {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for cluster configuration to propagate and be consistent across nodes.
|
||||||
|
proc wait_for_cluster_propagation {} {
|
||||||
|
wait_for_condition 50 100 {
|
||||||
|
[cluster_config_consistent] eq 1
|
||||||
|
} else {
|
||||||
|
fail "cluster config did not reach a consistent state"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check that cluster nodes agree about "state", or raise an error.
|
||||||
|
proc wait_for_cluster_state {state} {
|
||||||
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
|
wait_for_condition 100 50 {
|
||||||
|
[CI $j cluster_state] eq $state
|
||||||
|
} else {
|
||||||
|
fail "Cluster node $j cluster_state:[CI $j cluster_state]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default slot allocation for clusters, each master has a continuous block
|
||||||
|
# and approximately equal number of slots.
|
||||||
|
proc continuous_slot_allocation {masters} {
|
||||||
|
set avg [expr double(16384) / $masters]
|
||||||
|
set slot_start 0
|
||||||
|
for {set j 0} {$j < $masters} {incr j} {
|
||||||
|
set slot_end [expr int(ceil(($j + 1) * $avg) - 1)]
|
||||||
|
R $j cluster addslotsrange $slot_start $slot_end
|
||||||
|
set slot_start [expr $slot_end + 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Setup method to be executed to configure the cluster before the
|
||||||
|
# tests run.
|
||||||
|
proc cluster_setup {masters node_count slot_allocator code} {
|
||||||
|
# Have all nodes meet
|
||||||
|
for {set i 1} {$i < $node_count} {incr i} {
|
||||||
|
R 0 CLUSTER MEET [srv -$i host] [srv -$i port]
|
||||||
|
}
|
||||||
|
|
||||||
|
$slot_allocator $masters
|
||||||
|
|
||||||
|
wait_for_cluster_propagation
|
||||||
|
|
||||||
|
# Setup master/replica relationships
|
||||||
|
for {set i 0} {$i < $masters} {incr i} {
|
||||||
|
set nodeid [R $i CLUSTER MYID]
|
||||||
|
for {set j [expr $i + $masters]} {$j < $node_count} {incr j $masters} {
|
||||||
|
R $j CLUSTER REPLICATE $nodeid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_cluster_propagation
|
||||||
|
wait_for_cluster_state "ok"
|
||||||
|
|
||||||
|
uplevel 1 $code
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start a cluster with the given number of masters and replicas. Replicas
|
||||||
|
# will be allocated to masters by round robin.
|
||||||
|
proc start_cluster {masters replicas options code {slot_allocator continuous_slot_allocation}} {
|
||||||
|
set node_count [expr $masters + $replicas]
|
||||||
|
|
||||||
|
# Set the final code to be the tests + cluster setup
|
||||||
|
set code [list cluster_setup $masters $node_count $slot_allocator $code]
|
||||||
|
|
||||||
|
# Configure the starting of multiple servers. Set cluster node timeout
|
||||||
|
# aggressively since many tests depend on ping/pong messages.
|
||||||
|
set cluster_options [list overrides [list cluster-enabled yes cluster-node-timeout 500]]
|
||||||
|
set options [concat $cluster_options $options]
|
||||||
|
|
||||||
|
# Cluster mode only supports a single database, so before executing the tests
|
||||||
|
# it needs to be configured correctly and needs to be reset after the tests.
|
||||||
|
set old_singledb $::singledb
|
||||||
|
set ::singledb 1
|
||||||
|
start_multiple_servers $node_count $options $code
|
||||||
|
set ::singledb $old_singledb
|
||||||
|
}
|
@ -253,12 +253,15 @@ proc tags {tags code} {
|
|||||||
|
|
||||||
# Write the configuration in the dictionary 'config' in the specified
|
# Write the configuration in the dictionary 'config' in the specified
|
||||||
# file name.
|
# file name.
|
||||||
proc create_server_config_file {filename config} {
|
proc create_server_config_file {filename config config_lines} {
|
||||||
set fp [open $filename w+]
|
set fp [open $filename w+]
|
||||||
foreach directive [dict keys $config] {
|
foreach directive [dict keys $config] {
|
||||||
puts -nonewline $fp "$directive "
|
puts -nonewline $fp "$directive "
|
||||||
puts $fp [dict get $config $directive]
|
puts $fp [dict get $config $directive]
|
||||||
}
|
}
|
||||||
|
foreach {config_line_directive config_line_args} $config_lines {
|
||||||
|
puts $fp "$config_line_directive $config_line_args"
|
||||||
|
}
|
||||||
close $fp
|
close $fp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,6 +409,7 @@ proc start_server {options {code undefined}} {
|
|||||||
set tags {}
|
set tags {}
|
||||||
set args {}
|
set args {}
|
||||||
set keep_persistence false
|
set keep_persistence false
|
||||||
|
set config_lines {}
|
||||||
|
|
||||||
# parse options
|
# parse options
|
||||||
foreach {option value} $options {
|
foreach {option value} $options {
|
||||||
@ -416,6 +420,9 @@ proc start_server {options {code undefined}} {
|
|||||||
"overrides" {
|
"overrides" {
|
||||||
set overrides $value
|
set overrides $value
|
||||||
}
|
}
|
||||||
|
"config_lines" {
|
||||||
|
set config_lines $value
|
||||||
|
}
|
||||||
"args" {
|
"args" {
|
||||||
set args $value
|
set args $value
|
||||||
}
|
}
|
||||||
@ -503,7 +510,7 @@ proc start_server {options {code undefined}} {
|
|||||||
|
|
||||||
# write new configuration to temporary file
|
# write new configuration to temporary file
|
||||||
set config_file [tmpfile redis.conf]
|
set config_file [tmpfile redis.conf]
|
||||||
create_server_config_file $config_file $config
|
create_server_config_file $config_file $config $config_lines
|
||||||
|
|
||||||
set stdout [format "%s/%s" [dict get $config "dir"] "stdout"]
|
set stdout [format "%s/%s" [dict get $config "dir"] "stdout"]
|
||||||
set stderr [format "%s/%s" [dict get $config "dir"] "stderr"]
|
set stderr [format "%s/%s" [dict get $config "dir"] "stderr"]
|
||||||
@ -544,7 +551,7 @@ proc start_server {options {code undefined}} {
|
|||||||
} else {
|
} else {
|
||||||
dict set config port $port
|
dict set config port $port
|
||||||
}
|
}
|
||||||
create_server_config_file $config_file $config
|
create_server_config_file $config_file $config $config_lines
|
||||||
|
|
||||||
# Truncate log so wait_server_started will not be looking at
|
# Truncate log so wait_server_started will not be looking at
|
||||||
# output of the failed server.
|
# output of the failed server.
|
||||||
|
@ -77,12 +77,6 @@ proc getInfoProperty {infostr property} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc cluster_info {r field} {
|
|
||||||
if {[regexp "^$field:(.*?)\r\n" [$r cluster info] _ value]} {
|
|
||||||
set _ $value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Return value for INFO property
|
# Return value for INFO property
|
||||||
proc status {r property} {
|
proc status {r property} {
|
||||||
set _ [getInfoProperty [{*}$r info] $property]
|
set _ [getInfoProperty [{*}$r info] $property]
|
||||||
|
@ -8,6 +8,7 @@ set tcl_precision 17
|
|||||||
source tests/support/redis.tcl
|
source tests/support/redis.tcl
|
||||||
source tests/support/aofmanifest.tcl
|
source tests/support/aofmanifest.tcl
|
||||||
source tests/support/server.tcl
|
source tests/support/server.tcl
|
||||||
|
source tests/support/cluster_helper.tcl
|
||||||
source tests/support/tmpfile.tcl
|
source tests/support/tmpfile.tcl
|
||||||
source tests/support/test.tcl
|
source tests/support/test.tcl
|
||||||
source tests/support/util.tcl
|
source tests/support/util.tcl
|
||||||
@ -90,11 +91,13 @@ set ::all_tests {
|
|||||||
unit/oom-score-adj
|
unit/oom-score-adj
|
||||||
unit/shutdown
|
unit/shutdown
|
||||||
unit/networking
|
unit/networking
|
||||||
unit/cluster
|
|
||||||
unit/client-eviction
|
unit/client-eviction
|
||||||
unit/violations
|
unit/violations
|
||||||
unit/replybufsize
|
unit/replybufsize
|
||||||
unit/cluster-scripting
|
unit/cluster/cli
|
||||||
|
unit/cluster/scripting
|
||||||
|
unit/cluster/hostnames
|
||||||
|
unit/cluster/multi-slot-operations
|
||||||
}
|
}
|
||||||
# Index to the next test to run in the ::all_tests list.
|
# Index to the next test to run in the ::all_tests list.
|
||||||
set ::next_test 0
|
set ::next_test 0
|
||||||
@ -197,6 +200,13 @@ proc r {args} {
|
|||||||
[srv $level "client"] {*}$args
|
[srv $level "client"] {*}$args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Provide easy access to a client for an inner server. Requires a positive
|
||||||
|
# index, unlike r which uses an optional negative index.
|
||||||
|
proc R {n args} {
|
||||||
|
set level [expr -1*$n]
|
||||||
|
[srv $level "client"] {*}$args
|
||||||
|
}
|
||||||
|
|
||||||
proc reconnect {args} {
|
proc reconnect {args} {
|
||||||
set level [lindex $args 0]
|
set level [lindex $args 0]
|
||||||
if {[string length $level] == 0 || ![string is integer $level]} {
|
if {[string length $level] == 0 || ![string is integer $level]} {
|
||||||
@ -275,14 +285,9 @@ proc s {args} {
|
|||||||
status [srv $level "client"] [lindex $args 0]
|
status [srv $level "client"] [lindex $args 0]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Provide easy access to CLUSTER INFO properties. Same semantic as "proc s".
|
# Get the specified field from the givens instances cluster info output.
|
||||||
proc csi {args} {
|
proc CI {index field} {
|
||||||
set level 0
|
getInfoProperty [R $index cluster info] $field
|
||||||
if {[string is integer [lindex $args 0]]} {
|
|
||||||
set level [lindex $args 0]
|
|
||||||
set args [lrange $args 1 end]
|
|
||||||
}
|
|
||||||
cluster_info [srv $level "client"] [lindex $args 0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test wrapped into run_solo are sent back from the client to the
|
# Test wrapped into run_solo are sent back from the client to the
|
||||||
|
@ -2,20 +2,6 @@
|
|||||||
|
|
||||||
source tests/support/cli.tcl
|
source tests/support/cli.tcl
|
||||||
|
|
||||||
proc cluster_info {r field} {
|
|
||||||
set _ [getInfoProperty [$r cluster info] $field]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Provide easy access to CLUSTER INFO properties. Same semantic as "proc s".
|
|
||||||
proc csi {args} {
|
|
||||||
set level 0
|
|
||||||
if {[string is integer [lindex $args 0]]} {
|
|
||||||
set level [lindex $args 0]
|
|
||||||
set args [lrange $args 1 end]
|
|
||||||
}
|
|
||||||
cluster_info [srv $level "client"] [lindex $args 0]
|
|
||||||
}
|
|
||||||
|
|
||||||
# make sure the test infra won't use SELECT
|
# make sure the test infra won't use SELECT
|
||||||
set old_singledb $::singledb
|
set old_singledb $::singledb
|
||||||
set ::singledb 1
|
set ::singledb 1
|
||||||
@ -40,9 +26,9 @@ start_multiple_servers 3 [list overrides $base_conf] {
|
|||||||
127.0.0.1:[srv -2 port]
|
127.0.0.1:[srv -2 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok}
|
[CI 2 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -127,8 +113,8 @@ start_multiple_servers 3 [list overrides $base_conf] {
|
|||||||
exec kill -SIGSTOP $node3_pid
|
exec kill -SIGSTOP $node3_pid
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {fail} &&
|
[CI 0 cluster_state] eq {fail} &&
|
||||||
[csi -1 cluster_state] eq {fail}
|
[CI 1 cluster_state] eq {fail}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't fail"
|
fail "Cluster doesn't fail"
|
||||||
}
|
}
|
||||||
@ -162,9 +148,9 @@ start_multiple_servers 5 [list overrides $base_conf] {
|
|||||||
|
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok}
|
[CI 2 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -181,10 +167,10 @@ start_multiple_servers 5 [list overrides $base_conf] {
|
|||||||
127.0.0.1:[srv 0 port]
|
127.0.0.1:[srv 0 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok}
|
[CI 3 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -222,9 +208,9 @@ test {Migrate the last slot away from a node using redis-cli} {
|
|||||||
127.0.0.1:[srv -2 port]
|
127.0.0.1:[srv -2 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok}
|
[CI 2 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -239,10 +225,10 @@ test {Migrate the last slot away from a node using redis-cli} {
|
|||||||
127.0.0.1:[srv 0 port]
|
127.0.0.1:[srv 0 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok}
|
[CI 3 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -273,10 +259,10 @@ test {Migrate the last slot away from a node using redis-cli} {
|
|||||||
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -1 port]}] == 0 &&
|
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -1 port]}] == 0 &&
|
||||||
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -2 port]}] == 0 &&
|
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -2 port]}] == 0 &&
|
||||||
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -3 port]}] == 0 &&
|
[catch {exec src/redis-cli --cluster check 127.0.0.1:[srv -3 port]}] == 0 &&
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok}
|
[CI 3 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -291,10 +277,10 @@ test {Migrate the last slot away from a node using redis-cli} {
|
|||||||
# The empty node will become a replica of the new owner before the
|
# The empty node will become a replica of the new owner before the
|
||||||
# `MOVED` check, so let's wait for the cluster to become stable.
|
# `MOVED` check, so let's wait for the cluster to become stable.
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok}
|
[CI 3 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -336,17 +322,17 @@ start_server [list overrides [list cluster-enabled yes cluster-node-timeout 1 cl
|
|||||||
127.0.0.1:[srv -2 port]
|
127.0.0.1:[srv -2 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok}
|
[CI 2 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Make sure each node can meet other nodes
|
# Make sure each node can meet other nodes
|
||||||
assert_equal 3 [csi 0 cluster_known_nodes]
|
assert_equal 3 [CI 0 cluster_known_nodes]
|
||||||
assert_equal 3 [csi -1 cluster_known_nodes]
|
assert_equal 3 [CI 1 cluster_known_nodes]
|
||||||
assert_equal 3 [csi -2 cluster_known_nodes]
|
assert_equal 3 [CI 2 cluster_known_nodes]
|
||||||
}
|
}
|
||||||
|
|
||||||
test {redis-cli --cluster add-node with cluster-port} {
|
test {redis-cli --cluster add-node with cluster-port} {
|
||||||
@ -356,10 +342,10 @@ start_server [list overrides [list cluster-enabled yes cluster-node-timeout 1 cl
|
|||||||
127.0.0.1:[srv 0 port]
|
127.0.0.1:[srv 0 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok}
|
[CI 3 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
@ -370,21 +356,21 @@ start_server [list overrides [list cluster-enabled yes cluster-node-timeout 1 cl
|
|||||||
127.0.0.1:[srv 0 port]
|
127.0.0.1:[srv 0 port]
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
[CI 0 cluster_state] eq {ok} &&
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
[CI 1 cluster_state] eq {ok} &&
|
||||||
[csi -2 cluster_state] eq {ok} &&
|
[CI 2 cluster_state] eq {ok} &&
|
||||||
[csi -3 cluster_state] eq {ok} &&
|
[CI 3 cluster_state] eq {ok} &&
|
||||||
[csi -4 cluster_state] eq {ok}
|
[CI 4 cluster_state] eq {ok}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't stabilize"
|
fail "Cluster doesn't stabilize"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Make sure each node can meet other nodes
|
# Make sure each node can meet other nodes
|
||||||
assert_equal 5 [csi 0 cluster_known_nodes]
|
assert_equal 5 [CI 0 cluster_known_nodes]
|
||||||
assert_equal 5 [csi -1 cluster_known_nodes]
|
assert_equal 5 [CI 1 cluster_known_nodes]
|
||||||
assert_equal 5 [csi -2 cluster_known_nodes]
|
assert_equal 5 [CI 2 cluster_known_nodes]
|
||||||
assert_equal 5 [csi -3 cluster_known_nodes]
|
assert_equal 5 [CI 3 cluster_known_nodes]
|
||||||
assert_equal 5 [csi -4 cluster_known_nodes]
|
assert_equal 5 [CI 4 cluster_known_nodes]
|
||||||
}
|
}
|
||||||
# stop 5 servers
|
# stop 5 servers
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
source "../tests/includes/init-tests.tcl"
|
|
||||||
|
|
||||||
# Isolate a node from the cluster and give it a new nodeid
|
# Isolate a node from the cluster and give it a new nodeid
|
||||||
proc isolate_node {id} {
|
proc isolate_node {id} {
|
||||||
set node_id [R $id CLUSTER MYID]
|
set node_id [R $id CLUSTER MYID]
|
||||||
R 6 CLUSTER RESET HARD
|
R $id CLUSTER RESET HARD
|
||||||
for {set j 0} {$j < 20} {incr j} {
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
if { $j eq $id } {
|
if { $j eq $id } {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -12,21 +10,29 @@ proc isolate_node {id} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if cluster's view of hostnames is consistent
|
||||||
|
proc are_hostnames_propagated {match_string} {
|
||||||
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
|
set cfg [R $j cluster slots]
|
||||||
|
foreach node $cfg {
|
||||||
|
for {set i 2} {$i < [llength $node]} {incr i} {
|
||||||
|
if {! [string match $match_string [lindex [lindex [lindex $node $i] 3] 1]] } {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
proc get_slot_field {slot_output shard_id node_id attrib_id} {
|
proc get_slot_field {slot_output shard_id node_id attrib_id} {
|
||||||
return [lindex [lindex [lindex $slot_output $shard_id] $node_id] $attrib_id]
|
return [lindex [lindex [lindex $slot_output $shard_id] $node_id] $attrib_id]
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Create a 6 nodes cluster" {
|
# Start a cluster with 3 masters and 4 replicas.
|
||||||
cluster_create_with_continuous_slots 3 3
|
start_cluster 3 4 {tags {external:skip cluster}} {
|
||||||
}
|
|
||||||
|
|
||||||
test "Cluster should start ok" {
|
|
||||||
assert_cluster_state ok
|
|
||||||
wait_for_cluster_propagation
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Set cluster hostnames and verify they are propagated" {
|
test "Set cluster hostnames and verify they are propagated" {
|
||||||
for {set j 0} {$j < $::cluster_master_nodes + $::cluster_replica_nodes} {incr j} {
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
R $j config set cluster-announce-hostname "host-$j.com"
|
R $j config set cluster-announce-hostname "host-$j.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +47,7 @@ test "Set cluster hostnames and verify they are propagated" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "Update hostnames and make sure they are all eventually propagated" {
|
test "Update hostnames and make sure they are all eventually propagated" {
|
||||||
for {set j 0} {$j < $::cluster_master_nodes + $::cluster_replica_nodes} {incr j} {
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
R $j config set cluster-announce-hostname "host-updated-$j.com"
|
R $j config set cluster-announce-hostname "host-updated-$j.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +62,7 @@ test "Update hostnames and make sure they are all eventually propagated" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "Remove hostnames and make sure they are all eventually propagated" {
|
test "Remove hostnames and make sure they are all eventually propagated" {
|
||||||
for {set j 0} {$j < $::cluster_master_nodes + $::cluster_replica_nodes} {incr j} {
|
for {set j 0} {$j < [llength $::servers]} {incr j} {
|
||||||
R $j config set cluster-announce-hostname ""
|
R $j config set cluster-announce-hostname ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +142,7 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne
|
|||||||
# Have everyone forget node 6 and isolate it from the cluster.
|
# Have everyone forget node 6 and isolate it from the cluster.
|
||||||
isolate_node 6
|
isolate_node 6
|
||||||
|
|
||||||
# Set hostnames for the primaries, now that the node is isolated
|
# Set hostnames for the masters, now that the node is isolated
|
||||||
R 0 config set cluster-announce-hostname "shard-1.com"
|
R 0 config set cluster-announce-hostname "shard-1.com"
|
||||||
R 1 config set cluster-announce-hostname "shard-2.com"
|
R 1 config set cluster-announce-hostname "shard-2.com"
|
||||||
R 2 config set cluster-announce-hostname "shard-3.com"
|
R 2 config set cluster-announce-hostname "shard-3.com"
|
||||||
@ -149,14 +155,14 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne
|
|||||||
R 6 DEBUG DROP-CLUSTER-PACKET-FILTER 0
|
R 6 DEBUG DROP-CLUSTER-PACKET-FILTER 0
|
||||||
|
|
||||||
# Have a replica meet the isolated node
|
# Have a replica meet the isolated node
|
||||||
R 3 cluster meet 127.0.0.1 [get_instance_attrib redis 6 port]
|
R 3 cluster meet 127.0.0.1 [srv -6 port]
|
||||||
|
|
||||||
# Wait for the isolated node to learn about the rest of the cluster,
|
# Wait for the isolated node to learn about the rest of the cluster,
|
||||||
# which correspond to a single entry in cluster nodes. Note this
|
# which correspond to a single entry in cluster nodes. Note this
|
||||||
# doesn't mean the isolated node has successfully contacted each
|
# doesn't mean the isolated node has successfully contacted each
|
||||||
# node.
|
# node.
|
||||||
wait_for_condition 50 100 {
|
wait_for_condition 50 100 {
|
||||||
[llength [split [R 6 CLUSTER NODES] "\n"]] eq 21
|
[llength [split [R 6 CLUSTER NODES] "\n"]] eq [expr [llength $::servers] + 1]
|
||||||
} else {
|
} else {
|
||||||
fail "Isolated node didn't learn about the rest of the cluster *"
|
fail "Isolated node didn't learn about the rest of the cluster *"
|
||||||
}
|
}
|
||||||
@ -173,10 +179,10 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne
|
|||||||
assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "shard-2.com"
|
assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "shard-2.com"
|
||||||
assert_equal [lindex [get_slot_field $slot_result 1 2 3] 1] "shard-3.com"
|
assert_equal [lindex [get_slot_field $slot_result 1 2 3] 1] "shard-3.com"
|
||||||
|
|
||||||
# Also make sure we know about the isolated primary, we
|
# Also make sure we know about the isolated master, we
|
||||||
# just can't reach it.
|
# just can't reach it.
|
||||||
set primary_id [R 0 CLUSTER MYID]
|
set master_id [R 0 CLUSTER MYID]
|
||||||
assert_match "*$primary_id*" [R 6 CLUSTER NODES]
|
assert_match "*$master_id*" [R 6 CLUSTER NODES]
|
||||||
|
|
||||||
# Stop dropping cluster packets, and make sure everything
|
# Stop dropping cluster packets, and make sure everything
|
||||||
# stabilizes
|
# stabilizes
|
||||||
@ -199,8 +205,7 @@ test "Test restart will keep hostname information" {
|
|||||||
R 0 config set cluster-announce-hostname "restart-1.com"
|
R 0 config set cluster-announce-hostname "restart-1.com"
|
||||||
# Store the hostname in the config
|
# Store the hostname in the config
|
||||||
R 0 config rewrite
|
R 0 config rewrite
|
||||||
kill_instance redis 0
|
restart_server 0 true false
|
||||||
restart_instance redis 0
|
|
||||||
set slot_result [R 0 CLUSTER SLOTS]
|
set slot_result [R 0 CLUSTER SLOTS]
|
||||||
assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "restart-1.com"
|
assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "restart-1.com"
|
||||||
|
|
||||||
@ -217,3 +222,4 @@ test "Test hostname validation" {
|
|||||||
# Note this isn't a valid hostname, but it passes our internal validation
|
# Note this isn't a valid hostname, but it passes our internal validation
|
||||||
R 0 config set cluster-announce-hostname "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
|
R 0 config set cluster-announce-hostname "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-."
|
||||||
}
|
}
|
||||||
|
}
|
@ -1,7 +1,4 @@
|
|||||||
# Check the multiple slot add and remove commands
|
# This test uses a custom slot allocation for testing
|
||||||
|
|
||||||
source "../tests/includes/init-tests.tcl"
|
|
||||||
|
|
||||||
proc cluster_allocate_with_continuous_slots_local {n} {
|
proc cluster_allocate_with_continuous_slots_local {n} {
|
||||||
R 0 cluster ADDSLOTSRANGE 0 3276
|
R 0 cluster ADDSLOTSRANGE 0 3276
|
||||||
R 1 cluster ADDSLOTSRANGE 3277 6552
|
R 1 cluster ADDSLOTSRANGE 3277 6552
|
||||||
@ -10,28 +7,13 @@ proc cluster_allocate_with_continuous_slots_local {n} {
|
|||||||
R 4 cluster ADDSLOTSRANGE 13105 16383
|
R 4 cluster ADDSLOTSRANGE 13105 16383
|
||||||
}
|
}
|
||||||
|
|
||||||
proc cluster_create_with_continuous_slots_local {masters slaves} {
|
start_cluster 5 0 {tags {external:skip cluster}} {
|
||||||
cluster_allocate_with_continuous_slots_local $masters
|
|
||||||
if {$slaves} {
|
|
||||||
cluster_allocate_slaves $masters $slaves
|
|
||||||
}
|
|
||||||
assert_cluster_state ok
|
|
||||||
}
|
|
||||||
|
|
||||||
|
set master1 [srv 0 "client"]
|
||||||
test "Create a 5 nodes cluster" {
|
set master2 [srv -1 "client"]
|
||||||
cluster_create_with_continuous_slots_local 5 5
|
set master3 [srv -2 "client"]
|
||||||
}
|
set master4 [srv -3 "client"]
|
||||||
|
set master5 [srv -4 "client"]
|
||||||
test "Cluster should start ok" {
|
|
||||||
assert_cluster_state ok
|
|
||||||
}
|
|
||||||
|
|
||||||
set master1 [Rn 0]
|
|
||||||
set master2 [Rn 1]
|
|
||||||
set master3 [Rn 2]
|
|
||||||
set master4 [Rn 3]
|
|
||||||
set master5 [Rn 4]
|
|
||||||
|
|
||||||
test "Continuous slots distribution" {
|
test "Continuous slots distribution" {
|
||||||
assert_match "* 0-3276*" [$master1 CLUSTER NODES]
|
assert_match "* 0-3276*" [$master1 CLUSTER NODES]
|
||||||
@ -113,3 +95,4 @@ test "DELSLOTSRANGE command with several boundary conditions test suite" {
|
|||||||
assert_match "* 9829-11000 12001-12100 12201-13104*" [$master4 CLUSTER NODES]
|
assert_match "* 9829-11000 12001-12100 12201-13104*" [$master4 CLUSTER NODES]
|
||||||
assert_match "*9829 11000*12001 12100*12201 13104*" [$master4 CLUSTER SLOTS]
|
assert_match "*9829 11000*12001 12100*12201 13104*" [$master4 CLUSTER SLOTS]
|
||||||
}
|
}
|
||||||
|
} cluster_allocate_with_continuous_slots_local
|
@ -1,14 +1,4 @@
|
|||||||
# make sure the test infra won't use SELECT
|
start_cluster 1 0 {tags {external:skip cluster}} {
|
||||||
set old_singledb $::singledb
|
|
||||||
set ::singledb 1
|
|
||||||
|
|
||||||
start_server {overrides {cluster-enabled yes} tags {external:skip cluster}} {
|
|
||||||
r 0 cluster addslotsrange 0 16383
|
|
||||||
wait_for_condition 50 100 {
|
|
||||||
[csi 0 cluster_state] eq "ok"
|
|
||||||
} else {
|
|
||||||
fail "Cluster never became 'ok'"
|
|
||||||
}
|
|
||||||
|
|
||||||
test {Eval scripts with shebangs and functions default to no cross slots} {
|
test {Eval scripts with shebangs and functions default to no cross slots} {
|
||||||
# Test that scripts with shebang block cross slot operations
|
# Test that scripts with shebang block cross slot operations
|
||||||
@ -59,6 +49,22 @@ start_server {overrides {cluster-enabled yes} tags {external:skip cluster}} {
|
|||||||
return 'OK'
|
return 'OK'
|
||||||
} 1 bar}
|
} 1 bar}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
set ::singledb $old_singledb
|
test "Function no-cluster flag" {
|
||||||
|
R 0 function load {#!lua name=test
|
||||||
|
redis.register_function{function_name='f1', callback=function() return 'hello' end, flags={'no-cluster'}}
|
||||||
|
}
|
||||||
|
catch {R 0 fcall f1 0} e
|
||||||
|
assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
|
||||||
|
}
|
||||||
|
|
||||||
|
test "Script no-cluster flag" {
|
||||||
|
catch {
|
||||||
|
R 0 eval {#!lua flags=no-cluster
|
||||||
|
return 1
|
||||||
|
} 0
|
||||||
|
} e
|
||||||
|
|
||||||
|
assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
|
||||||
|
}
|
||||||
|
}
|
@ -1,59 +1,27 @@
|
|||||||
# Primitive tests on cluster-enabled redis with modules using redis-cli
|
# Primitive tests on cluster-enabled redis with modules
|
||||||
|
|
||||||
source tests/support/cli.tcl
|
source tests/support/cli.tcl
|
||||||
|
|
||||||
set testmodule [file normalize tests/modules/blockonkeys.so]
|
|
||||||
set testmodule_nokey [file normalize tests/modules/blockonbackground.so]
|
|
||||||
set testmodule_blockedclient [file normalize tests/modules/blockedclient.so]
|
|
||||||
|
|
||||||
# make sure the test infra won't use SELECT
|
|
||||||
set old_singledb $::singledb
|
|
||||||
set ::singledb 1
|
|
||||||
|
|
||||||
# cluster creation is complicated with TLS, and the current tests don't really need that coverage
|
# cluster creation is complicated with TLS, and the current tests don't really need that coverage
|
||||||
tags {tls:skip external:skip cluster modules} {
|
tags {tls:skip external:skip cluster modules} {
|
||||||
|
|
||||||
# start three servers
|
set testmodule_nokey [file normalize tests/modules/blockonbackground.so]
|
||||||
set base_conf [list cluster-enabled yes cluster-node-timeout 1 loadmodule $testmodule]
|
set testmodule_blockedclient [file normalize tests/modules/blockedclient.so]
|
||||||
start_server [list overrides $base_conf] {
|
set testmodule [file normalize tests/modules/blockonkeys.so]
|
||||||
start_server [list overrides $base_conf] {
|
|
||||||
start_server [list overrides $base_conf] {
|
set modules [list loadmodule $testmodule loadmodule $testmodule_nokey loadmodule $testmodule_blockedclient]
|
||||||
|
start_cluster 3 0 [list config_lines $modules] {
|
||||||
|
|
||||||
set node1 [srv 0 client]
|
set node1 [srv 0 client]
|
||||||
set node2 [srv -1 client]
|
set node2 [srv -1 client]
|
||||||
set node3 [srv -2 client]
|
set node3 [srv -2 client]
|
||||||
set node3_pid [srv -2 pid]
|
set node3_pid [srv -2 pid]
|
||||||
|
|
||||||
# the "overrides" mechanism can only support one "loadmodule" directive
|
|
||||||
$node1 module load $testmodule_nokey
|
|
||||||
$node2 module load $testmodule_nokey
|
|
||||||
$node3 module load $testmodule_nokey
|
|
||||||
|
|
||||||
$node1 module load $testmodule_blockedclient
|
|
||||||
$node2 module load $testmodule_blockedclient
|
|
||||||
$node3 module load $testmodule_blockedclient
|
|
||||||
|
|
||||||
test {Create 3 node cluster} {
|
|
||||||
exec src/redis-cli --cluster-yes --cluster create \
|
|
||||||
127.0.0.1:[srv 0 port] \
|
|
||||||
127.0.0.1:[srv -1 port] \
|
|
||||||
127.0.0.1:[srv -2 port]
|
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
|
||||||
[csi 0 cluster_state] eq {ok} &&
|
|
||||||
[csi -1 cluster_state] eq {ok} &&
|
|
||||||
[csi -2 cluster_state] eq {ok}
|
|
||||||
} else {
|
|
||||||
fail "Cluster doesn't stabilize"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Run blocking command (blocked on key) on cluster node3" {
|
test "Run blocking command (blocked on key) on cluster node3" {
|
||||||
# key9184688 is mapped to slot 10923 (first slot of node 3)
|
# key9184688 is mapped to slot 10923 (first slot of node 3)
|
||||||
set node3_rd [redis_deferring_client -2]
|
set node3_rd [redis_deferring_client -2]
|
||||||
$node3_rd fsl.bpop key9184688 0
|
$node3_rd fsl.bpop key9184688 0
|
||||||
$node3_rd flush
|
$node3_rd flush
|
||||||
|
|
||||||
wait_for_condition 50 100 {
|
wait_for_condition 50 100 {
|
||||||
[s -2 blocked_clients] eq {1}
|
[s -2 blocked_clients] eq {1}
|
||||||
} else {
|
} else {
|
||||||
@ -164,8 +132,8 @@ start_server [list overrides $base_conf] {
|
|||||||
exec kill -SIGSTOP $node3_pid
|
exec kill -SIGSTOP $node3_pid
|
||||||
|
|
||||||
wait_for_condition 1000 50 {
|
wait_for_condition 1000 50 {
|
||||||
[csi 0 cluster_state] eq {fail} &&
|
[CI 0 cluster_state] eq {fail} &&
|
||||||
[csi -1 cluster_state] eq {fail}
|
[CI 1 cluster_state] eq {fail}
|
||||||
} else {
|
} else {
|
||||||
fail "Cluster doesn't fail"
|
fail "Cluster doesn't fail"
|
||||||
}
|
}
|
||||||
@ -190,12 +158,5 @@ start_server [list overrides $base_conf] {
|
|||||||
exec kill -SIGCONT $node3_pid
|
exec kill -SIGCONT $node3_pid
|
||||||
$node1_rd close
|
$node1_rd close
|
||||||
$node2_rd close
|
$node2_rd close
|
||||||
|
|
||||||
# stop three servers
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} ;# tags
|
|
||||||
|
|
||||||
set ::singledb $old_singledb
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user