1package daemon23import (4 "context"5 "net/http"6 "net/http/httptest"7 "testing"8)910func TestProcessHealthAndReadinessLifecycle(t *testing.T) {11 a, err := New(context.Background(), Config{DataDir: t.TempDir(), DefaultTenant: "missing"})12 if err != nil {13 t.Fatal(err)14 }15 ready := func() *httptest.ResponseRecorder {16 req := httptest.NewRequest(http.MethodGet, "http://relay.test/readyz", nil)17 res := httptest.NewRecorder()18 a.ServeHTTP(res, req)19 return res20 }21 if got := ready().Code; got != http.StatusServiceUnavailable {22 t.Fatalf("before start readiness = %d", got)23 }24 if err := a.Start(context.Background(), "http://relay.test"); err != nil {25 t.Fatal(err)26 }27 if got := ready().Code; got != http.StatusOK {28 t.Fatalf("after start readiness = %d", got)29 }30 healthReq := httptest.NewRequest(http.MethodGet, "http://relay.test/healthz", nil)31 healthRes := httptest.NewRecorder()32 a.ServeHTTP(healthRes, healthReq)33 if healthRes.Code != http.StatusOK {34 t.Fatalf("liveness = %d", healthRes.Code)35 }36 if err := a.Close(context.Background()); err != nil {37 t.Fatal(err)38 }39 if got := ready().Code; got != http.StatusServiceUnavailable {40 t.Fatalf("after close readiness = %d", got)41 }42}4344func TestProcessReadinessReportsCatalogFailure(t *testing.T) {45 a, err := New(context.Background(), Config{DataDir: t.TempDir()})46 if err != nil {47 t.Fatal(err)48 }49 if err := a.Start(context.Background(), "http://relay.test"); err != nil {50 t.Fatal(err)51 }52 if err := a.catalog.Close(); err != nil {53 t.Fatal(err)54 }55 req := httptest.NewRequest(http.MethodGet, "http://relay.test/readyz", nil)56 res := httptest.NewRecorder()57 a.ServeHTTP(res, req)58 if res.Code != http.StatusServiceUnavailable {59 t.Fatalf("closed catalog readiness = %d", res.Code)60 }61 _ = a.Close(context.Background())62}6364func TestTenantHealthObeysMaintenanceAndStorage(t *testing.T) {65 a, tenant := testTenant(t)66 request := func(path string) int {67 req := httptest.NewRequest(http.MethodGet, "http://relay.test"+path, nil)68 res := httptest.NewRecorder()69 a.ServeHTTP(res, req)70 return res.Code71 }72 if got := request("/r/main/healthz"); got != http.StatusOK {73 t.Fatalf("tenant health = %d", got)74 }75 _, release, err := tenant.beginMaintenance(context.Background())76 if err != nil {77 t.Fatal(err)78 }79 if got := request("/r/main/readyz"); got != http.StatusServiceUnavailable {80 t.Fatalf("tenant readiness during maintenance = %d", got)81 }82 release()83 if got := request("/r/main/readyz"); got != http.StatusOK {84 t.Fatalf("tenant readiness after maintenance = %d", got)85 }86 // Stop the tenant workers before closing their shared store. Closing the87 // database underneath a live queue claim races cleanup and can turn this88 // health probe into an unrelated "database is closed" failure.89 if err := tenant.closeServices(context.Background()); err != nil {90 t.Fatal(err)91 }92 if err := tenant.store.Close(); err != nil {93 t.Fatal(err)94 }95 if got := request("/r/main/healthz"); got != http.StatusServiceUnavailable {96 t.Fatalf("tenant health after storage close = %d", got)97 }98}