Files
felhom-controller/controller/internal/agentapi/linetest_test.go
T
admin 046b808792
gates / gates (push) Successful in 1m22s
upwatch: hold a seeding torrent app for one line test, then put its limit back exactly (R-1250)
When the agent waits for quiet and qBittorrent or Transmission runs: record the limit first,
hold at 1 KiB/s, ask the agent for a test on request, put the old limit back (deferred; a
household change during the test stays). Start-up puts back a limit a killed controller left;
the 50 % rule skips while a hold record exists. Commit only.
2026-10-24 13:19:07 +02:00

65 lines
2.6 KiB
Go

package agentapi
import (
"context"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
// R-1247: GET /host/line-test decodes the agent's weekly line test, and an agent before the route is a typed 404 (the
// controller reads it as „not measured" → no qBittorrent limit).
func TestLineTestDecodesAndAnOlderAgentIs404(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("GET /host/line-test", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"ok":true,"data":{"present":true,"mbps":90.7,"measured_at":"2026-10-24T06:31:00Z","method":"iperf3-tunnel"}}`))
})
s := httptest.NewTLSServer(mux)
defer s.Close()
st, err := clientFor(t, s, strings.TrimPrefix(s.URL, "https://")).LineTest(context.Background())
if err != nil {
t.Fatal(err)
}
if !st.Present || st.Mbps != 90.7 || !st.MeasuredAtTime().Equal(time.Date(2026, 10, 24, 6, 31, 0, 0, time.UTC)) {
t.Fatalf("state = %+v", st)
}
old := httptest.NewTLSServer(http.NewServeMux())
defer old.Close()
_, err = clientFor(t, old, strings.TrimPrefix(old.URL, "https://")).LineTest(context.Background())
var se *StatusError
if !errors.As(err, &se) || se.Code != http.StatusNotFound {
t.Fatalf("an older agent must answer a typed 404, got %v", err)
}
}
// R-1250: the request decodes its outcome, waiting_for_quiet decodes, and the request outlasts the client's own
// timeout (the agent answers after about 55 s; the client's default is 15 s).
func TestLineTestRunOutlastsTheClientTimeout(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("GET /host/line-test", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"ok":true,"data":{"present":false,"waiting_for_quiet":true}}`))
})
mux.HandleFunc("POST /host/line-test/run", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(300 * time.Millisecond)
_, _ = w.Write([]byte(`{"ok":true,"data":{"ok":true,"mbps":93.5,"runs_mbps":[92,93.5,93]}}`))
})
s := httptest.NewTLSServer(mux)
defer s.Close()
c := clientFor(t, s, strings.TrimPrefix(s.URL, "https://"))
st, err := c.LineTest(context.Background())
if err != nil || st.Present || !st.WaitingForQuiet {
t.Fatalf("GET = %+v %v, want present:false waiting_for_quiet:true", st, err)
}
c.hc.Timeout = 100 * time.Millisecond // stands in for the 15 s default against a 55 s answer
if _, err := c.post(context.Background(), "/host/line-test/run", struct{}{}); err == nil {
t.Fatal("the plain POST should time out here — the seam does not test anything")
}
res, err := c.LineTestRun(context.Background())
if err != nil || !res.OK || res.Mbps != 93.5 || len(res.RunsMbps) != 3 {
t.Fatalf("LineTestRun = %+v %v", res, err)
}
}