package status import ( "context" "encoding/json" "strings" "testing" "time" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" ) // TestBoxMetricsCarryThePlatformSelfUpdateState proves Task 5's three new // Probes fields (Platform, SystemChannel, System) reach Box.Metrics, reach // the wire under their json names, count toward the "something is known" // emptiness guard on their own, and — like every other Metrics field — never // reach the public fleet feed. func TestBoxMetricsCarryThePlatformSelfUpdateState(t *testing.T) { at := time.Date(2026, 9, 6, 9, 0, 0, 0, time.UTC) p := Probes{Release: "v1", Platform: "linux-arm64", SystemChannel: "canary", System: &SystemState{Channel: "canary", Version: "v2", PromotedAt: at, Outcome: "rolled-back", Reason: "gate", At: at}} b := CollectBox(nil, p, at) if b.Metrics == nil || b.Metrics.Platform != "linux-arm64" || b.Metrics.SystemChannel != "canary" || b.Metrics.System == nil || b.Metrics.System.Outcome != "rolled-back" { t.Fatalf("metrics = %+v", b.Metrics) } out, _ := json.Marshal(b) for _, want := range []string{`"platform":"linux-arm64"`, `"system_channel":"canary"`, `"outcome":"rolled-back"`} { if !strings.Contains(string(out), want) { t.Errorf("json lacks %s: %s", want, out) } } // A box with only the new fields is not "empty". b2 := CollectBox(nil, Probes{Platform: "linux-arm64"}, at) if b2.Metrics == nil { t.Fatal("platform alone must produce a metrics block") } // The public fleet feed still never carries the metrics block. s := release.NewDirStore(t.TempDir()) if err := WriteBox(context.Background(), s, b); err != nil { t.Fatal(err) } f, err := BuildFleet(context.Background(), s, nil, at, 5*time.Minute) if err != nil { t.Fatal(err) } fb, _ := json.Marshal(f) if strings.Contains(string(fb), "system_channel") || strings.Contains(string(fb), "rolled-back") { t.Fatalf("fleet.json leaked the private metrics: %s", fb) } } // TestCollectBoxCarriesTheLayoutReport pins Task 5's Probes.Layout: it // round-trips through CollectBox into Box.Metrics.Layout and onto the wire // under its json names, and a Probes with none produces no "layout" key at // all — the same "unknown stays absent, never a guess" rule every other // Metrics field follows. func TestCollectBoxCarriesTheLayoutReport(t *testing.T) { at := time.Date(2026, 9, 25, 9, 0, 0, 0, time.UTC) report := &LayoutReport{ Mode: "nested", Rows: map[string]RowLayout{ "h.example.com": {Layout: "nested"}, "f.example.com": {Layout: "foreign", Reason: `db "x" socket "y" are neither the flat nor the nested defaults`}, "q.example.com": {Layout: "nested", Note: "migrated at 2026-10-06T00:00:00Z: kept aside /data/layout/aside/q.example.com/creds.q-1-ab"}, }, } b := CollectBox(nil, Probes{Layout: report}, at) if b.Metrics == nil || b.Metrics.Layout == nil { t.Fatalf("metrics.layout missing: %+v", b.Metrics) } if b.Metrics.Layout.Mode != "nested" { t.Errorf("mode = %q, want nested", b.Metrics.Layout.Mode) } if row := b.Metrics.Layout.Rows["h.example.com"]; row.Layout != "nested" || row.Reason != "" { t.Errorf("h.example.com row = %+v", row) } if row := b.Metrics.Layout.Rows["f.example.com"]; row.Layout != "foreign" || row.Reason == "" { t.Errorf("f.example.com row = %+v", row) } out, err := json.Marshal(b) if err != nil { t.Fatal(err) } for _, want := range []string{`"layout":{"mode":"nested"`, `"h.example.com":{"layout":"nested"}`, `"f.example.com":{"layout":"foreign","reason":`, `"q.example.com":{"layout":"nested","note":"migrated at`} { if !strings.Contains(string(out), want) { t.Errorf("json lacks %s: %s", want, out) } } // A Probes with no Layout at all publishes no "layout" key — not the // field present-and-null, absent entirely, same as every other Metrics // field with nothing to report. b2 := CollectBox(nil, Probes{Release: "v1"}, at) out2, err := json.Marshal(b2) if err != nil { t.Fatal(err) } if strings.Contains(string(out2), `"layout"`) { t.Fatalf("layout key present with no Layout probe: %s", out2) } } // TestBoxMetricsCarryAlertDelivery pins discussion #192's visibility ask: a // box says whether its own alert rules have anywhere to deliver, an // all-off answer is published (it is the answer that matters), the field // alone makes a metrics block, and the public fleet feed never sees it. func TestBoxMetricsCarryAlertDelivery(t *testing.T) { at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) none := CollectBox(nil, Probes{Alerts: &AlertDelivery{}}, at) if none.Metrics == nil || none.Metrics.Alerts == nil || none.Metrics.Alerts.Delivered() { t.Fatalf("an all-off answer must publish as not delivered: %+v", none.Metrics) } out, _ := json.Marshal(none) if !strings.Contains(string(out), `"alerts":{"webhook":false,"sns":false}`) { t.Errorf("json lacks the explicit all-off alerts block: %s", out) } unknown := CollectBox(nil, Probes{Release: "v1"}, at) if unknown.Metrics == nil || unknown.Metrics.Alerts != nil { t.Errorf("an unasked box must publish no alerts key: %+v", unknown.Metrics) } sns := CollectBox(nil, Probes{Alerts: &AlertDelivery{SNS: true, SNSFailures: 2}}, at) out, _ = json.Marshal(sns) if !strings.Contains(string(out), `"sns":true`) || !strings.Contains(string(out), `"sns_failures":2`) { t.Errorf("json lacks the sns sink or its failures: %s", out) } s := release.NewDirStore(t.TempDir()) if err := WriteBox(context.Background(), s, none); err != nil { t.Fatal(err) } f, err := BuildFleet(context.Background(), s, nil, at, 5*time.Minute) if err != nil { t.Fatal(err) } fb, _ := json.Marshal(f) if strings.Contains(string(fb), "alerts") || strings.Contains(string(fb), "webhook") { t.Fatalf("fleet.json leaked the alert-sink state: %s", fb) } } func TestCollectBoxCarriesGeoIP(t *testing.T) { box := CollectBox(nil, Probes{GeoIP: &GeoIPState{Mode: "mirror", SHA256: "abc", Type: "DBIP-City-Lite"}}, time.Now()) if box.Metrics == nil || box.Metrics.GeoIP == nil || box.Metrics.GeoIP.SHA256 != "abc" { t.Fatalf("metrics = %+v", box.Metrics) } raw, err := json.Marshal(box) if err != nil { t.Fatal(err) } if !strings.Contains(string(raw), `"geoip":{"mode":"mirror"`) { t.Fatalf("json = %s", raw) } if b := CollectBox(nil, Probes{}, time.Now()); b.Metrics != nil { t.Fatal("no GeoIP and nothing else known must still mean no metrics block") } } func TestTheRolloutReportRidesThePrivateMetrics(t *testing.T) { r := &RolloutReport{Hosts: map[string]HostRollout{"a.example.com": {App: "blog", Installed: "v2", Serving: "v1", Attempt: AttemptFailed, HeldBy: "v2", Reason: ReasonHealth}}} box := CollectBox(nil, Probes{Rollout: r}, time.Now()) if box.Metrics == nil || box.Metrics.Rollout == nil || box.Metrics.Rollout.Hosts["a.example.com"].HeldBy != "v2" { t.Fatalf("metrics = %+v", box.Metrics) } if b := CollectBox(nil, Probes{}, time.Now()); b.Metrics != nil { t.Fatal("the flag off publishes no rollout block and no Metrics because of it") } } // RouteServing is the build the agent started for each route (plan 5's // ServingVersion), carried beside RouteVersions, root's install stamp. func TestCollectBoxCarriesTheServingBuild(t *testing.T) { routes := []registry.Route{ {Host: "side.titogo.bab.sidecar.internal", Kind: "sidecar", Version: "v2", ServingVersion: "v1"}, {Host: "never.titogo.bab.sidecar.internal", Kind: "sidecar", Version: "v2"}, {Host: "alias.example.com", Platform: true, ServingVersion: "v9"}, } b := CollectBox(routes, Probes{MachineID: "m"}, time.Now()) if b.Metrics == nil || b.Metrics.RouteServing["side.titogo.bab.sidecar.internal"] != "v1" { t.Fatalf("RouteServing = %+v", b.Metrics) } if _, ok := b.Metrics.RouteServing["never.titogo.bab.sidecar.internal"]; ok { t.Error("a route that never started has a serving build") } if _, ok := b.Metrics.RouteServing["alias.example.com"]; ok { t.Error("a platform alias carries a serving build") } }