package healthcheck import ( "reflect" "testing" healthcheckPb "github.com/runconduit/conduit/controller/gen/common/healthcheck" ) type mockSubsystem struct { checksToReturn []*healthcheckPb.CheckResult } func (m *mockSubsystem) SelfCheck() []*healthcheckPb.CheckResult { return m.checksToReturn } func TestSelfChecker(t *testing.T) { workingSubsystem1 := &mockSubsystem{ checksToReturn: []*healthcheckPb.CheckResult{ {SubsystemName: "w1", CheckDescription: "w1a", Status: healthcheckPb.CheckStatus_OK}, {SubsystemName: "w1", CheckDescription: "w1b", Status: healthcheckPb.CheckStatus_OK}, }, } workingSubsystem2 := &mockSubsystem{ checksToReturn: []*healthcheckPb.CheckResult{ {SubsystemName: "w2", CheckDescription: "w2a", Status: healthcheckPb.CheckStatus_OK}, {SubsystemName: "w2", CheckDescription: "w2b", Status: healthcheckPb.CheckStatus_OK}, }, } failingSubsystem1 := &mockSubsystem{ checksToReturn: []*healthcheckPb.CheckResult{ {SubsystemName: "f1", CheckDescription: "fa", Status: healthcheckPb.CheckStatus_OK}, {SubsystemName: "f1", CheckDescription: "fb", Status: healthcheckPb.CheckStatus_FAIL}, }, } errorSubsystem1 := &mockSubsystem{ checksToReturn: []*healthcheckPb.CheckResult{ {SubsystemName: "e1", CheckDescription: "ea", Status: healthcheckPb.CheckStatus_ERROR}, {SubsystemName: "e1", CheckDescription: "eb", Status: healthcheckPb.CheckStatus_OK}, }, } t.Run("Notifies observer of all results", func(t *testing.T) { healthChecker := MakeHealthChecker() healthChecker.Add(workingSubsystem1) healthChecker.Add(workingSubsystem2) healthChecker.Add(failingSubsystem1) observedResults := make([]*healthcheckPb.CheckResult, 0) observer := func(r *healthcheckPb.CheckResult) { observedResults = append(observedResults, r) } allChecks := make([]*healthcheckPb.CheckResult, 0) allChecks = append(allChecks, workingSubsystem1.checksToReturn...) allChecks = append(allChecks, workingSubsystem2.checksToReturn...) allChecks = append(allChecks, failingSubsystem1.checksToReturn...) expectedResults := make([]*healthcheckPb.CheckResult, 0) for _, check := range allChecks { expectedResults = append(expectedResults, check) } healthChecker.PerformCheck(observer) observedLength := len(observedResults) expectedLength := len(expectedResults) if expectedLength != observedLength { t.Fatalf("Expecting observed check to contain [%d] check, got [%d]", expectedLength, observedLength) } observedResultsSet := make(map[healthcheckPb.CheckResult]bool) for _, result := range observedResults { observedResultsSet[*result] = true } for _, expected := range expectedResults { if !observedResultsSet[*expected] { t.Fatalf("Expected observed results to contain [%v], but was: %v", expected, reflect.ValueOf(observedResultsSet).MapKeys()) } } }) t.Run("Is successful if all checks were successful", func(t *testing.T) { healthChecker := MakeHealthChecker() healthChecker.Add(workingSubsystem1) healthChecker.Add(workingSubsystem2) checkStatus := healthChecker.PerformCheck(nil) if checkStatus != healthcheckPb.CheckStatus_OK { t.Fatalf("Expecting check to be successful, but got [%s]", checkStatus) } }) t.Run("Is failure if even a single test failed and no errors", func(t *testing.T) { healthChecker := MakeHealthChecker() healthChecker.Add(workingSubsystem1) healthChecker.Add(failingSubsystem1) healthChecker.Add(workingSubsystem2) checkStatus := healthChecker.PerformCheck(nil) if checkStatus != healthcheckPb.CheckStatus_FAIL { t.Fatalf("Expecting check to be error, but got [%s]", checkStatus) } }) t.Run("Is error if even a single test errored", func(t *testing.T) { healthChecker := MakeHealthChecker() healthChecker.Add(workingSubsystem1) healthChecker.Add(failingSubsystem1) healthChecker.Add(errorSubsystem1) checkStatus := healthChecker.PerformCheck(nil) if checkStatus != healthcheckPb.CheckStatus_ERROR { t.Fatalf("Expecting check to be error, but got [%s]", checkStatus) } }) }