From e53d2c76f93567eec5d342ccddf7ff9c2bd8fb25 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Sun, 22 Feb 2026 17:18:24 +0000 Subject: [PATCH] Address PR #5410 review findings across FFTO, sessions, TAP, and docs Apply actionable bot review feedback from PR #5410 without behavior drift:\n- fix MySQL/PgSQL FFTO digest normalization and max-length hashing\n- add early FFTO packet/message size guards for bypass safety\n- restore MySQL session GTID reset and harden GenAI async error ownership\n- add null-check for stripped KILL query normalization path\n- call FFTO on_close() before observer reset/bypass in session flows\n- fix processlist query-options default pagination limit semantics\n- fix TAP noise_failures locking race and noise-aware plan count\n- extend wait_get_enpoint_ready with optional basic-auth passthrough\n- update MCP architecture docs from observe->stats naming\n- clean corrupted character in pgsql query-cache test comment\n\nValidation run:\n- git diff --check\n- make -C test/tap/tap tap.o utils_mariadb.o utils_mysql57.o utils_mysql8.o -j4\n- make -C lib obj/MySQLFFTO.oo obj/PgSQLFFTO.oo obj/MySQL_Session.oo obj/PgSQL_Session.oo obj/Query_Processor.oo -j4 --- doc/MCP/Architecture.md | 12 +-- include/proxysql_admin.h | 3 +- lib/MySQLFFTO.cpp | 50 +++++++------ lib/MySQL_Session.cpp | 65 +++++++++++----- lib/PgSQLFFTO.cpp | 10 ++- lib/PgSQL_Session.cpp | 82 ++++++++++++--------- test/tap/tap/tap.cpp | 8 +- test/tap/tap/utils.cpp | 4 +- test/tap/tap/utils.h | 4 +- test/tap/tests/mysql-set_transaction-t.cpp | 2 +- test/tap/tests/pgsql-query_cache_test-t.cpp | 2 +- 11 files changed, 147 insertions(+), 95 deletions(-) diff --git a/doc/MCP/Architecture.md b/doc/MCP/Architecture.md index 39f2d272c..38a726b5d 100644 --- a/doc/MCP/Architecture.md +++ b/doc/MCP/Architecture.md @@ -31,7 +31,7 @@ The MCP module implements JSON-RPC 2.0 over HTTPS for LLM (Large Language Model) │ │ - query_tool_handler (NEW) │ │ │ │ - admin_tool_handler (NEW) │ │ │ │ - cache_tool_handler (NEW) │ │ -│ │ - observe_tool_handler (NEW) │ │ +│ │ - stats_tool_handler (NEW) │ │ │ │ - ai_tool_handler (NEW) │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ @@ -47,7 +47,7 @@ The MCP module implements JSON-RPC 2.0 over HTTPS for LLM (Large Language Model) │ ┌──────────────┬──────────────┼──────────────┬──────────────┬─────────┐ │ │ ▼ ▼ ▼ ▼ ▼ ▼ │ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌───┐│ -│ │conf│ │obs │ │qry │ │adm │ │cach│ │ai ││ +│ │conf│ │sts │ │qry │ │adm │ │cach│ │ai ││ │ │TH │ │TH │ │TH │ │TH │ │TH │ │TH ││ │ └─┬──┘ └─┬──┘ └─┬──┘ └─┬──┘ └─┬──┘ └─┬─┘│ │ │ │ │ │ │ │ │ @@ -80,7 +80,7 @@ include/ ├── Query_Tool_Handler.h # Query endpoint tool handler (includes discovery tools) ├── Admin_Tool_Handler.h # Administration endpoint tool handler ├── Cache_Tool_Handler.h # Cache endpoint tool handler -├── Observe_Tool_Handler.h # Observability endpoint tool handler +├── Stats_Tool_Handler.h # Stats endpoint tool handler ├── AI_Tool_Handler.h # AI endpoint tool handler ├── Discovery_Schema.h # Discovery catalog implementation ├── Static_Harvester.h # Static database harvester for discovery @@ -94,7 +94,7 @@ lib/ ├── Query_Tool_Handler.cpp # Query endpoint implementation ├── Admin_Tool_Handler.cpp # Administration endpoint implementation ├── Cache_Tool_Handler.cpp # Cache endpoint implementation -├── Observe_Tool_Handler.cpp # Observability endpoint implementation +├── Stats_Tool_Handler.cpp # Stats endpoint implementation ├── AI_Tool_Handler.cpp # AI endpoint implementation ├── Discovery_Schema.cpp # Discovery catalog implementation ├── Static_Harvester.cpp # Static database harvester implementation @@ -449,7 +449,7 @@ private: ### Phase 1: Base Infrastructure ✅ COMPLETED 1. ✅ Create `MCP_Tool_Handler` base class -2. ✅ Create implementations for all 6 tool handlers (config, query, admin, cache, observe, ai) +2. ✅ Create implementations for all 6 tool handlers (config, query, admin, cache, stats, ai) 3. ✅ Update `MCP_Threads_Handler` to manage all handlers 4. ✅ Update `ProxySQL_MCP_Server` to pass handlers to endpoints @@ -459,7 +459,7 @@ private: 2. ✅ Implement Query_Tool_Handler tools (includes MySQL tools and discovery tools) 3. ✅ Implement Admin_Tool_Handler tools 4. ✅ Implement Cache_Tool_Handler tools -5. ✅ Implement Observe_Tool_Handler tools +5. ✅ Implement Stats_Tool_Handler tools 6. ✅ Implement AI_Tool_Handler tools ### Phase 3: Authentication & Testing ✅ MOSTLY COMPLETED diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index 744c2ad45..1ea23581a 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "ProxySQL_RESTAPI_Server.hpp" @@ -280,7 +281,7 @@ struct processlist_query_options_t { processlist_sort_by_t sort_by {processlist_sort_by_t::none}; ///< Optional primary sort key. bool sort_desc {true}; ///< Sort direction for @ref sort_by. bool disable_pagination {false}; ///< If true, ignore @ref limit and @ref offset. - uint32_t limit {0}; ///< Page size (`0` means return zero rows). + uint32_t limit {std::numeric_limits::max()}; ///< Page size (defaults to no limit). uint32_t offset {0}; ///< Number of rows to skip before page. }; diff --git a/lib/MySQLFFTO.cpp b/lib/MySQLFFTO.cpp index 09b9cc34d..41bffad74 100644 --- a/lib/MySQLFFTO.cpp +++ b/lib/MySQLFFTO.cpp @@ -67,13 +67,18 @@ MySQLFFTO::~MySQLFFTO() { void MySQLFFTO::on_client_data(const char* buf, std::size_t len) { if (!buf || len == 0) return; m_client_buffer.insert(m_client_buffer.end(), buf, buf + len); - while (m_client_buffer.size() - m_client_offset >= sizeof(mysql_hdr)) { - const mysql_hdr* hdr = reinterpret_cast(m_client_buffer.data() + m_client_offset); - uint32_t pkt_len = hdr->pkt_length; - if (m_client_buffer.size() - m_client_offset < sizeof(mysql_hdr) + pkt_len) break; - const unsigned char* payload = reinterpret_cast(m_client_buffer.data()) + m_client_offset + sizeof(mysql_hdr); - process_client_packet(payload, pkt_len); - m_client_offset += sizeof(mysql_hdr) + pkt_len; + while (m_client_buffer.size() - m_client_offset >= sizeof(mysql_hdr)) { + const mysql_hdr* hdr = reinterpret_cast(m_client_buffer.data() + m_client_offset); + uint32_t pkt_len = hdr->pkt_length; + if (pkt_len > (uint32_t)mysql_thread___ffto_max_buffer_size) { + m_session->ffto_bypassed = true; + on_close(); + return; + } + if (m_client_buffer.size() - m_client_offset < sizeof(mysql_hdr) + pkt_len) break; + const unsigned char* payload = reinterpret_cast(m_client_buffer.data()) + m_client_offset + sizeof(mysql_hdr); + process_client_packet(payload, pkt_len); + m_client_offset += sizeof(mysql_hdr) + pkt_len; } if (m_client_offset > 0) { if (m_client_offset >= m_client_buffer.size()) { @@ -238,24 +243,25 @@ void MySQLFFTO::report_query_stats(const std::string& query, unsigned long long auto* ui = m_session->client_myds->myconn->userinfo; if (!ui->username || !ui->schemaname) return; - options opts; - opts.lowercase = mysql_thread___query_digests_lowercase; - opts.replace_null = mysql_thread___query_digests_replace_null; - opts.replace_number = !mysql_thread___query_digests_no_digits; - opts.keep_comment = mysql_thread___query_digests_keep_comment; - opts.grouping_limit = mysql_thread___query_digests_grouping_limit; - opts.groups_grouping_limit = mysql_thread___query_digests_groups_grouping_limit; - opts.max_query_length = mysql_thread___query_digests_max_query_length; + options opts; + opts.lowercase = mysql_thread___query_digests_lowercase; + opts.replace_null = mysql_thread___query_digests_replace_null; + opts.replace_number = mysql_thread___query_digests_no_digits; + opts.keep_comment = mysql_thread___query_digests_keep_comment; + opts.grouping_limit = mysql_thread___query_digests_grouping_limit; + opts.groups_grouping_limit = mysql_thread___query_digests_groups_grouping_limit; + opts.max_query_length = mysql_thread___query_digests_max_query_length; SQP_par_t qp; memset(&qp, 0, sizeof(qp)); char* fst_cmnt = NULL; - char* digest_text = mysql_query_digest_and_first_comment(query.c_str(), query.length(), &fst_cmnt, - ((query.length() < QUERY_DIGEST_BUF) ? qp.buf : NULL), &opts); - if (digest_text) { - qp.digest_text = digest_text; - qp.digest = SpookyHash::Hash64(digest_text, strlen(digest_text), 0); - char* ca = (char*)""; - if (mysql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; + char* digest_text = mysql_query_digest_and_first_comment(query.c_str(), query.length(), &fst_cmnt, + ((query.length() < QUERY_DIGEST_BUF) ? qp.buf : NULL), &opts); + if (digest_text) { + qp.digest_text = digest_text; + const int digest_len = strnlen(digest_text, mysql_thread___query_digests_max_digest_length); + qp.digest = SpookyHash::Hash64(digest_text, digest_len, 0); + char* ca = (char*)""; + if (mysql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; uint64_t hash2; SpookyHash myhash; myhash.Init(19, 3); myhash.Update(ui->username, strlen(ui->username)); myhash.Update(&qp.digest, sizeof(qp.digest)); diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 68de2e971..127ceb06f 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -729,15 +729,19 @@ void MySQL_Session::reset() { delete mybes; mybes=NULL; } - mybe=NULL; + mybe=NULL; - with_gtid = false; - backend_closed_in_fast_forward = false; - fast_forward_grace_start_time = 0; - ffto_bypassed = false; - m_ffto.reset(); + with_gtid = false; + backend_closed_in_fast_forward = false; + fast_forward_grace_start_time = 0; + ffto_bypassed = false; + if (m_ffto) { + m_ffto->on_close(); + } + m_ffto.reset(); - //gtid_trxid = 0; gtid_hid = -1; + //gtid_trxid = 0; + gtid_hid = -1; memset(gtid_buf,0,sizeof(gtid_buf)); if (session_type == PROXYSQL_SESSION_SQLITE) { SQLite3_Session *sqlite_sess = (SQLite3_Session *)thread->gen_args; @@ -759,9 +763,6 @@ void MySQL_Session::reset() { * @brief Destructor for the MySQL session. */ MySQL_Session::~MySQL_Session() { - if (m_ffto) { - m_ffto->on_close(); - } reset(); // we moved this out to allow CHANGE_USER @@ -4190,6 +4191,11 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___genai_s if (written != sizeof(hdr)) { proxy_error("GenAI: Failed to write request header to fd %d: %s\n", fds[0], strerror(errno)); + auto it = pending_genai_requests_.find(hdr.request_id); + if (it != pending_genai_requests_.end() && it->second.original_pkt) { + it->second.original_pkt->ptr = nullptr; + it->second.original_pkt->size = 0; + } genai_cleanup_request(hdr.request_id); client_myds->myprot.generate_pkt_ERR(true, NULL, NULL, 1, 1263, (char*)"HY000", "Failed to send request to GenAI module", true); @@ -4207,6 +4213,11 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___genai_s } proxy_error("GenAI: Failed to write JSON query to fd %d: %s\n", fds[0], strerror(errno)); + auto it = pending_genai_requests_.find(hdr.request_id); + if (it != pending_genai_requests_.end() && it->second.original_pkt) { + it->second.original_pkt->ptr = nullptr; + it->second.original_pkt->size = 0; + } genai_cleanup_request(hdr.request_id); client_myds->myprot.generate_pkt_ERR(true, NULL, NULL, 1, 1264, (char*)"HY000", "Failed to send query to GenAI module", true); @@ -4832,6 +4843,9 @@ void MySQL_Session::observe_ffto_client_packet(const PtrSize_t& pkt) { if (pkt.size > (size_t)mysql_thread___ffto_max_buffer_size) { ffto_bypassed = true; + if (m_ffto) { + m_ffto->on_close(); + } m_ffto.reset(); return; } @@ -6024,16 +6038,23 @@ handler_again: // register the mysql_data_stream thread->mypolls.add(POLLIN|POLLOUT, mybe->server_myds->fd, mybe->server_myds, thread->curtime); } - if (mysql_thread___ffto_enabled && !ffto_bypassed && m_ffto) { - for (unsigned int i = 0; i < mybe->server_myds->PSarrayIN->len; i++) { - if (mybe->server_myds->PSarrayIN->pdata[i].size > (size_t)mysql_thread___ffto_max_buffer_size) { - ffto_bypassed = true; - m_ffto.reset(); - break; - } - m_ffto->on_server_data((const char*)mybe->server_myds->PSarrayIN->pdata[i].ptr, mybe->server_myds->PSarrayIN->pdata[i].size); - } - } client_myds->PSarrayOUT->copy_add(mybe->server_myds->PSarrayIN, 0, mybe->server_myds->PSarrayIN->len); + if (mysql_thread___ffto_enabled && !ffto_bypassed && m_ffto) { + for (unsigned int i = 0; i < mybe->server_myds->PSarrayIN->len; i++) { + if (mybe->server_myds->PSarrayIN->pdata[i].size > (size_t)mysql_thread___ffto_max_buffer_size) { + ffto_bypassed = true; + if (m_ffto) { + m_ffto->on_close(); + } + m_ffto.reset(); + break; + } + m_ffto->on_server_data( + (const char*)mybe->server_myds->PSarrayIN->pdata[i].ptr, + mybe->server_myds->PSarrayIN->pdata[i].size + ); + } + } + client_myds->PSarrayOUT->copy_add(mybe->server_myds->PSarrayIN, 0, mybe->server_myds->PSarrayIN->len); while (mybe->server_myds->PSarrayIN->len) mybe->server_myds->PSarrayIN->remove_index(mybe->server_myds->PSarrayIN->len-1,NULL); break; case CONNECTING_CLIENT: @@ -9085,6 +9106,10 @@ bool MySQL_Session::handle_command_query_kill(PtrSize_t *pkt) { if (CurrentQuery.MyComQueryCmd == MYSQL_COM_QUERY_KILL) { char* qu = mysql_query_strip_comments((char *)pkt->ptr+1+sizeof(mysql_hdr), pkt->size-1-sizeof(mysql_hdr), mysql_thread___query_digests_lowercase); + if (!qu) { + proxy_error("Failed to normalize KILL query for digest matching (out of memory)\n"); + return false; + } string nq=string(qu,strlen(qu)); re2::RE2::Options *opt2=new re2::RE2::Options(RE2::Quiet); opt2->set_case_sensitive(false); diff --git a/lib/PgSQLFFTO.cpp b/lib/PgSQLFFTO.cpp index c22639dad..5c2df046a 100644 --- a/lib/PgSQLFFTO.cpp +++ b/lib/PgSQLFFTO.cpp @@ -80,6 +80,11 @@ void PgSQLFFTO::on_client_data(const char* buf, std::size_t len) { while (m_client_buffer.size() - m_client_offset >= 5) { char type = m_client_buffer[m_client_offset]; uint32_t msg_len; memcpy(&msg_len, &m_client_buffer[m_client_offset + 1], 4); msg_len = ntohl(msg_len); + if (msg_len > (uint32_t)pgsql_thread___ffto_max_buffer_size) { + m_session->ffto_bypassed = true; + on_close(); + return; + } if (msg_len < 4 || msg_len > 1024 * 1024 * 1024) { // Sanity check on_close(); m_client_buffer.clear(); m_client_offset = 0; @@ -271,7 +276,7 @@ void PgSQLFFTO::report_query_stats(const std::string& query, unsigned long long options opts; opts.lowercase = pgsql_thread___query_digests_lowercase; opts.replace_null = pgsql_thread___query_digests_replace_null; - opts.replace_number = !pgsql_thread___query_digests_no_digits; + opts.replace_number = pgsql_thread___query_digests_no_digits; opts.keep_comment = pgsql_thread___query_digests_keep_comment; opts.grouping_limit = pgsql_thread___query_digests_grouping_limit; opts.groups_grouping_limit = pgsql_thread___query_digests_groups_grouping_limit; @@ -283,7 +288,8 @@ void PgSQLFFTO::report_query_stats(const std::string& query, unsigned long long ((query.length() < QUERY_DIGEST_BUF) ? qp.buf : NULL), &opts); if (digest_text) { qp.digest_text = digest_text; - qp.digest = SpookyHash::Hash64(digest_text, strlen(digest_text), 0); + const int digest_len = strnlen(digest_text, pgsql_thread___query_digests_max_digest_length); + qp.digest = SpookyHash::Hash64(digest_text, digest_len, 0); char* ca = (char*)""; if (pgsql_thread___query_digests_track_hostname && m_session->client_myds->addr.addr) ca = m_session->client_myds->addr.addr; uint64_t hash2; SpookyHash myhash; myhash.Init(19, 3); diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index c096514a1..95d9cb417 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -306,17 +306,18 @@ void PgSQL_Session::reset() { } } } - if (client_myds && client_myds->myconn) { - client_myds->myconn->reset(); - } - extended_query_phase = EXTQ_PHASE_IDLE; - ffto_bypassed = false; - m_ffto.reset(); - }PgSQL_Session::~PgSQL_Session() { + if (client_myds && client_myds->myconn) { + client_myds->myconn->reset(); + } + extended_query_phase = EXTQ_PHASE_IDLE; + ffto_bypassed = false; if (m_ffto) { m_ffto->on_close(); } + m_ffto.reset(); +} +PgSQL_Session::~PgSQL_Session() { if (locked_on_hostgroup >= 0) { thread->status_variables.stvar[st_var_hostgroup_locked]--; } @@ -2284,22 +2285,25 @@ __implicit_sync: break; } break; - case FAST_FORWARD: - if (pgsql_thread___ffto_enabled && !ffto_bypassed) { - if (pkt.size > (size_t)pgsql_thread___ffto_max_buffer_size) { - ffto_bypassed = true; - m_ffto.reset(); - } else { - if (!m_ffto) { - m_ffto = std::make_unique(this); - } - if (m_ffto) { - m_ffto->on_client_data((const char*)pkt.ptr, pkt.size); + case FAST_FORWARD: + if (pgsql_thread___ffto_enabled && !ffto_bypassed) { + if (pkt.size > (size_t)pgsql_thread___ffto_max_buffer_size) { + ffto_bypassed = true; + if (m_ffto) { + m_ffto->on_close(); + } + m_ffto.reset(); + } else { + if (!m_ffto) { + m_ffto = std::make_unique(this); + } + if (m_ffto) { + m_ffto->on_client_data((const char*)pkt.ptr, pkt.size); + } } } - } - mybe->server_myds->PSarrayOUT->add(pkt.ptr, pkt.size); - break; + mybe->server_myds->PSarrayOUT->add(pkt.ptr, pkt.size); + break; // This state is required because it covers the following situation: // 1. A new connection is created by a client and the 'FAST_FORWARD' mode is enabled. // 2. The first packet received for this connection isn't a whole packet, i.e, it's either @@ -2725,20 +2729,27 @@ handler_again: break; case FAST_FORWARD: { - if (mybe->server_myds->mypolls == NULL) { - // register the PgSQL_Data_Stream - thread->mypolls.add(POLLIN | POLLOUT, mybe->server_myds->fd, mybe->server_myds, thread->curtime); - } - if (pgsql_thread___ffto_enabled && !ffto_bypassed && m_ffto) { - for (unsigned int i = 0; i < mybe->server_myds->PSarrayIN->len; i++) { - if (mybe->server_myds->PSarrayIN->pdata[i].size > (size_t)pgsql_thread___ffto_max_buffer_size) { - ffto_bypassed = true; - m_ffto.reset(); - break; - } - m_ffto->on_server_data((const char*)mybe->server_myds->PSarrayIN->pdata[i].ptr, mybe->server_myds->PSarrayIN->pdata[i].size); - } - } client_myds->PSarrayOUT->copy_add(mybe->server_myds->PSarrayIN, 0, mybe->server_myds->PSarrayIN->len); + if (mybe->server_myds->mypolls == NULL) { + // register the PgSQL_Data_Stream + thread->mypolls.add(POLLIN | POLLOUT, mybe->server_myds->fd, mybe->server_myds, thread->curtime); + } + if (pgsql_thread___ffto_enabled && !ffto_bypassed && m_ffto) { + for (unsigned int i = 0; i < mybe->server_myds->PSarrayIN->len; i++) { + if (mybe->server_myds->PSarrayIN->pdata[i].size > (size_t)pgsql_thread___ffto_max_buffer_size) { + ffto_bypassed = true; + if (m_ffto) { + m_ffto->on_close(); + } + m_ffto.reset(); + break; + } + m_ffto->on_server_data( + (const char*)mybe->server_myds->PSarrayIN->pdata[i].ptr, + mybe->server_myds->PSarrayIN->pdata[i].size + ); + } + } + client_myds->PSarrayOUT->copy_add(mybe->server_myds->PSarrayIN, 0, mybe->server_myds->PSarrayIN->len); constexpr unsigned char ready_packet[] = { 0x5A, 0x00, 0x00, 0x00, 0x05 }; bool is_copy_ready_packet = false; @@ -6908,4 +6919,3 @@ std::string PgSQL_DateStyle_Util::datestyle_to_string(PgSQL_DateStyle_t datestyl std::string PgSQL_DateStyle_Util::datestyle_to_string(std::string_view input, const PgSQL_DateStyle_t& default_datestyle) { return datestyle_to_string(parse_datestyle(input), default_datestyle); } - diff --git a/test/tap/tap/tap.cpp b/test/tap/tap/tap.cpp index 84eb96705..cbf1a22f2 100644 --- a/test/tap/tap/tap.cpp +++ b/test/tap/tap/tap.cpp @@ -367,12 +367,14 @@ int exit_status() int noise_count = get_noise_tools_count(); stop_noise_tools(); - if (!noise_failures.empty()) { + { std::lock_guard lock(noise_failure_mutex); - for (const auto& failed_routine : noise_failures) { + if (!noise_failures.empty()) { + for (const auto& failed_routine : noise_failures) { diag("Noise failure detected in: %s", failed_routine.c_str()); + } + return EXIT_FAILURE; } - return EXIT_FAILURE; } // Add noise tools to the count of executed tests if they didn't fail diff --git a/test/tap/tap/utils.cpp b/test/tap/tap/utils.cpp index 2d1b84bfe..da20fbdc8 100644 --- a/test/tap/tap/utils.cpp +++ b/test/tap/tap/utils.cpp @@ -821,14 +821,14 @@ int wait_post_enpoint_ready(string endpoint, string post_params, uint32_t timeou return res; } -int wait_get_enpoint_ready(string endpoint, uint32_t timeout, uint32_t delay) { +int wait_get_enpoint_ready(string endpoint, uint32_t timeout, uint32_t delay, const string& userpwd) { double waited = 0; int res = -1; while (waited < timeout) { string curl_resp_err {}; uint64_t curl_res_code = 0; - int curl_res = perform_simple_get(endpoint, curl_res_code, curl_resp_err); + int curl_res = perform_simple_get(endpoint, curl_res_code, curl_resp_err, userpwd); if (curl_res != CURLE_OK || curl_res_code != 200) { diag("'curl_res': %d, 'curl_err': '%s', waiting for '%d'ms...", curl_res, curl_resp_err.c_str(), delay); diff --git a/test/tap/tap/utils.h b/test/tap/tap/utils.h index c3f02d2ac..3d066f0a1 100644 --- a/test/tap/tap/utils.h +++ b/test/tap/tap/utils.h @@ -397,7 +397,9 @@ int wait_post_enpoint_ready( std::string endpoint, std::string post_params, uint32_t timeout, uint32_t delay=100 ); -int wait_get_enpoint_ready(std::string endpoint, uint32_t timeout, uint32_t delay=100); +int wait_get_enpoint_ready( + std::string endpoint, uint32_t timeout, uint32_t delay=100, const std::string& userpwd="" +); /** * @brief Perform a simple POST query to the specified endpoint using the supplied diff --git a/test/tap/tests/mysql-set_transaction-t.cpp b/test/tap/tests/mysql-set_transaction-t.cpp index 1ada37dc0..1f75da0ab 100644 --- a/test/tap/tests/mysql-set_transaction-t.cpp +++ b/test/tap/tests/mysql-set_transaction-t.cpp @@ -127,7 +127,7 @@ int main(int argc, char** argv) { spawn_internal_noise(cl, internal_noise_rest_prometheus_poller, {{"enable_rest_api", "true"}}); spawn_internal_noise(cl, internal_noise_pgsql_traffic_v2, {{"num_connections", "100"}, {"reconnect_interval", "100"}, {"avg_delay_ms", "300"}}); - plan(48); + plan(48 + (cl.use_noise ? 3 : 0)); MYSQL* mysql = mysql_init(NULL); if (!mysql) diff --git a/test/tap/tests/pgsql-query_cache_test-t.cpp b/test/tap/tests/pgsql-query_cache_test-t.cpp index 724c55c7c..21170294c 100644 --- a/test/tap/tests/pgsql-query_cache_test-t.cpp +++ b/test/tap/tests/pgsql-query_cache_test-t.cpp @@ -956,7 +956,7 @@ void execute_query_cache_notice_test(PGconn* admin_conn, PGconn* conn) { void execute_prepared_test(PGconn* admin_conn, PGconn* conn) { // 1) Enable query-cache-for-SELECT rules (same as basic test) so the system *would* cache - // simple queries � but extended query protocol should bypass cache. + // simple queries -- but extended query protocol should bypass cache. if (!executeQueries(admin_conn, { "DELETE FROM pgsql_query_rules", "INSERT INTO pgsql_query_rules (rule_id,active,match_digest,cache_ttl) VALUES (2,1,'^SELECT',4000)",