From 8c6a6444dbebb4b9570f49eb5c16bb57882f0bd3 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Fri, 20 Mar 2026 00:29:57 +0000 Subject: [PATCH] fix: support zstd compression in mysql84 TAP --- lib/MySQL_Protocol.cpp | 50 +++++++++---------- test/infra/control/ensure-infras.bash | 11 +++- test/infra/control/run-tests-isolated.bash | 13 ++++- .../infra-mysql84/conf/mysql/mysql1/my.cnf | 2 +- .../infra-mysql84/conf/mysql/mysql2/my.cnf | 2 +- .../infra-mysql84/conf/mysql/mysql3/my.cnf | 2 +- .../infra-mysql84/docker-compose-init.bash | 8 +-- test/tap/groups/groups.json | 2 +- 8 files changed, 55 insertions(+), 35 deletions(-) diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index fe2435503..a6a4eb9b4 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -1093,8 +1093,14 @@ bool MySQL_Protocol::generate_pkt_initial_handshake(bool send, void **ptr, unsig } else { mysql_thread___server_capabilities &= ~CLIENT_DEPRECATE_EOF; } - (*myds)->myconn->options.server_capabilities=mysql_thread___server_capabilities; - memcpy(_ptr+l,&mysql_thread___server_capabilities, sizeof(mysql_thread___server_capabilities)/2); l+=sizeof(mysql_thread___server_capabilities)/2; + uint32_t server_capabilities = mysql_thread___server_capabilities; + if (deprecate_eof_active && mysql_thread___enable_client_deprecate_eof) { + server_capabilities |= CLIENT_DEPRECATE_EOF; + } else { + server_capabilities &= ~CLIENT_DEPRECATE_EOF; + } + (*myds)->myconn->options.server_capabilities=server_capabilities; + memcpy(_ptr+l,&server_capabilities, sizeof(server_capabilities)/2); l+=sizeof(server_capabilities)/2; const MARIADB_CHARSET_INFO *ci = NULL; ci = proxysql_find_charset_collate(mysql_thread___default_variables[SQL_COLLATION_CONNECTION]); if (!ci) { @@ -1107,18 +1113,8 @@ bool MySQL_Protocol::generate_pkt_initial_handshake(bool send, void **ptr, unsig uint8_t uint8_charset = ci->nr & 255; memcpy(_ptr+l,&uint8_charset, sizeof(uint8_charset)); l+=sizeof(uint8_charset); memcpy(_ptr+l,&server_status, sizeof(server_status)); l+=sizeof(server_status); - uint32_t extended_capabilities = CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS | CLIENT_PS_MULTI_RESULTS | - CLIENT_PLUGIN_AUTH | CLIENT_SESSION_TRACKING | CLIENT_REMEMBER_OPTIONS; - // we conditionally reply the client specifying in 'server_capabilities' that - // 'CLIENT_DEPRECATE_EOF' is available if explicitly enabled by 'mysql-enable_client_deprecate_eof' - // variable. This is the first step of ensuring that client connections doesn't - // enable 'CLIENT_DEPRECATE_EOF' unless explicitly stated by 'mysql-enable_client_deprecate_eof'. - // Second step occurs during client handshake response (process_pkt_handshake_response). - if (deprecate_eof_active && mysql_thread___enable_client_deprecate_eof) { - extended_capabilities |= CLIENT_DEPRECATE_EOF; - } - // Copy the 'capability_flags_2' - uint16_t upper_word = static_cast(extended_capabilities >> 16); + // Copy the upper 16 capability bits from the effective server capability mask. + uint16_t upper_word = static_cast(server_capabilities >> 16); memcpy(_ptr+l, static_cast(&upper_word), sizeof(upper_word)); l += sizeof(upper_word); // Copy the 'auth_plugin_data_len'. Hardcoded due to 'CLIENT_PLUGIN_AUTH' always enabled and reported // as 'mysql_native_password'. @@ -1704,13 +1700,16 @@ bool MySQL_Protocol::PPHR_2(unsigned char *pkt, unsigned int len, bool& ret, MyP vars1.auth_plugin = extra_pkt; extra_pkt += auth_plugin_len + 1; } - if ((vars1.capabilities & CLIENT_CONNECT_ATTRS) && vars1._ptr + len > extra_pkt) { + const unsigned char* packet_end = vars1._ptr + len; + const bool has_zstd_level = vars1.capabilities & CLIENT_ZSTD_COMPRESSION_ALGORITHM; + const unsigned char* connect_attrs_end = packet_end - (has_zstd_level ? 1 : 0); + if ((vars1.capabilities & CLIENT_CONNECT_ATTRS) && extra_pkt < connect_attrs_end) { uint64_t attrs_len = 0; const int attrs_len_enc = mysql_decode_length_ll(extra_pkt, &attrs_len); if ( attrs_len_enc <= 0 || - static_cast((vars1._ptr + len) - extra_pkt) < static_cast(attrs_len_enc) + attrs_len + static_cast(connect_attrs_end - extra_pkt) < static_cast(attrs_len_enc) + attrs_len ) { ret = false; proxy_debug(PROXY_DEBUG_MYSQL_AUTH, 5, "Session=%p , DS=%p , user='%s' . malformed connect attrs in handshake response\n", (*myds), (*myds)->sess, vars1.user); @@ -1718,8 +1717,8 @@ bool MySQL_Protocol::PPHR_2(unsigned char *pkt, unsigned int len, bool& ret, MyP } extra_pkt += attrs_len_enc + attrs_len; } - if (vars1.capabilities & CLIENT_ZSTD_COMPRESSION_ALGORITHM) { - if (vars1._ptr + len <= extra_pkt) { + if (has_zstd_level) { + if (packet_end <= extra_pkt) { ret = false; proxy_debug(PROXY_DEBUG_MYSQL_AUTH, 5, "Session=%p , DS=%p , user='%s' . missing zstd compression level in handshake response\n", (*myds), (*myds)->sess, vars1.user); return false; @@ -2202,18 +2201,19 @@ void MySQL_Protocol::PPHR_SetConnAttrs(MyProt_tmp_auth_vars& vars1, account_deta mysql_variables.client_set_value(sess, SQL_CHARACTER_SET_CONNECTION, ss.str().c_str()); mysql_variables.client_set_value(sess, SQL_COLLATION_CONNECTION, ss.str().c_str()); - // enable compression - const bool use_zlib_compression = - (vars1.capabilities & CLIENT_COMPRESS) - && - (myconn->options.server_capabilities & CLIENT_COMPRESS); - // Match MySQL server behavior and prefer zlib whenever both peers advertise both compression capabilities. + // Honor an explicit zstd negotiation from the client before falling back to legacy zlib compression. const bool use_zstd_compression = - !use_zlib_compression + vars1.use_zstd_compression && (vars1.capabilities & CLIENT_ZSTD_COMPRESSION_ALGORITHM) && (myconn->options.server_capabilities & CLIENT_ZSTD_COMPRESSION_ALGORITHM); + const bool use_zlib_compression = + !use_zstd_compression + && + (vars1.capabilities & CLIENT_COMPRESS) + && + (myconn->options.server_capabilities & CLIENT_COMPRESS); const uint8_t zstd_compression_level = (vars1.zstd_compression_level > 0 && vars1.zstd_compression_level <= ZSTD_maxCLevel()) ? vars1.zstd_compression_level diff --git a/test/infra/control/ensure-infras.bash b/test/infra/control/ensure-infras.bash index 276d4a90f..78789fdde 100755 --- a/test/infra/control/ensure-infras.bash +++ b/test/infra/control/ensure-infras.bash @@ -9,6 +9,15 @@ export WORKSPACE="${REPO_ROOT}" # Default INFRA_ID if not provided export INFRA_ID="${INFRA_ID:-dev-$USER}" +export INFRA="${INFRA:-${INFRA_TYPE}}" + +expand_infra_list() { + local list_path="$1" + while IFS= read -r infra_name; do + [ -n "${infra_name}" ] || continue + eval "printf '%s\n' \"${infra_name}\"" + done < "${list_path}" +} if [ -z "${TAP_GROUP}" ]; then echo "ERROR: TAP_GROUP is not set." @@ -27,7 +36,7 @@ fi INFRAS="" if [ -n "${LST_PATH}" ]; then - INFRAS=$(cat "${LST_PATH}") + INFRAS=$(expand_infra_list "${LST_PATH}") echo ">>> Found infrastructure requirements for group '${TAP_GROUP}' in '${LST_PATH}'" else if [ -n "${INFRA_TYPE}" ]; then diff --git a/test/infra/control/run-tests-isolated.bash b/test/infra/control/run-tests-isolated.bash index 495d107b8..187765ca4 100755 --- a/test/infra/control/run-tests-isolated.bash +++ b/test/infra/control/run-tests-isolated.bash @@ -9,6 +9,15 @@ export WORKSPACE="${REPO_ROOT}" # Default INFRA_ID if not provided export INFRA_ID="${INFRA_ID:-dev-$USER}" +export INFRA="${INFRA:-${INFRA_TYPE}}" + +expand_infra_list() { + local list_path="$1" + while IFS= read -r infra_name; do + [ -n "${infra_name}" ] || continue + eval "printf '%s\n' \"${infra_name}\"" + done < "${list_path}" +} # 1. Determine Required Infras INFRAS_TO_CHECK="" @@ -16,9 +25,9 @@ BASE_GROUP="${TAP_GROUP%%-g[0-9]*}" # Strip -g1, -g2 etc. if [ -n "${TAP_GROUP}" ]; then if [ -f "${WORKSPACE}/test/tap/groups/${TAP_GROUP}/infras.lst" ]; then - INFRAS_TO_CHECK=$(cat "${WORKSPACE}/test/tap/groups/${TAP_GROUP}/infras.lst") + INFRAS_TO_CHECK=$(expand_infra_list "${WORKSPACE}/test/tap/groups/${TAP_GROUP}/infras.lst") elif [ -f "${WORKSPACE}/test/tap/groups/${BASE_GROUP}/infras.lst" ]; then - INFRAS_TO_CHECK=$(cat "${WORKSPACE}/test/tap/groups/${BASE_GROUP}/infras.lst") + INFRAS_TO_CHECK=$(expand_infra_list "${WORKSPACE}/test/tap/groups/${BASE_GROUP}/infras.lst") fi fi diff --git a/test/infra/infra-mysql84/conf/mysql/mysql1/my.cnf b/test/infra/infra-mysql84/conf/mysql/mysql1/my.cnf index 799446dde..e92c2445c 100644 --- a/test/infra/infra-mysql84/conf/mysql/mysql1/my.cnf +++ b/test/infra/infra-mysql84/conf/mysql/mysql1/my.cnf @@ -40,7 +40,7 @@ relay_log_recovery=ON #source_info_repository=TABLE read_only=0 -log-error=/var/log/mysql/error.log +log-error=/var/lib/mysql/error.log #log_warnings=2 #ssl-ca=/var/lib/mysql/ca.pem diff --git a/test/infra/infra-mysql84/conf/mysql/mysql2/my.cnf b/test/infra/infra-mysql84/conf/mysql/mysql2/my.cnf index f805765b4..9f23a0bc0 100644 --- a/test/infra/infra-mysql84/conf/mysql/mysql2/my.cnf +++ b/test/infra/infra-mysql84/conf/mysql/mysql2/my.cnf @@ -40,7 +40,7 @@ relay_log_recovery=ON #source_info_repository=TABLE read_only=1 -log-error=/var/log/mysql/error.log +log-error=/var/lib/mysql/error.log #log_warnings=2 #ssl-ca=/var/lib/mysql/ca.pem diff --git a/test/infra/infra-mysql84/conf/mysql/mysql3/my.cnf b/test/infra/infra-mysql84/conf/mysql/mysql3/my.cnf index 99f1fec9e..2a9a14f4f 100644 --- a/test/infra/infra-mysql84/conf/mysql/mysql3/my.cnf +++ b/test/infra/infra-mysql84/conf/mysql/mysql3/my.cnf @@ -40,7 +40,7 @@ relay_log_recovery=ON #source_info_repository=TABLE read_only=1 -log-error=/var/log/mysql/error.log +log-error=/var/lib/mysql/error.log #log_warnings=2 #ssl-ca=/var/lib/mysql/ca.pem diff --git a/test/infra/infra-mysql84/docker-compose-init.bash b/test/infra/infra-mysql84/docker-compose-init.bash index b004ca212..7165c25aa 100755 --- a/test/infra/infra-mysql84/docker-compose-init.bash +++ b/test/infra/infra-mysql84/docker-compose-init.bash @@ -93,10 +93,12 @@ for RAW_PATH in ${MOUNTED_PATHS}; do fi done -# 3. Inject dynamic ROOT_PASSWORD into Orchestrator configs +# 3. Inject dynamic values into Orchestrator configs if [ -d "./conf/orchestrator" ]; then - echo "Injecting ROOT_PASSWORD into Orchestrator configurations..." - find ./conf/orchestrator -name "orchestrator.conf.json" -exec sed -i "s/\"MySQLTopologyPassword\": \".*\"/\"MySQLTopologyPassword\": \"${ROOT_PASSWORD}\"/g" {} + + echo "Injecting ROOT_PASSWORD and INFRA into Orchestrator configurations..." + find ./conf/orchestrator -name "orchestrator.conf.json" -exec sed -i \ + -e "s/\"MySQLTopologyPassword\": \".*\"/\"MySQLTopologyPassword\": \"${ROOT_PASSWORD}\"/g" \ + -e "s/\${INFRA}/${INFRA}/g" {} + fi # 4. TRANSIENT SSL SETUP (Avoiding repo permission changes) diff --git a/test/tap/groups/groups.json b/test/tap/groups/groups.json index 3164b077f..de4d5247a 100644 --- a/test/tap/groups/groups.json +++ b/test/tap/groups/groups.json @@ -62,7 +62,7 @@ "reg_test_1493-mixed_compression-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], "reg_test_1574-mariadb_read_stmt_execute_response-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], "reg_test_1574-stmt_metadata-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], - "reg_test_2793-compression-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], + "reg_test_2793-compression-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1","mysql84-g1" ], "reg_test_3184-set_wait_timeout-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], "reg_test_3223-restapi_return_codes-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], "reg_test_3247-mycli_support-t" : [ "legacy-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ],