60 lines
2.5 KiB
Go
60 lines
2.5 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
|
)
|
|
|
|
// R-1192 follow-up (night 2026-10-21): a host whose swap is below its guests' swap allowance raises host_swap_short
|
|
// ONCE (edge-triggered from the host's newest swap event, so repeats and a hub restart stay quiet), host_swap_ok once
|
|
// when covered, and an older agent (no numbers) is not evaluated. Operator-only (TestR1192_HostSwapEventsAreOperatorOnly
|
|
// in notify).
|
|
// RED-PROOF: with checkHostSwap not called from handleHostReport the first assertion fails (0 events).
|
|
func swapReportBody(hostID string, hostMB, guestMB int64) string {
|
|
b := validReportBody(hostID)
|
|
return strings.Replace(b, `"uptime_seconds":100}`, `"uptime_seconds":100,"host_swap_mb":`+strconv.FormatInt(hostMB, 10)+`,"guest_swap_mb":`+strconv.FormatInt(guestMB, 10)+`}`, 1)
|
|
}
|
|
|
|
func TestR1192_HostSwapShortIsRaisedOnceAndClearedOnce(t *testing.T) {
|
|
h, st, _ := newTestHandler(t)
|
|
st.SaveCustomerConfig(&store.CustomerConfig{CustomerID: "c1", APIKey: "ckey", RetrievalPassword: "p"})
|
|
st.UpsertHost(&store.Host{HostID: "h1", CustomerID: "c1", APIKey: "HKEY"})
|
|
post := func(body string) {
|
|
t.Helper()
|
|
if rr := do(h, http.MethodPost, "/host-report", "HKEY", body); rr.Code != http.StatusOK {
|
|
t.Fatalf("host-report = %d %s", rr.Code, rr.Body.String())
|
|
}
|
|
}
|
|
count := func(typ string) int {
|
|
evs, _ := st.GetEventsByType("c1", typ, time.Time{})
|
|
return len(evs)
|
|
}
|
|
post(validReportBody("h1")) // an older agent: no numbers → nothing
|
|
if count(eventHostSwapShort) != 0 {
|
|
t.Fatal("an agent that reports no swap numbers must not be evaluated")
|
|
}
|
|
post(swapReportBody("h1", 0, 4096)) // no host swap, a 4 GB guest allowance
|
|
post(swapReportBody("h1", 0, 4096))
|
|
if n := count(eventHostSwapShort); n != 1 {
|
|
t.Fatalf("host_swap_short events = %d, want exactly 1 (edge-triggered)", n)
|
|
}
|
|
evs, _ := st.GetEventsByType("c1", eventHostSwapShort, time.Time{})
|
|
if !strings.Contains(evs[0].Message, "Host h1:") || !strings.Contains(evs[0].DetailsJSON, `"guest_swap_mb":4096`) {
|
|
t.Fatalf("the alarm must name the host and both numbers: %q %s", evs[0].Message, evs[0].DetailsJSON)
|
|
}
|
|
post(swapReportBody("h1", 7935, 4096)) // the installer's 8 GB host
|
|
post(swapReportBody("h1", 7935, 4096))
|
|
if n := count(eventHostSwapOK); n != 1 {
|
|
t.Fatalf("host_swap_ok events = %d, want exactly 1", n)
|
|
}
|
|
post(swapReportBody("h1", 7935, 4096))
|
|
if count(eventHostSwapShort) != 1 {
|
|
t.Fatal("a covered host must not alarm again")
|
|
}
|
|
}
|