package snapshot import ( "context" "errors" "testing" "time" "mfd-monitor-agent/internal/status" ) // TestCollectorFailuresReturnPartialSnapshot verifies failed collectors do not fail snapshots. func TestCollectorFailuresReturnPartialSnapshot(t *testing.T) { cache := NewCache([]Collector{ CollectorFunc(func(context.Context, *status.HostStatus) error { return nil }), CollectorFunc(func(context.Context, *status.HostStatus) error { return errors.New("permission denied") }), }, "test", time.Now()) got := cache.Collect(context.Background()) if got.Agent.SnapshotStatus != "partial" { t.Fatalf("snapshot status = %q", got.Agent.SnapshotStatus) } if len(got.Errors) != 1 || got.Errors[0].Message != "permission denied" { t.Fatalf("errors = %+v", got.Errors) } } // TestCacheStoresLastSnapshot verifies successful collection is cached. func TestCacheStoresLastSnapshot(t *testing.T) { cache := NewCache([]Collector{ CollectorFunc(func(_ context.Context, out *status.HostStatus) error { out.Host.Hostname = "host-a" return nil }), }, "test", time.Now()) cache.Collect(context.Background()) got, ok := cache.Get() if !ok { t.Fatal("expected cached snapshot") } if got.Host.Hostname != "host-a" { t.Fatalf("hostname = %q", got.Host.Hostname) } } // TestRunCollectsImmediately verifies Run collects before the first interval tick. func TestRunCollectsImmediately(t *testing.T) { collected := make(chan struct{}) cache := NewCache([]Collector{ CollectorFunc(func(_ context.Context, out *status.HostStatus) error { out.Host.Hostname = "host-a" close(collected) return nil }), }, "test", time.Now()) ctx, cancel := context.WithCancel(context.Background()) defer cancel() go cache.Run(ctx, time.Hour, time.Second) select { case <-collected: case <-time.After(time.Second): t.Fatal("initial collection did not run") } got, ok := cache.Get() if !ok { t.Fatal("expected cached snapshot") } if got.Host.Hostname != "host-a" { t.Fatalf("hostname = %q", got.Host.Hostname) } } // TestCollectWithTimeoutMarksCanceledCollectorPartial verifies timeout errors are partial. func TestCollectWithTimeoutMarksCanceledCollectorPartial(t *testing.T) { cache := NewCache([]Collector{ CollectorFunc(func(ctx context.Context, _ *status.HostStatus) error { <-ctx.Done() return ctx.Err() }), }, "test", time.Now()) cache.collectWithTimeout(context.Background(), time.Millisecond) got, ok := cache.Get() if !ok { t.Fatal("expected cached snapshot") } if got.Agent.SnapshotStatus != "partial" { t.Fatalf("snapshot status = %q", got.Agent.SnapshotStatus) } if len(got.Errors) != 1 || got.Errors[0].Message != context.DeadlineExceeded.Error() { t.Fatalf("errors = %+v", got.Errors) } }