package runtime import ( "context" "errors" "testing" "browser.local/run/config" ) func TestWorkerReportsMetricsWithCurrentSessionAndManagedProcessState(t *testing.T) { client := newFakeWorkerClient() cfg := workerTestConfig(t) cfg.ServerInstanceID = "server-worker" cfg.ComponentKind = config.PackageComponentRun managed := &metricManagedSupervisor{identity: ProcessIdentity{ServerInstanceID: cfg.ServerInstanceID, RunEndpointID: cfg.RunEndpointID, Scope: "server", State: "running"}} worker, err := NewWorker(cfg, client, WithManagedProcessSupervisor(managed), WithMetricCollector(metricCollectorStub{disk: 42.5})) if err != nil { t.Fatalf("new worker: %v", err) } if err := worker.Register(context.Background()); err != nil { t.Fatalf("register: %v", err) } if err := worker.ReportMetricsOnce(context.Background()); err != nil { t.Fatalf("report metrics: %v", err) } if len(client.metricRequests) != 1 { t.Fatalf("expected one metric request, got %d", len(client.metricRequests)) } request := client.metricRequests[0] if request.RunEndpointID != cfg.RunEndpointID || request.SessionToken != "session-token" || len(request.Samples) != 1 { t.Fatalf("expected registered session metric request, got %+v", request) } sample := request.Samples[0] if !sample.Online || sample.Source != "run" || sample.PlayerCount != nil || sample.TPS != nil || sample.LatencyMS != nil || sample.DiskPercent == nil || *sample.DiskPercent != 42.5 { t.Fatalf("unexpected generic metric sample: %+v", sample) } } func TestWorkerReportsOfflineWhenManagedProcessExitedAndOmitsUnavailableUtilization(t *testing.T) { client := newFakeWorkerClient() cfg := workerTestConfig(t) cfg.ServerInstanceID = "server-worker" cfg.ComponentKind = config.PackageComponentRun managed := &metricManagedSupervisor{identity: ProcessIdentity{ServerInstanceID: cfg.ServerInstanceID, RunEndpointID: cfg.RunEndpointID, Scope: "server", State: "exited"}} worker, err := NewWorker(cfg, client, WithManagedProcessSupervisor(managed), WithMetricCollector(metricCollectorError{})) if err != nil { t.Fatalf("new worker: %v", err) } if err := worker.Register(context.Background()); err != nil { t.Fatalf("register: %v", err) } if err := worker.ReportMetricsOnce(context.Background()); err != nil { t.Fatalf("report metrics: %v", err) } sample := client.metricRequests[0].Samples[0] if sample.Online || sample.CPUPercent != nil || sample.MemoryPercent != nil || sample.DiskPercent != nil { t.Fatalf("expected offline sample without unavailable utilization, got %+v", sample) } } func TestWorkerReportsAvailableUtilizationWhenOneMetricFails(t *testing.T) { client := newFakeWorkerClient() cfg := workerTestConfig(t) cfg.ServerInstanceID = "server-worker" cfg.ComponentKind = config.PackageComponentRun worker, err := NewWorker(cfg, client, WithMetricCollector(metricCollectorPartial{disk: 42.5})) if err != nil { t.Fatalf("new worker: %v", err) } if err := worker.Register(context.Background()); err != nil { t.Fatalf("register: %v", err) } if err := worker.ReportMetricsOnce(context.Background()); err != nil { t.Fatalf("report metrics: %v", err) } sample := client.metricRequests[0].Samples[0] if sample.DiskPercent == nil || *sample.DiskPercent != 42.5 { t.Fatalf("expected available disk utilization to be reported, got %+v", sample) } } func TestMetricUploadFailureDoesNotFailReportingCycle(t *testing.T) { client := newFakeWorkerClient() client.metricErr = errors.New("platform unavailable") cfg := workerTestConfig(t) cfg.ServerInstanceID = "server-worker" cfg.ComponentKind = config.PackageComponentRun worker, err := NewWorker(cfg, client) if err != nil { t.Fatalf("new worker: %v", err) } if err := worker.Register(context.Background()); err != nil { t.Fatalf("register: %v", err) } worker.reportMetricsDegraded(context.Background(), "test") if len(client.metricRequests) != 1 { t.Fatalf("expected degraded metric attempt, got %d", len(client.metricRequests)) } } type metricManagedSupervisor struct{ identity ProcessIdentity } func (supervisor *metricManagedSupervisor) Start(context.Context, ProcessCommand, ProcessIdentity, ManagedProcessOutput) (ProcessIdentity, error) { return supervisor.identity, nil } func (supervisor *metricManagedSupervisor) Stop(context.Context, ProcessIdentity) (ProcessIdentity, error) { return supervisor.identity, nil } func (supervisor *metricManagedSupervisor) Status(ProcessIdentity) ProcessIdentity { return supervisor.identity } func (supervisor *metricManagedSupervisor) ResumeOutput(ManagedProcessOutput) {} func (supervisor *metricManagedSupervisor) ManagedProcessObservations() []ProcessIdentity { return []ProcessIdentity{supervisor.identity} } type metricCollectorStub struct{ disk float64 } func (collector metricCollectorStub) Collect(context.Context, string) (MetricUtilization, error) { return MetricUtilization{DiskPercent: &collector.disk}, nil } type metricCollectorError struct{} func (metricCollectorError) Collect(context.Context, string) (MetricUtilization, error) { return MetricUtilization{}, errors.New("collector unavailable") } type metricCollectorPartial struct{ disk float64 } func (collector metricCollectorPartial) Collect(context.Context, string) (MetricUtilization, error) { return MetricUtilization{DiskPercent: &collector.disk}, errors.New("CPU unavailable") }