Files
3x-ui-web-src/internal/mtproto/manager_mutation_test.go
T
Sanaei f727d04f65
CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Docs CI / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
v3.7.0
2026-08-24 15:07:15 +02:00

70 lines
1.9 KiB
Go

package mtproto
import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"testing"
)
// serverPort extracts the loopback port a httptest server bound to, so
// scrapeStats can rebuild the same http://127.0.0.1:<port>/stats URL.
func serverPort(t *testing.T, srv *httptest.Server) int {
t.Helper()
u, err := url.Parse(srv.URL)
if err != nil {
t.Fatalf("parse url: %v", err)
}
port, err := strconv.Atoi(u.Port())
if err != nil {
t.Fatalf("parse port: %v", err)
}
return port
}
func TestScrapeStats(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/stats" {
http.NotFound(w, r)
return
}
if r.Header.Get("Authorization") != "Bearer sesame" {
w.WriteHeader(http.StatusUnauthorized)
return
}
_, _ = io.WriteString(w, `{"started_at":"2026-01-01T00:00:00Z","total_connections":2,`+
`"users":{`+
`"alice":{"connections":2,"bytes_in":100,"bytes_out":200,"last_seen":"2026-01-01T00:01:00Z"},`+
`"bob":{"connections":0,"bytes_in":5,"bytes_out":7,"last_seen":null}}}`)
}))
defer srv.Close()
users, ok := scrapeStats(serverPort(t, srv), "sesame")
if !ok {
t.Fatal("scrapeStats should succeed against a valid /stats endpoint")
}
if len(users) != 2 {
t.Fatalf("expected 2 users, got %d: %+v", len(users), users)
}
if users["alice"].BytesIn != 100 || users["alice"].BytesOut != 200 || users["alice"].Connections != 2 {
t.Fatalf("alice stats parsed wrong: %+v", users["alice"])
}
if users["bob"].Connections != 0 || users["bob"].BytesIn != 5 {
t.Fatalf("bob stats parsed wrong: %+v", users["bob"])
}
}
func TestScrapeStatsUnreachable(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}))
port := serverPort(t, srv)
srv.Close()
if _, ok := scrapeStats(port, ""); ok {
t.Fatal("scrapeStats must report ok=false when the endpoint is unreachable")
}
}