WIP: Building tests, figuring out what I want AlertAfter to do
This commit is contained in:
parent
ba33071070
commit
061b0c980a
2
alert.go
2
alert.go
@ -54,7 +54,7 @@ func (alert *Alert) BuildTemplates() {
|
||||
)
|
||||
log.Printf("Template built: %v", alert.commandShellTemplate)
|
||||
} else {
|
||||
panic("No template provided for alert %s", alert.Name)
|
||||
log.Fatalf("No template provided for alert %s", alert.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ type Monitor struct {
|
||||
func (monitor Monitor) IsValid() bool {
|
||||
atLeastOneCommand := (monitor.CommandShell != "" || monitor.Command != nil)
|
||||
atMostOneCommand := (monitor.CommandShell == "" || monitor.Command == nil)
|
||||
return atLeastOneCommand && atMostOneCommand
|
||||
return atLeastOneCommand && atMostOneCommand && monitor.AlertAfter >= 0
|
||||
}
|
||||
|
||||
// ShouldCheck returns a boolean indicating if the Monitor is ready to be
|
||||
@ -116,9 +116,12 @@ func (monitor *Monitor) failure() (notice *AlertNotice) {
|
||||
}
|
||||
|
||||
failureCount := (monitor.failureCount - monitor.AlertAfter)
|
||||
log.Printf("Total fail %v, this fail %v", monitor.failureCount, failureCount)
|
||||
|
||||
if monitor.AlertEvery > 0 {
|
||||
// Handle integer number of failures before alerting
|
||||
modVal := failureCount % monitor.AlertEvery
|
||||
log.Printf("Alert every > 0: Mod val: %v", modVal)
|
||||
if failureCount%monitor.AlertEvery == 0 {
|
||||
notice = monitor.createAlertNotice(false)
|
||||
}
|
||||
|
188
monitor_test.go
Normal file
188
monitor_test.go
Normal file
@ -0,0 +1,188 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestMonitorIsValid tests the Monitor.IsValid()
|
||||
func TestMonitorIsValid(t *testing.T) {
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expected bool
|
||||
name string
|
||||
}{
|
||||
{Monitor{Command: []string{"echo", "test"}}, true, "Command only"},
|
||||
{Monitor{CommandShell: "echo test"}, true, "CommandShell only"},
|
||||
{Monitor{}, false, "No commands"},
|
||||
{
|
||||
Monitor{Command: []string{"echo", "test"}, CommandShell: "echo test"},
|
||||
false,
|
||||
"Both commands",
|
||||
},
|
||||
{Monitor{AlertAfter: -1}, false, "Invalid alert threshold, -1"},
|
||||
{Monitor{AlertAfter: 0}, false, "Invalid alert threshold, 0"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
actual := c.monitor.IsValid()
|
||||
if actual != c.expected {
|
||||
t.Errorf("IsValid(%v), expected=%t actual=%t", c.name, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorShouldCheck tests the Monitor.ShouldCheck()
|
||||
func TestMonitorShouldCheck(t *testing.T) {
|
||||
timeNow := time.Now()
|
||||
timeTenSecAgo := time.Now().Add(time.Second * -10)
|
||||
timeTwentySecAgo := time.Now().Add(time.Second * -20)
|
||||
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expected bool
|
||||
name string
|
||||
}{
|
||||
{Monitor{}, true, "Empty"},
|
||||
{Monitor{lastCheck: timeNow, CheckInterval: 15}, false, "Just checked"},
|
||||
{Monitor{lastCheck: timeTenSecAgo, CheckInterval: 15}, false, "-10s"},
|
||||
{Monitor{lastCheck: timeTwentySecAgo, CheckInterval: 15}, true, "-20s"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
actual := c.monitor.ShouldCheck()
|
||||
if actual != c.expected {
|
||||
t.Errorf("ShouldCheck(%v), expected=%t actual=%t", c.name, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorIsUp tests the Monitor.isUp()
|
||||
func TestMonitorIsUp(t *testing.T) {
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expected bool
|
||||
name string
|
||||
}{
|
||||
{Monitor{}, true, "Empty"},
|
||||
{Monitor{alertCount: 1}, false, "Has alert"},
|
||||
{Monitor{alertCount: -1}, false, "Negative alerts"},
|
||||
{Monitor{alertCount: 0}, true, "No alerts"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
actual := c.monitor.isUp()
|
||||
if actual != c.expected {
|
||||
t.Errorf("isUp(%v), expected=%t actual=%t", c.name, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorSuccess tests the Monitor.success()
|
||||
func TestMonitorSuccess(t *testing.T) {
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expectNotice bool
|
||||
name string
|
||||
}{
|
||||
{Monitor{}, false, "Empty"},
|
||||
{Monitor{alertCount: 0}, false, "No alerts"},
|
||||
{Monitor{alertCount: 1}, true, "Has alert"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
notice := c.monitor.success()
|
||||
hasNotice := (notice != nil)
|
||||
if hasNotice != c.expectNotice {
|
||||
t.Errorf("success(%v), expected=%t actual=%t", c.name, c.expectNotice, hasNotice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorFailureAlertAfter tests that alerts will not trigger until
|
||||
// hitting the threshold provided by AlertAfter
|
||||
func TestMonitorFailureAlertAfter(t *testing.T) {
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expectNotice bool
|
||||
name string
|
||||
}{
|
||||
{Monitor{AlertAfter: 1}, true, "Empty"}, // Defaults to true because and AlertEvery default to 0
|
||||
// TODO: Update this if meaning of AlertEvery changes
|
||||
{Monitor{failureCount: 0, AlertAfter: 0, AlertEvery: 1}, true, "Alert after 0: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 0, AlertEvery: 1}, true, "Alert after 0: second failure"},
|
||||
// TODO: This one probably shouldn't trigger an alert if AlertAfter is made to behave consistently
|
||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 1}, true, "Alert after 1: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert after 1: second failure"},
|
||||
{Monitor{failureCount: 0, AlertAfter: 20, AlertEvery: 1}, false, "Alert after 20: first failure"},
|
||||
{Monitor{failureCount: 19, AlertAfter: 20, AlertEvery: 1}, true, "Alert after 20: 20th failure"},
|
||||
{Monitor{failureCount: 20, AlertAfter: 20, AlertEvery: 1}, true, "Alert after 20: 21st failure"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
log.Printf("Testing case %s", c.name)
|
||||
|
||||
notice := c.monitor.failure()
|
||||
hasNotice := (notice != nil)
|
||||
if hasNotice != c.expectNotice {
|
||||
t.Errorf("failure(%v), expected=%t actual=%t", c.name, c.expectNotice, hasNotice)
|
||||
log.Printf("Case failed: %s", c.name)
|
||||
}
|
||||
log.Println("-----")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMonitorFailureAlertEvery tests that alerts will trigger
|
||||
// on the expected intervals
|
||||
func TestMonitorFailureAlertEvery(t *testing.T) {
|
||||
cases := []struct {
|
||||
monitor Monitor
|
||||
expectNotice bool
|
||||
name string
|
||||
}{
|
||||
/*
|
||||
TODO: Actually found a bug in original implementation. There is an inconsistency in the way AlertAfter is treated.
|
||||
For "First alert only" (ie. AlertEvery=0), it is the number of failures to ignore before alerting, so AlertAfter=1
|
||||
will ignore the first failure and alert on the second failure
|
||||
For other intervals (ie. AlertEvery=1), it is essentially indexed on one. Essentially making AlertAfter=1 trigger
|
||||
on the first failure.
|
||||
|
||||
For usabilty, this should be consistent. Consistent with what though? minitor-py? Or itself? Dun dun duuuunnnnn!
|
||||
*/
|
||||
{Monitor{}, true, "Empty"}, // Defaults to true because AlertAfter and AlertEvery default to 0
|
||||
// Alert first time only, after 0
|
||||
{Monitor{failureCount: 0, AlertAfter: 0, AlertEvery: 0}, true, "Alert first time only after 0: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 0, AlertEvery: 0}, false, "Alert first time only after 0: second failure"},
|
||||
// Alert first time only, after 1
|
||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 0}, false, "Alert first time only after 1: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 0}, true, "Alert first time only after 1: second failure"},
|
||||
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: 0}, false, "Alert first time only after 1: third failure"},
|
||||
{Monitor{failureCount: 3, AlertAfter: 1, AlertEvery: 0}, false, "Alert first time only after 1: fourth failure"},
|
||||
// Alert every time, after 0
|
||||
{Monitor{failureCount: 0, AlertAfter: 0, AlertEvery: 1}, true, "Alert every time after 0: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 0, AlertEvery: 1}, true, "Alert every time after 0: second failure"},
|
||||
// Alert every time, after 1
|
||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 1}, false, "Alert every time after 1: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert every time after 1: second failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert every time after 1: third failure"},
|
||||
// Alert every other time
|
||||
{Monitor{failureCount: 0, AlertAfter: 0, AlertEvery: 2}, true, "Alert every other time after 0: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 0, AlertEvery: 2}, false, "Alert every other time after 0: second failure"},
|
||||
{Monitor{failureCount: 2, AlertAfter: 0, AlertEvery: 2}, true, "Alert every other time after 0: third failure2"},
|
||||
{Monitor{failureCount: 3, AlertAfter: 0, AlertEvery: 2}, false, "Alert every other time after 0: fourth failure"},
|
||||
// Alert every other time, after 1
|
||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 2}, false, "Alert every other time after 1: first failure"},
|
||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 2}, true, "Alert every other time after 1: second failure"},
|
||||
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: 2}, false, "Alert every other time after 1: third failure"},
|
||||
{Monitor{failureCount: 3, AlertAfter: 1, AlertEvery: 2}, true, "Alert every other time after 1: fourth failure"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
notice := c.monitor.failure()
|
||||
hasNotice := (notice != nil)
|
||||
if hasNotice != c.expectNotice {
|
||||
t.Errorf("failure(%v), expected=%t actual=%t", c.name, c.expectNotice, hasNotice)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user