blob: 86fbd4c8a2fca13bea2786523af152fa76945b5d [file] [log] [blame]
package incident
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.skia.org/infra/am/go/silence"
"go.skia.org/infra/go/alerts"
"go.skia.org/infra/go/paramtools"
)
func TestAreIncidentsFlaky(t *testing.T) {
now := time.Now().Unix()
// Add 10 incidents with duration = 10 mins and 10 with duration < 10 mins.
incidents := []Incident{}
for i := 0; i < 10; i++ {
incidents = append(incidents, Incident{LastSeen: now, Start: now - 600})
incidents = append(incidents, Incident{LastSeen: now, Start: now - 10})
}
// Should not be flaky because 50% are flaky not matching the specified 60%.
assert.False(t, AreIncidentsFlaky(incidents, 10, 600, 0.60))
// Should be flaky because 50% are flaky matching the specifeid 50%.
assert.True(t, AreIncidentsFlaky(incidents, 10, 600, 0.50))
// Add 4 incidents with duration = 10 mins and 6 with duration < 10 mins.
incidents = []Incident{}
for i := 0; i < 4; i++ {
incidents = append(incidents, Incident{LastSeen: now, Start: now - 600})
}
for i := 0; i < 6; i++ {
incidents = append(incidents, Incident{LastSeen: now, Start: now - 10})
}
// Should not be flaky because 60% are flaky not matching the specified 61%.
assert.False(t, AreIncidentsFlaky(incidents, 10, 600, 0.61))
// Should be flaky because 60% are flaky matching the specified 60%.
assert.True(t, AreIncidentsFlaky(incidents, 10, 600, 0.60))
// Add 9 incidents with duration < 10 mins.
incidents = []Incident{}
for i := 0; i < 9; i++ {
incidents = append(incidents, Incident{LastSeen: now, Start: now - 10})
}
// Should not be flaky because num incidents did not meet the specified threshold of 10.
assert.False(t, AreIncidentsFlaky(incidents, 10, 600, 1.00))
// Should be flaky because num incidents do meet the specified threshold of 9 and 100%.
assert.True(t, AreIncidentsFlaky(incidents, 9, 600, 1.00))
}
func TestIsSilenced(t *testing.T) {
i := Incident{
Params: map[string]string{
"foo": "2123",
"bar": "aa",
},
}
// Test with simple silences
silences := []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"2123"}},
},
}
assert.True(t, i.IsSilenced(silences, true))
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"abc", "xyz", "2123"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"blah": []string{"abc", "xyz", "2123"}},
},
}
assert.True(t, i.IsSilenced(silences, true))
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"abc", "xyz", "32"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"blah": []string{"abc", "xyz", "2123"}},
},
}
assert.False(t, i.IsSilenced(silences, true))
// Test with ignore.
silences = []silence.Silence{
{
Active: false,
ParamSet: paramtools.ParamSet{"foo": []string{"2123"}},
},
}
assert.False(t, i.IsSilenced(silences, true))
assert.True(t, i.IsSilenced(silences, false))
// Tests with regexes.
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"2.*"}},
},
}
assert.True(t, i.IsSilenced(silences, true))
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"3.*"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"bar": []string{"aa"}},
},
}
assert.True(t, i.IsSilenced(silences, true))
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"3.*"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"bar": []string{"bb"}},
},
}
assert.False(t, i.IsSilenced(silences, true))
// Test with paramset with both regex and non-regex by adding another value to existing key.
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"3.*"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"bar": []string{"bb", "aa", "cc"}},
},
}
assert.True(t, i.IsSilenced(silences, true))
// Test with silence that does not apply.
silences = []silence.Silence{
{
Active: true,
ParamSet: paramtools.ParamSet{"foo": []string{"3.*"}},
},
{
Active: true,
ParamSet: paramtools.ParamSet{"bar": []string{"bb", "aa", "cc"}, "blah": []string{"abc"}},
},
}
assert.False(t, i.IsSilenced(silences, true))
}
func TestIdForAlert(t *testing.T) {
m := map[string]string{
"__name__": "ALERTS",
"alertname": "BotMissing",
"alertstate": "firing",
"bot": "skia-rpi-064",
"category": "infra",
"instance": "skia-datahopper2:20000",
"job": "datahopper",
"pool": "Skia",
"severity": "critical",
"swarming": "chromium-swarm.appspot.com",
}
st := NewStore(nil, []string{})
id1, err := st.idForAlert(m)
assert.NoError(t, err)
id2, err := st.idForAlert(m)
assert.NoError(t, err)
assert.Equal(t, id1, id2)
m[alerts.STATE] = alerts.STATE_ACTIVE
id2, err = st.idForAlert(m)
assert.NoError(t, err)
assert.Equal(t, id1, id2)
}
func TestGetRegexesToOwners(t *testing.T) {
ownersRegexesStr := "owner1:abbr_regex1,abbr_regex2;owner2:abbr_regex3"
m1, err := getRegexesToOwners(ownersRegexesStr)
assert.NoError(t, err)
assert.Equal(t, 3, len(m1))
assert.Equal(t, "owner1", m1["abbr_regex1"])
assert.Equal(t, "owner1", m1["abbr_regex2"])
assert.Equal(t, "owner2", m1["abbr_regex3"])
// Test badly formed regex with missing owner1.
m2, err := getRegexesToOwners("abbr_regex1,abbr2_regex;owner2:abbr_regex3")
assert.Error(t, err)
assert.Nil(t, m2)
}
func TestGetOwnerIfMatch(t *testing.T) {
// Test matches.
ownersRegexesStr := "superman@krypton.com:Bizarro.*,^Kryptonite.*Asteroid.*$;batman@gotham.com:Joker.*"
ownerTest1, err := getOwnerIfMatch(ownersRegexesStr, "something Bizarro something")
assert.NoError(t, err)
assert.Equal(t, "superman@krypton.com", ownerTest1)
ownerTest2, err := getOwnerIfMatch(ownersRegexesStr, "Kryptonite really big Asteroid thing")
assert.NoError(t, err)
assert.Equal(t, "superman@krypton.com", ownerTest2)
ownerTest3, err := getOwnerIfMatch(ownersRegexesStr, "Joker is here!!!")
assert.NoError(t, err)
assert.Equal(t, "batman@gotham.com", ownerTest3)
ownerTest4, err := getOwnerIfMatch(ownersRegexesStr, "Joker")
assert.NoError(t, err)
assert.Equal(t, "batman@gotham.com", ownerTest4)
// Test misses.
ownerMiss1, err := getOwnerIfMatch(ownersRegexesStr, "bizarro")
assert.NoError(t, err)
assert.Equal(t, "", ownerMiss1)
ownerMiss2, err := getOwnerIfMatch(ownersRegexesStr, "wrong start Kryptonite really big Asteroid thing")
assert.NoError(t, err)
assert.Equal(t, "", ownerMiss2)
ownerMiss3, err := getOwnerIfMatch(ownersRegexesStr, "joker")
assert.NoError(t, err)
assert.Equal(t, "", ownerMiss3)
// Test badly formed regex.
badRegex := "superman@krypton:.***"
ownerBadTest, err := getOwnerIfMatch(badRegex, "Anything")
assert.Error(t, err)
assert.Equal(t, "", ownerBadTest)
}
func TestGetOwnerFromDockerImage(t *testing.T) {
tests := []struct {
dockerImage string
expectedOwner string
}{
{dockerImage: "abc", expectedOwner: ""},
{dockerImage: "gcr.io/skia-public/autoroll-be:2021-04-30T14_04_37Z-batman-c3ecfbb-dirty", expectedOwner: "batman@google.com"},
{dockerImage: "gcr.io/skia-public/autoroll-be:2021-04-30T14_04_37Z-batman-c3ecfbb-clean", expectedOwner: "batman@google.com"},
{dockerImage: "gcr.io/skia-public/autoroll-be:2021-04-30T14_04_37Z-batman-c3ecfbb-invalidtag", expectedOwner: ""},
}
for _, test := range tests {
assert.Equal(t, test.expectedOwner, getOwnerFromDockerImage(test.dockerImage))
}
}