summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/unit/cluster/slot-stats.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/unit/cluster/slot-stats.tcl')
-rw-r--r--examples/redis-unstable/tests/unit/cluster/slot-stats.tcl1169
1 files changed, 0 insertions, 1169 deletions
diff --git a/examples/redis-unstable/tests/unit/cluster/slot-stats.tcl b/examples/redis-unstable/tests/unit/cluster/slot-stats.tcl
deleted file mode 100644
index 1123731..0000000
--- a/examples/redis-unstable/tests/unit/cluster/slot-stats.tcl
+++ /dev/null
@@ -1,1169 +0,0 @@
-#
-# Copyright (c) 2009-Present, Redis Ltd.
-# All rights reserved.
-#
-# Copyright (c) 2024-present, Valkey contributors.
-# All rights reserved.
-#
-# Licensed under your choice of (a) the Redis Source Available License 2.0
-# (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
-# GNU Affero General Public License v3 (AGPLv3).
-#
-# Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information.
-#
-
-# Integration tests for CLUSTER SLOT-STATS command.
-
-# -----------------------------------------------------------------------------
-# Helper functions for CLUSTER SLOT-STATS test cases.
-# -----------------------------------------------------------------------------
-
-# Converts array RESP response into a dict.
-# This is useful for many test cases, where unnecessary nesting is removed.
-proc convert_array_into_dict {slot_stats} {
- set res [dict create]
- foreach slot_stat $slot_stats {
- # slot_stat is an array of size 2, where 0th index represents (int) slot,
- # and 1st index represents (map) usage statistics.
- dict set res [lindex $slot_stat 0] [lindex $slot_stat 1]
- }
- return $res
-}
-
-proc get_cmdstat_usec {cmd r} {
- set cmdstatline [cmdrstat $cmd r]
- regexp "usec=(.*?),usec_per_call=(.*?),rejected_calls=0,failed_calls=0" $cmdstatline -> usec _
- return $usec
-}
-
-proc initialize_expected_slots_dict {} {
- set expected_slots [dict create]
- for {set i 0} {$i < 16384} {incr i 1} {
- dict set expected_slots $i 0
- }
- return $expected_slots
-}
-
-proc initialize_expected_slots_dict_with_range {start_slot end_slot} {
- assert {$start_slot <= $end_slot}
- set expected_slots [dict create]
- for {set i $start_slot} {$i <= $end_slot} {incr i 1} {
- dict set expected_slots $i 0
- }
- return $expected_slots
-}
-
-proc assert_empty_slot_stats {slot_stats metrics_to_assert} {
- set slot_stats [convert_array_into_dict $slot_stats]
- dict for {slot stats} $slot_stats {
- foreach metric_name $metrics_to_assert {
- set metric_value [dict get $stats $metric_name]
- assert {$metric_value == 0}
- }
- }
-}
-
-proc assert_empty_slot_stats_with_exception {slot_stats exception_slots metrics_to_assert} {
- set slot_stats [convert_array_into_dict $slot_stats]
- dict for {slot stats} $exception_slots {
- assert {[dict exists $slot_stats $slot]} ;# slot_stats must contain the expected slots.
- }
- dict for {slot stats} $slot_stats {
- if {[dict exists $exception_slots $slot]} {
- foreach metric_name $metrics_to_assert {
- set metric_value [dict get $exception_slots $slot $metric_name]
- assert {[dict get $stats $metric_name] == $metric_value}
- }
- } else {
- dict for {metric value} $stats {
- assert {$value == 0}
- }
- }
- }
-}
-
-proc assert_equal_slot_stats {slot_stats_1 slot_stats_2 deterministic_metrics non_deterministic_metrics} {
- set slot_stats_1 [convert_array_into_dict $slot_stats_1]
- set slot_stats_2 [convert_array_into_dict $slot_stats_2]
- assert {[dict size $slot_stats_1] == [dict size $slot_stats_2]}
-
- dict for {slot stats_1} $slot_stats_1 {
- assert {[dict exists $slot_stats_2 $slot]}
- set stats_2 [dict get $slot_stats_2 $slot]
-
- # For deterministic metrics, we assert their equality.
- foreach metric $deterministic_metrics {
- assert {[dict get $stats_1 $metric] == [dict get $stats_2 $metric]}
- }
- # For non-deterministic metrics, we assert their non-zeroness as a best-effort.
- foreach metric $non_deterministic_metrics {
- assert {([dict get $stats_1 $metric] == 0 && [dict get $stats_2 $metric] == 0) || \
- ([dict get $stats_1 $metric] != 0 && [dict get $stats_2 $metric] != 0)}
- }
- }
-}
-
-proc assert_all_slots_have_been_seen {expected_slots} {
- dict for {k v} $expected_slots {
- assert {$v == 1}
- }
-}
-
-proc assert_slot_visibility {slot_stats expected_slots} {
- set slot_stats [convert_array_into_dict $slot_stats]
- dict for {slot _} $slot_stats {
- assert {[dict exists $expected_slots $slot]}
- dict set expected_slots $slot 1
- }
-
- assert_all_slots_have_been_seen $expected_slots
-}
-
-proc assert_slot_stats_monotonic_order {slot_stats orderby is_desc} {
- # For Tcl dict, the order of iteration is the order in which the keys were inserted into the dictionary
- # Thus, the response ordering is preserved upon calling 'convert_array_into_dict()'.
- # Source: https://www.tcl.tk/man/tcl8.6.11/TclCmd/dict.htm
- set slot_stats [convert_array_into_dict $slot_stats]
- set prev_metric -1
- dict for {_ stats} $slot_stats {
- set curr_metric [dict get $stats $orderby]
- if {$prev_metric != -1} {
- if {$is_desc == 1} {
- assert {$prev_metric >= $curr_metric}
- } else {
- assert {$prev_metric <= $curr_metric}
- }
- }
- set prev_metric $curr_metric
- }
-}
-
-proc assert_slot_stats_monotonic_descent {slot_stats orderby} {
- assert_slot_stats_monotonic_order $slot_stats $orderby 1
-}
-
-proc assert_slot_stats_monotonic_ascent {slot_stats orderby} {
- assert_slot_stats_monotonic_order $slot_stats $orderby 0
-}
-
-proc wait_for_replica_key_exists {key key_count} {
- wait_for_condition 1000 50 {
- [R 1 exists $key] eq "$key_count"
- } else {
- fail "Test key was not replicated"
- }
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS cpu-usec metric correctness.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
-
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 cluster keyslot $key]
- set key_secondary "FOO2"
- set key_secondary_slot [R 0 cluster keyslot $key_secondary]
- set metrics_to_assert [list cpu-usec]
-
- test "CLUSTER SLOT-STATS cpu-usec reset upon CONFIG RESETSTAT." {
- R 0 SET $key VALUE
- R 0 DEL $key
- R 0 CONFIG RESETSTAT
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec reset upon slot migration." {
- R 0 SET $key VALUE
-
- R 0 CLUSTER DELSLOTS $key_slot
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
-
- R 0 CLUSTER ADDSLOTS $key_slot
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for non-slot specific commands." {
- R 0 INFO
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for slot specific commands." {
- R 0 SET $key VALUE
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set usec [get_cmdstat_usec set r]
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec $usec
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for blocking commands, unblocked on keyspace update." {
- # Blocking command with no timeout. Only keyspace update can unblock this client.
- set rd [redis_deferring_client]
- $rd BLPOP $key 0
- wait_for_blocked_clients_count 1
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- # When the client is blocked, no accumulation is made. This behaviour is identical to INFO COMMANDSTATS.
- assert_empty_slot_stats $slot_stats $metrics_to_assert
-
- # Unblocking command.
- R 0 LPUSH $key value
- wait_for_blocked_clients_count 0
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set lpush_usec [get_cmdstat_usec lpush r]
- set blpop_usec [get_cmdstat_usec blpop r]
-
- # Assert that both blocking and non-blocking command times have been accumulated.
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec [expr $lpush_usec + $blpop_usec]
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for blocking commands, unblocked on timeout." {
- # Blocking command with 0.5 seconds timeout.
- set rd [redis_deferring_client]
- $rd BLPOP $key 0.5
-
- # Confirm that the client is blocked, then unblocked within 1 second.
- wait_for_blocked_clients_count 1
- wait_for_blocked_clients_count 0
-
- # Assert that the blocking command time has been accumulated.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set blpop_usec [get_cmdstat_usec blpop r]
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec $blpop_usec
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for transactions." {
- set r1 [redis_client]
- $r1 MULTI
- $r1 SET $key value
- $r1 GET $key
-
- # CPU metric is not accumulated until EXEC is reached. This behaviour is identical to INFO COMMANDSTATS.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
-
- # Execute transaction, and assert that all nested command times have been accumulated.
- $r1 EXEC
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set exec_usec [get_cmdstat_usec exec r]
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec $exec_usec
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for lua-scripts, without cross-slot keys." {
- R 0 eval {#!lua
- redis.call('set', KEYS[1], 'bar') redis.call('get', KEYS[2])
- } 2 $key $key
-
- set eval_usec [get_cmdstat_usec eval r]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec $eval_usec
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for lua-scripts, with cross-slot keys." {
- R 0 eval {#!lua flags=allow-cross-slot-keys
- redis.call('set', KEYS[1], 'bar') redis.call('get', ARGV[1])
- } 1 $key $key_secondary
-
- # For cross-slot, we do not accumulate at all.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for functions, without cross-slot keys." {
- R 0 function load replace {#!lua name=f1
- redis.register_function{
- function_name='f1',
- callback=function(keys, args) redis.call('set', keys[1], '1') redis.call('get', keys[2]) end
- }
- }
- R 0 fcall f1 2 $key $key
-
- set fcall_usec [get_cmdstat_usec fcall r]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create cpu-usec $fcall_usec
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS cpu-usec for functions, with cross-slot keys." {
- R 0 function load replace {#!lua name=f1
- redis.register_function{
- function_name='f1',
- callback=function(keys, args) redis.call('set', keys[1], '1') redis.call('get', args[1]) end,
- flags={'allow-cross-slot-keys'}
- }
- }
- R 0 fcall f1 1 $key $key_secondary
-
- # For cross-slot, we do not accumulate at all.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS network-bytes-in.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
-
- # Define shared variables.
- set key "key"
- set key_slot [R 0 cluster keyslot $key]
- set metrics_to_assert [list network-bytes-in]
-
- test "CLUSTER SLOT-STATS network-bytes-in, multi bulk buffer processing." {
- # *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 33 bytes.
- R 0 SET $key value
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 33
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-in, in-line buffer processing." {
- set rd [redis_deferring_client]
- # SET key value\r\n --> 15 bytes.
- $rd write "SET $key value\r\n"
- $rd flush
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 15
- ]
- ]
-
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-in, blocking command." {
- set rd [redis_deferring_client]
- # *3\r\n$5\r\nblpop\r\n$3\r\nkey\r\n$1\r\n0\r\n --> 31 bytes.
- $rd BLPOP $key 0
- wait_for_blocked_clients_count 1
-
- # Slot-stats must be empty here, as the client is yet to be unblocked.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
-
- # *3\r\n$5\r\nlpush\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 35 bytes.
- R 0 LPUSH $key value
- wait_for_blocked_clients_count 0
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 66 ;# 31 + 35 bytes.
- ]
- ]
-
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-in, multi-exec transaction." {
- set r [redis_client]
- # *1\r\n$5\r\nmulti\r\n --> 15 bytes.
- $r MULTI
- # *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 33 bytes.
- assert {[$r SET $key value] eq {QUEUED}}
- # *1\r\n$4\r\nexec\r\n --> 14 bytes.
- assert {[$r EXEC] eq {OK}}
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 62 ;# 15 + 33 + 14 bytes.
- ]
- ]
-
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-in, non slot specific command." {
- R 0 INFO
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-in, pub/sub." {
- # PUB/SUB does not get accumulated at per-slot basis,
- # as it is cluster-wide and is not slot specific.
- set rd [redis_deferring_client]
- $rd subscribe channel
- R 0 publish channel message
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-}
-
-start_cluster 1 1 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
- set channel "channel"
- set key_slot [R 0 cluster keyslot $channel]
- set metrics_to_assert [list network-bytes-in]
-
- # Setup replication.
- assert {[s -1 role] eq {slave}}
- wait_for_condition 1000 50 {
- [s -1 master_link_status] eq {up}
- } else {
- fail "Instance #1 master link status is not up"
- }
- R 1 readonly
-
- test "CLUSTER SLOT-STATS network-bytes-in, sharded pub/sub." {
- set slot [R 0 cluster keyslot $channel]
- set primary [Rn 0]
- set replica [Rn 1]
- set replica_subcriber [redis_deferring_client -1]
- $replica_subcriber SSUBSCRIBE $channel
- # *2\r\n$10\r\nssubscribe\r\n$7\r\nchannel\r\n --> 34 bytes.
- $primary SPUBLISH $channel hello
- # *3\r\n$8\r\nspublish\r\n$7\r\nchannel\r\n$5\r\nhello\r\n --> 42 bytes.
-
- set slot_stats [$primary CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 42
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
-
- set slot_stats [$replica CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-in 34
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS network-bytes-out correctness.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster}} {
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 cluster keyslot $key]
- set expected_slots_to_key_count [dict create $key_slot 1]
- set metrics_to_assert [list network-bytes-out]
- R 0 CONFIG SET cluster-slot-stats-enabled yes
-
- test "CLUSTER SLOT-STATS network-bytes-out, for non-slot specific commands." {
- R 0 INFO
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-out, for slot specific commands." {
- R 0 SET $key value
- # +OK\r\n --> 5 bytes
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-out 5
- ]
- ]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-
- test "CLUSTER SLOT-STATS network-bytes-out, blocking commands." {
- set rd [redis_deferring_client]
- $rd BLPOP $key 0
- wait_for_blocked_clients_count 1
-
- # Assert empty slot stats here, since COB is yet to be flushed due to the block.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
-
- # Unblock the command.
- # LPUSH client) :1\r\n --> 4 bytes.
- # BLPOP client) *2\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 24 bytes, upon unblocking.
- R 0 LPUSH $key value
- wait_for_blocked_clients_count 0
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-out 28 ;# 4 + 24 bytes.
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- R 0 CONFIG RESETSTAT
- R 0 FLUSHALL
-}
-
-start_cluster 1 1 {tags {external:skip cluster}} {
-
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 CLUSTER KEYSLOT $key]
- set metrics_to_assert [list network-bytes-out]
- R 0 CONFIG SET cluster-slot-stats-enabled yes
-
- # Setup replication.
- assert {[s -1 role] eq {slave}}
- wait_for_condition 1000 50 {
- [s -1 master_link_status] eq {up}
- } else {
- fail "Instance #1 master link status is not up"
- }
- R 1 readonly
-
- test "CLUSTER SLOT-STATS network-bytes-out, replication stream egress." {
- assert_equal [R 0 SET $key VALUE] {OK}
- # Local client) +OK\r\n --> 5 bytes.
- # Replication stream) *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 33 bytes.
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-out 38 ;# 5 + 33 bytes.
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
-}
-
-start_cluster 1 1 {tags {external:skip cluster}} {
-
- # Define shared variables.
- set channel "channel"
- set key_slot [R 0 cluster keyslot $channel]
- set channel_secondary "channel2"
- set key_slot_secondary [R 0 cluster keyslot $channel_secondary]
- set metrics_to_assert [list network-bytes-out]
- R 0 CONFIG SET cluster-slot-stats-enabled yes
-
- test "CLUSTER SLOT-STATS network-bytes-out, sharded pub/sub, single channel." {
- set slot [R 0 cluster keyslot $channel]
- set publisher [Rn 0]
- set subscriber [redis_client]
- set replica [redis_deferring_client -1]
-
- # Subscriber client) *3\r\n$10\r\nssubscribe\r\n$7\r\nchannel\r\n:1\r\n --> 38 bytes
- $subscriber SSUBSCRIBE $channel
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-out 38
- ]
- ]
- R 0 CONFIG RESETSTAT
-
- # Publisher client) :1\r\n --> 4 bytes.
- # Subscriber client) *3\r\n$8\r\nsmessage\r\n$7\r\nchannel\r\n$5\r\nhello\r\n --> 42 bytes.
- assert_equal 1 [$publisher SPUBLISH $channel hello]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create $key_slot [
- dict create network-bytes-out 46 ;# 4 + 42 bytes.
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
- $subscriber QUIT
- R 0 FLUSHALL
- R 0 CONFIG RESETSTAT
-
- test "CLUSTER SLOT-STATS network-bytes-out, sharded pub/sub, cross-slot channels." {
- set slot [R 0 cluster keyslot $channel]
- set publisher [Rn 0]
- set subscriber [redis_client]
- set replica [redis_deferring_client -1]
-
- # Stack multi-slot subscriptions against a single client.
- # For primary channel;
- # Subscriber client) *3\r\n$10\r\nssubscribe\r\n$7\r\nchannel\r\n:1\r\n --> 38 bytes
- # For secondary channel;
- # Subscriber client) *3\r\n$10\r\nssubscribe\r\n$8\r\nchannel2\r\n:1\r\n --> 39 bytes
- $subscriber SSUBSCRIBE $channel
- $subscriber SSUBSCRIBE $channel_secondary
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create \
- $key_slot [ \
- dict create network-bytes-out 38
- ] \
- $key_slot_secondary [ \
- dict create network-bytes-out 39
- ]
- ]
- R 0 CONFIG RESETSTAT
-
- # For primary channel;
- # Publisher client) :1\r\n --> 4 bytes.
- # Subscriber client) *3\r\n$8\r\nsmessage\r\n$7\r\nchannel\r\n$5\r\nhello\r\n --> 42 bytes.
- # For secondary channel;
- # Publisher client) :1\r\n --> 4 bytes.
- # Subscriber client) *3\r\n$8\r\nsmessage\r\n$8\r\nchannel2\r\n$5\r\nhello\r\n --> 43 bytes.
- assert_equal 1 [$publisher SPUBLISH $channel hello]
- assert_equal 1 [$publisher SPUBLISH $channel_secondary hello]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set expected_slot_stats [
- dict create \
- $key_slot [ \
- dict create network-bytes-out 46 ;# 4 + 42 bytes.
- ] \
- $key_slot_secondary [ \
- dict create network-bytes-out 47 ;# 4 + 43 bytes.
- ]
- ]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS key-count metric correctness.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
-
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 cluster keyslot $key]
- set metrics_to_assert [list key-count]
- set expected_slot_stats [
- dict create $key_slot [
- dict create key-count 1
- ]
- ]
-
- test "CLUSTER SLOT-STATS contains default value upon redis-server startup" {
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
-
- test "CLUSTER SLOT-STATS contains correct metrics upon key introduction" {
- R 0 SET $key TEST
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
-
- test "CLUSTER SLOT-STATS contains correct metrics upon key mutation" {
- R 0 SET $key NEW_VALUE
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
-
- test "CLUSTER SLOT-STATS contains correct metrics upon key deletion" {
- R 0 DEL $key
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats $slot_stats $metrics_to_assert
- }
-
- test "CLUSTER SLOT-STATS slot visibility based on slot ownership changes" {
- R 0 CONFIG SET cluster-require-full-coverage no
-
- R 0 CLUSTER DELSLOTS $key_slot
- set expected_slots [initialize_expected_slots_dict]
- dict unset expected_slots $key_slot
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert {[dict size $expected_slots] == 16383}
- assert_slot_visibility $slot_stats $expected_slots
-
- R 0 CLUSTER ADDSLOTS $key_slot
- set expected_slots [initialize_expected_slots_dict]
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert {[dict size $expected_slots] == 16384}
- assert_slot_visibility $slot_stats $expected_slots
- }
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS SLOTSRANGE sub-argument.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster}} {
-
- test "CLUSTER SLOT-STATS SLOTSRANGE all slots present" {
- set start_slot 100
- set end_slot 102
- set expected_slots [initialize_expected_slots_dict_with_range $start_slot $end_slot]
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE $start_slot $end_slot]
- assert_slot_visibility $slot_stats $expected_slots
- }
-
- test "CLUSTER SLOT-STATS SLOTSRANGE some slots missing" {
- set start_slot 100
- set end_slot 102
- set expected_slots [initialize_expected_slots_dict_with_range $start_slot $end_slot]
-
- R 0 CLUSTER DELSLOTS $start_slot
- dict unset expected_slots $start_slot
-
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE $start_slot $end_slot]
- assert_slot_visibility $slot_stats $expected_slots
- }
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS ORDERBY sub-argument.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
-
- set metrics [list "key-count" "memory-bytes" "cpu-usec" "network-bytes-in" "network-bytes-out"]
-
- # SET keys for target hashslots, to encourage ordering.
- set hash_tags [list 0 1 2 3 4]
- set num_keys 1
- foreach hash_tag $hash_tags {
- for {set i 0} {$i < $num_keys} {incr i 1} {
- R 0 SET "$i{$hash_tag}" VALUE
- }
- incr num_keys 1
- }
-
- # SET keys for random hashslots, for random noise.
- set num_keys 0
- while {$num_keys < 1000} {
- set random_key [randomInt 16384]
- R 0 SET $random_key VALUE
- incr num_keys 1
- }
-
- test "CLUSTER SLOT-STATS ORDERBY DESC correct ordering" {
- foreach orderby $metrics {
- set slot_stats [R 0 CLUSTER SLOT-STATS ORDERBY $orderby DESC]
- assert_slot_stats_monotonic_descent $slot_stats $orderby
- }
- }
-
- test "CLUSTER SLOT-STATS ORDERBY ASC correct ordering" {
- foreach orderby $metrics {
- set slot_stats [R 0 CLUSTER SLOT-STATS ORDERBY $orderby ASC]
- assert_slot_stats_monotonic_ascent $slot_stats $orderby
- }
- }
-
- test "CLUSTER SLOT-STATS ORDERBY LIMIT correct response pagination, where limit is less than number of assigned slots" {
- R 0 FLUSHALL SYNC
- R 0 CONFIG RESETSTAT
-
- foreach orderby $metrics {
- set limit 5
- set slot_stats_desc [R 0 CLUSTER SLOT-STATS ORDERBY $orderby LIMIT $limit DESC]
- set slot_stats_asc [R 0 CLUSTER SLOT-STATS ORDERBY $orderby LIMIT $limit ASC]
- set slot_stats_desc_length [llength $slot_stats_desc]
- set slot_stats_asc_length [llength $slot_stats_asc]
- assert {$limit == $slot_stats_desc_length && $limit == $slot_stats_asc_length}
-
- # All slot statistics have been reset to 0, so we will order by slot in ascending order.
- set expected_slots [dict create 0 0 1 0 2 0 3 0 4 0]
- assert_slot_visibility $slot_stats_desc $expected_slots
- assert_slot_visibility $slot_stats_asc $expected_slots
- }
- }
-
- test "CLUSTER SLOT-STATS ORDERBY LIMIT correct response pagination, where limit is greater than number of assigned slots" {
- R 0 CONFIG SET cluster-require-full-coverage no
- R 0 FLUSHALL SYNC
- R 0 CLUSTER FLUSHSLOTS
- R 0 CLUSTER ADDSLOTS 100 101
-
- foreach orderby $metrics {
- set num_assigned_slots 2
- set limit 5
- set slot_stats_desc [R 0 CLUSTER SLOT-STATS ORDERBY $orderby LIMIT $limit DESC]
- set slot_stats_asc [R 0 CLUSTER SLOT-STATS ORDERBY $orderby LIMIT $limit ASC]
- set slot_stats_desc_length [llength $slot_stats_desc]
- set slot_stats_asc_length [llength $slot_stats_asc]
- set expected_response_length [expr min($num_assigned_slots, $limit)]
- assert {$expected_response_length == $slot_stats_desc_length && $expected_response_length == $slot_stats_asc_length}
-
- set expected_slots [dict create 100 0 101 0]
- assert_slot_visibility $slot_stats_desc $expected_slots
- assert_slot_visibility $slot_stats_asc $expected_slots
- }
- }
-
- test "CLUSTER SLOT-STATS ORDERBY arg sanity check." {
- # Non-existent argument.
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY key-count non-existent-arg}
- # Negative LIMIT.
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY key-count DESC LIMIT -1}
- # Non-existent ORDERBY metric.
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY non-existent-metric}
- # When cluster-slot-stats-enabled config is disabled, you cannot sort using advanced metrics.
- R 0 CONFIG SET cluster-slot-stats-enabled no
- set orderby "cpu-usec"
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY $orderby}
- set orderby "network-bytes-in"
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY $orderby}
- set orderby "network-bytes-out"
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY $orderby}
- set orderby "memory-bytes"
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY $orderby}
-
- # When only cpu net is enabled, memory-bytes ORDERBY should fail
- R 0 CONFIG SET cluster-slot-stats-enabled "cpu net"
- assert_error "ERR*" {R 0 CLUSTER SLOT-STATS ORDERBY memory-bytes}
- }
-
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS replication.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 1 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
-
- # Define shared variables.
- set key "key"
- set key_slot [R 0 CLUSTER KEYSLOT $key]
- set primary [Rn 0]
- set replica [Rn 1]
-
- # For replication, assertions are split between deterministic and non-deterministic metrics.
- # * For deterministic metrics, strict equality assertions are made.
- # * For non-deterministic metrics, non-zeroness assertions are made.
- # Non-zeroness as in, both primary and replica should either have some value, or no value at all.
- #
- # * key-count is deterministic between primary and its replica.
- # * cpu-usec is non-deterministic between primary and its replica.
- # * network-bytes-in is deterministic between primary and its replica.
- # * network-bytes-out will remain empty in the replica, since primary client do not receive replies, unless for replicationSendAck().
- set deterministic_metrics [list key-count network-bytes-in]
- set non_deterministic_metrics [list cpu-usec]
- set empty_metrics [list network-bytes-out]
-
- # Setup replication.
- assert {[s -1 role] eq {slave}}
- wait_for_condition 1000 50 {
- [s -1 master_link_status] eq {up}
- } else {
- fail "Instance #1 master link status is not up"
- }
- R 1 readonly
-
- test "CLUSTER SLOT-STATS metrics replication for new keys" {
- # *3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n --> 33 bytes.
- R 0 SET $key VALUE
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create key-count 1 network-bytes-in 33
- ]
- ]
- set slot_stats_master [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats_master $expected_slot_stats $deterministic_metrics
-
- wait_for_condition 500 10 {
- [string match {*calls=1,*} [cmdrstat set $replica]]
- } else {
- fail "Replica did not receive the command."
- }
- set slot_stats_replica [R 1 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_equal_slot_stats $slot_stats_master $slot_stats_replica $deterministic_metrics $non_deterministic_metrics
- assert_empty_slot_stats $slot_stats_replica $empty_metrics
- }
- R 0 CONFIG RESETSTAT
- R 1 CONFIG RESETSTAT
-
- test "CLUSTER SLOT-STATS metrics replication for existing keys" {
- # *3\r\n$3\r\nset\r\n$3\r\nkey\r\n$13\r\nvalue_updated\r\n --> 42 bytes.
- R 0 SET $key VALUE_UPDATED
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create key-count 1 network-bytes-in 42
- ]
- ]
- set slot_stats_master [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats_master $expected_slot_stats $deterministic_metrics
-
- wait_for_condition 500 10 {
- [string match {*calls=1,*} [cmdrstat set $replica]]
- } else {
- fail "Replica did not receive the command."
- }
- set slot_stats_replica [R 1 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_equal_slot_stats $slot_stats_master $slot_stats_replica $deterministic_metrics $non_deterministic_metrics
- assert_empty_slot_stats $slot_stats_replica $empty_metrics
- }
- R 0 CONFIG RESETSTAT
- R 1 CONFIG RESETSTAT
-
- test "CLUSTER SLOT-STATS metrics replication for deleting keys" {
- # *2\r\n$3\r\ndel\r\n$3\r\nkey\r\n --> 22 bytes.
- R 0 DEL $key
-
- set expected_slot_stats [
- dict create $key_slot [
- dict create key-count 0 network-bytes-in 22
- ]
- ]
- set slot_stats_master [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_empty_slot_stats_with_exception $slot_stats_master $expected_slot_stats $deterministic_metrics
-
- wait_for_condition 500 10 {
- [string match {*calls=1,*} [cmdrstat del $replica]]
- } else {
- fail "Replica did not receive the command."
- }
- set slot_stats_replica [R 1 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- assert_equal_slot_stats $slot_stats_master $slot_stats_replica $deterministic_metrics $non_deterministic_metrics
- assert_empty_slot_stats $slot_stats_replica $empty_metrics
- }
- R 0 CONFIG RESETSTAT
- R 1 CONFIG RESETSTAT
-}
-
-start_cluster 2 2 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
- test "CLUSTER SLOT-STATS reset upon atomic slot migration" {
- # key on slot-0
- set key0 "{06S}mykey0"
- set key0_slot [R 0 CLUSTER KEYSLOT $key0]
- R 0 SET $key0 VALUE
-
- # Migrate slot-0 to node-1
- R 1 CLUSTER MIGRATION IMPORT 0 0
- wait_for_condition 1000 10 {
- [CI 0 cluster_slot_migration_active_tasks] == 0 &&
- [CI 1 cluster_slot_migration_active_tasks] == 0
- } else {
- fail "ASM tasks did not complete"
- }
-
- set expected_slot_stats [
- dict create \
- $key0_slot [ \
- dict create key-count 1 \
- dict create cpu-usec 0 \
- dict create network-bytes-in 0 \
- dict create network-bytes-out 0 \
- ]
- ]
- set metrics_to_assert [list key-count cpu-usec network-bytes-in network-bytes-out]
-
- # Verify metrics are reset except key-count
- set slot_stats [R 1 CLUSTER SLOT-STATS SLOTSRANGE 0 0]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
-
- # Migrate slot-0 back to node-0
- R 0 CLUSTER MIGRATION IMPORT 0 0
- wait_for_condition 1000 10 {
- [CI 0 cluster_slot_migration_active_tasks] == 0 &&
- [CI 1 cluster_slot_migration_active_tasks] == 0
- } else {
- fail "ASM tasks did not complete"
- }
-
- # Verify metrics are reset except key-count
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 0]
- assert_empty_slot_stats_with_exception $slot_stats $expected_slot_stats $metrics_to_assert
- }
-}
-
-# -----------------------------------------------------------------------------
-# Test cases for CLUSTER SLOT-STATS memory-bytes field presence.
-# -----------------------------------------------------------------------------
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled yes}} {
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 cluster keyslot $key]
-
- test "CLUSTER SLOT-STATS memory-bytes field present when cluster-slot-stats-enabled set on startup" {
- R 0 SET $key VALUE
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- # Verify memory-bytes field is present
- assert {[dict exists $slot_stats $key_slot]}
- set stats [dict get $slot_stats $key_slot]
- assert {[dict exists $stats memory-bytes]}
- assert {[dict get $stats memory-bytes] > 0}
- }
-
- test "CLUSTER SLOT-STATS net mem combination shows only net and mem stats" {
- R 0 CONFIG SET cluster-slot-stats-enabled "net mem"
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- set stats [dict get $slot_stats $key_slot]
- assert {[dict exists $stats memory-bytes]}
- assert {[dict exists $stats network-bytes-in]}
- assert {[dict exists $stats network-bytes-out]}
- assert {![dict exists $stats cpu-usec]}
- }
-
- test "CLUSTER SLOT-STATS cpu mem combination shows only cpu and mem stats" {
- R 0 CONFIG SET cluster-slot-stats-enabled "cpu mem"
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- set stats [dict get $slot_stats $key_slot]
- assert {[dict exists $stats memory-bytes]}
- assert {[dict exists $stats cpu-usec]}
- assert {![dict exists $stats network-bytes-in]}
- assert {![dict exists $stats network-bytes-out]}
-
- # Restore to yes for subsequent tests
- R 0 CONFIG SET cluster-slot-stats-enabled yes
- }
-
- test "CLUSTER SLOT-STATS memory-bytes field not present after disabling cluster-slot-stats-enabled" {
- R 0 CONFIG SET cluster-slot-stats-enabled no
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- # Verify memory-bytes field is not present after disabling config
- # (memory tracking is disabled when MEM flag is removed)
- assert {[dict exists $slot_stats $key_slot]}
- set stats [dict get $slot_stats $key_slot]
- assert {![dict exists $stats memory-bytes]}
-
- # Verify other stats fields are not present
- assert {![dict exists $stats cpu-usec]}
- assert {![dict exists $stats network-bytes-in]}
- assert {![dict exists $stats network-bytes-out]}
- }
-
- test "CLUSTER SLOT-STATS memory tracking cannot be re-enabled after being disabled" {
- # Once memory tracking is disabled, it cannot be re-enabled at runtime
- assert_error "ERR*memory tracking cannot be enabled at runtime*" {R 0 CONFIG SET cluster-slot-stats-enabled yes}
- assert_error "ERR*memory tracking cannot be enabled at runtime*" {R 0 CONFIG SET cluster-slot-stats-enabled mem}
-
- # But cpu and net can still be enabled
- R 0 CONFIG SET cluster-slot-stats-enabled "cpu net"
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- assert {[dict exists $slot_stats $key_slot]}
- set stats [dict get $slot_stats $key_slot]
- assert {![dict exists $stats memory-bytes]}
- assert {[dict exists $stats cpu-usec]}
- assert {[dict exists $stats network-bytes-in]}
- assert {[dict exists $stats network-bytes-out]}
- }
-}
-
-start_cluster 1 0 {tags {external:skip cluster} overrides {cluster-slot-stats-enabled no}} {
- # Define shared variables.
- set key "FOO"
- set key_slot [R 0 cluster keyslot $key]
-
- test "CLUSTER SLOT-STATS memory-bytes field not present when cluster-slot-stats-enabled not set on startup" {
- R 0 SET $key VALUE
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- # Verify memory-bytes field is not present
- assert {[dict exists $slot_stats $key_slot]}
- set stats [dict get $slot_stats $key_slot]
- assert {![dict exists $stats memory-bytes]}
-
- # Only key-count should be present
- assert {[dict exists $stats key-count]}
- assert {[dict get $stats key-count] == 1}
- }
-
- test "CLUSTER SLOT-STATS enabling mem at runtime fails when not enabled at startup" {
- # Trying to enable memory tracking at runtime should fail
- assert_error "ERR*memory tracking cannot be enabled at runtime*" {R 0 CONFIG SET cluster-slot-stats-enabled mem}
- assert_error "ERR*memory tracking cannot be enabled at runtime*" {R 0 CONFIG SET cluster-slot-stats-enabled yes}
- assert_error "ERR*memory tracking cannot be enabled at runtime*" {R 0 CONFIG SET cluster-slot-stats-enabled "cpu net mem"}
- }
-
- test "CLUSTER SLOT-STATS enabling cpu and net at runtime works" {
- R 0 CONFIG SET cluster-slot-stats-enabled "cpu net"
- set slot_stats [R 0 CLUSTER SLOT-STATS SLOTSRANGE 0 16383]
- set slot_stats [convert_array_into_dict $slot_stats]
-
- # Verify memory-bytes field is still not present
- assert {[dict exists $slot_stats $key_slot]}
- set stats [dict get $slot_stats $key_slot]
- assert {![dict exists $stats memory-bytes]}
-
- # Other stats fields should now be present
- assert {[dict exists $stats cpu-usec]}
- assert {[dict exists $stats network-bytes-in]}
- assert {[dict exists $stats network-bytes-out]}
- }
-}