diff --git a/main.go b/main.go index a811de7..5b1916e 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "time" ) @@ -12,11 +13,14 @@ func checkMonitors(config *Config) { // Should probably consider refactoring everything below here if alertNotice != nil { - log.Printf("DEBUG: Recieved an alert notice: %v", alertNotice) + log.Printf("DEBUG: Recieved an alert notice from %s", alertNotice.MonitorName) alertNames := monitor.GetAlertNames(alertNotice.IsUp) if alertNames == nil { // TODO: Should this be a panic? Should this be validated against? Probably - log.Printf("WARNING: Found alert, but no alert mechanisms exist: %v", alertNotice) + log.Printf( + "WARNING: Recieved alert, but no alert mechanisms exist. MonitorName=%s IsUp=%t", + alertNotice.MonitorName, alertNotice.IsUp, + ) } for _, alertName := range alertNames { if alert, ok := config.Alerts[alertName]; ok { @@ -29,12 +33,12 @@ func checkMonitors(config *Config) { output, ) // TODO: Maybe return this error instead of panicking here - log.Fatalf( + panic(fmt.Errorf( "ERROR: Unsuccessfully triggered alert '%s'. "+ "Crashing to avoid false negatives: %v", alert.Name, err, - ) + )) } } else { // TODO: Maybe panic here. Also, probably validate up front diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..b574dcc --- /dev/null +++ b/main_test.go @@ -0,0 +1,122 @@ +package main + +import "testing" + +func TestCheckMonitors(t *testing.T) { + cases := []struct { + config Config + expectPanic bool + name string + }{ + { + config: Config{}, + expectPanic: false, + name: "Empty", + }, + { + config: Config{ + Monitors: []*Monitor{ + &Monitor{ + Name: "Success", + Command: []string{"true"}, + }, + }, + }, + expectPanic: false, + name: "Monitor success, no alerts", + }, + { + config: Config{ + Monitors: []*Monitor{ + &Monitor{ + Name: "Failure", + Command: []string{"false"}, + AlertAfter: 1, + }, + &Monitor{ + Name: "Failure", + Command: []string{"false"}, + AlertDown: []string{"unknown"}, + AlertAfter: 1, + }, + }, + }, + expectPanic: false, + name: "Monitor failure, no and unknown alerts", + }, + { + config: Config{ + Monitors: []*Monitor{ + &Monitor{ + Name: "Success", + Command: []string{"ls"}, + alertCount: 1, + }, + &Monitor{ + Name: "Success", + Command: []string{"true"}, + AlertUp: []string{"unknown"}, + alertCount: 1, + }, + }, + }, + expectPanic: false, + name: "Monitor recovery, no alerts", + }, + { + config: Config{ + Monitors: []*Monitor{ + &Monitor{ + Name: "Failure", + Command: []string{"false"}, + AlertDown: []string{"good"}, + AlertAfter: 1, + }, + }, + Alerts: map[string]*Alert{ + "good": &Alert{ + Command: []string{"true"}, + }, + }, + }, + expectPanic: false, + name: "Monitor failure, successful alert", + }, + { + config: Config{ + Monitors: []*Monitor{ + &Monitor{ + Name: "Failure", + Command: []string{"false"}, + AlertDown: []string{"bad"}, + AlertAfter: 1, + }, + }, + Alerts: map[string]*Alert{ + "bad": &Alert{ + Name: "bad", + Command: []string{"false"}, + }, + }, + }, + expectPanic: true, + name: "Monitor failure, bad alert", + }, + } + + for _, c := range cases { + // Create new function so that deferred recovery can run at end of each test case + func() { + // Set up recover to catch panic + defer func() { + if r := recover(); r == nil { + if c.expectPanic { + t.Errorf("checkMonitors(%s): Expected panic, the code did not panic", c.name) + } + } + }() + c.config.Init() + checkMonitors(&c.config) + }() + } +}