package health import ( "context" "errors" "testing" "time" "git.dcentral.systems/toolz/goplt/pkg/health" ) func TestNewRegistry(t *testing.T) { t.Parallel() registry := NewRegistry() if registry == nil { t.Fatal("Expected registry, got nil") } if registry.checkers == nil { t.Error("Expected checkers map, got nil") } } func TestRegistry_Register(t *testing.T) { t.Parallel() registry := NewRegistry() mockChecker := &mockChecker{ checkFunc: func(ctx context.Context) error { return nil }, } registry.Register("test", mockChecker) // Verify checker is registered registry.mu.RLock() checker, ok := registry.checkers["test"] registry.mu.RUnlock() if !ok { t.Error("Expected checker to be registered") } if checker != mockChecker { t.Error("Registered checker does not match") } } func TestRegistry_Check_AllHealthy(t *testing.T) { t.Parallel() registry := NewRegistry() registry.Register("healthy1", &mockChecker{ checkFunc: func(ctx context.Context) error { return nil }, }) registry.Register("healthy2", &mockChecker{ checkFunc: func(ctx context.Context) error { return nil }, }) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() status := registry.Check(ctx) if status.Status != health.StatusHealthy { t.Errorf("Expected status healthy, got %s", status.Status) } if len(status.Components) != 2 { t.Errorf("Expected 2 components, got %d", len(status.Components)) } for _, component := range status.Components { if component.Status != health.StatusHealthy { t.Errorf("Expected component %s to be healthy, got %s", component.Name, component.Status) } } } func TestRegistry_Check_OneUnhealthy(t *testing.T) { t.Parallel() registry := NewRegistry() registry.Register("healthy", &mockChecker{ checkFunc: func(ctx context.Context) error { return nil }, }) registry.Register("unhealthy", &mockChecker{ checkFunc: func(ctx context.Context) error { return errors.New("component failed") }, }) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() status := registry.Check(ctx) if status.Status != health.StatusUnhealthy { t.Errorf("Expected status unhealthy, got %s", status.Status) } if len(status.Components) != 2 { t.Errorf("Expected 2 components, got %d", len(status.Components)) } unhealthyFound := false for _, component := range status.Components { if component.Name == "unhealthy" { unhealthyFound = true if component.Status != health.StatusUnhealthy { t.Errorf("Expected unhealthy component to be unhealthy, got %s", component.Status) } if component.Error == "" { t.Error("Expected error message for unhealthy component") } } } if !unhealthyFound { t.Error("Expected to find unhealthy component") } } func TestRegistry_LivenessCheck(t *testing.T) { t.Parallel() registry := NewRegistry() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() status := registry.LivenessCheck(ctx) if status.Status != health.StatusHealthy { t.Errorf("Expected liveness check to be healthy, got %s", status.Status) } if len(status.Components) != 0 { t.Errorf("Expected no components in liveness check, got %d", len(status.Components)) } } func TestRegistry_ReadinessCheck(t *testing.T) { t.Parallel() registry := NewRegistry() registry.Register("test", &mockChecker{ checkFunc: func(ctx context.Context) error { return nil }, }) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() status := registry.ReadinessCheck(ctx) if status.Status != health.StatusHealthy { t.Errorf("Expected readiness check to be healthy, got %s", status.Status) } if len(status.Components) != 1 { t.Errorf("Expected 1 component in readiness check, got %d", len(status.Components)) } } // mockChecker is a mock implementation of HealthChecker for testing. type mockChecker struct { checkFunc func(ctx context.Context) error } func (m *mockChecker) Check(ctx context.Context) error { if m.checkFunc != nil { return m.checkFunc(ctx) } return nil }