From c3b08b6d9f1761736b14dbd3c44056d94f441810 Mon Sep 17 00:00:00 2001 From: Sanaei Date: Sun, 13 Sep 2026 12:01:56 +0200 Subject: [PATCH] fix(tgbot): guard the mock Telegram server's call counts staleButtonServer increments its per-method map from the HTTP handler, which httptest runs on one goroutine per connection. #6491's TestAdminListReadersShareTheWriterLock is the first test to reach it from several goroutines at once, so CI's race job flagged the helper's map rather than the code under test. --- internal/web/service/tgbot/tgbot_stale_button_test.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/web/service/tgbot/tgbot_stale_button_test.go b/internal/web/service/tgbot/tgbot_stale_button_test.go index 0f746ac55..91b6c04e3 100644 --- a/internal/web/service/tgbot/tgbot_stale_button_test.go +++ b/internal/web/service/tgbot/tgbot_stale_button_test.go @@ -5,6 +5,7 @@ import ( "net/http" "net/http/httptest" "path/filepath" + "sync" "testing" "github.com/mhsanaei/3x-ui/v3/internal/database" @@ -17,11 +18,14 @@ import ( // bot-dependent paths; the returned func reports per-method call counts. func staleButtonServer(t *testing.T, responses map[string]any) (*httptest.Server, func(string) int) { t.Helper() + var mu sync.Mutex counts := map[string]int{} srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { for method, body := range responses { if r.URL.Path == "/bot"+testBotToken+"/"+method { + mu.Lock() counts[method]++ + mu.Unlock() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(body) return @@ -29,7 +33,11 @@ func staleButtonServer(t *testing.T, responses map[string]any) (*httptest.Server } w.WriteHeader(http.StatusNotFound) })) - return srv, func(method string) int { return counts[method] } + return srv, func(method string) int { + mu.Lock() + defer mu.Unlock() + return counts[method] + } } func swapTestBot(t *testing.T, url string) {