github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/merger/v2_alerts_test.go (about) 1 package merger 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/go-openapi/strfmt" 8 v2_models "github.com/prometheus/alertmanager/api/v2/models" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestV2Alerts(t *testing.T) { 13 14 // This test is to check the parsing round-trip is working as expected, the merging logic is 15 // tested in TestMergeV2Alerts. The test data is based on captures from an actual Alertmanager. 16 17 in := [][]byte{ 18 []byte(`[` + 19 `{"annotations":{},"endsAt":"2021-04-21T10:47:32.161+02:00","fingerprint":"c4b6b79a607b6ba0",` + 20 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.161+02:00",` + 21 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 22 `"updatedAt":"2021-04-21T07:47:32.163Z","labels":{"group":"group_1","name":"alert_1"}},` + 23 `{"annotations":{},"endsAt":"2021-04-21T10:47:32.163+02:00","fingerprint":"c4b8b79a607bee77",` + 24 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.163+02:00",` + 25 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 26 `"updatedAt":"2021-04-21T07:47:32.165Z","labels":{"group":"group_1","name":"alert_2"}}` + 27 `]`), 28 []byte(`[{"annotations":{},"endsAt":"2021-04-21T10:47:32.165+02:00","fingerprint":"465de60f606461c3",` + 29 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.165+02:00",` + 30 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 31 `"updatedAt":"2021-04-21T07:47:32.167Z","labels":{"group":"group_2","name":"alert_3"}}]`), 32 []byte(`[]`), 33 } 34 35 expected := []byte(`[` + 36 `{"annotations":{},"endsAt":"2021-04-21T10:47:32.165+02:00","fingerprint":"465de60f606461c3",` + 37 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.165+02:00",` + 38 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 39 `"updatedAt":"2021-04-21T07:47:32.167Z","labels":{"group":"group_2","name":"alert_3"}},` + 40 `{"annotations":{},"endsAt":"2021-04-21T10:47:32.161+02:00","fingerprint":"c4b6b79a607b6ba0",` + 41 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.161+02:00",` + 42 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 43 `"updatedAt":"2021-04-21T07:47:32.163Z","labels":{"group":"group_1","name":"alert_1"}},` + 44 `{"annotations":{},"endsAt":"2021-04-21T10:47:32.163+02:00","fingerprint":"c4b8b79a607bee77",` + 45 `"receivers":[{"name":"dummy"}],"startsAt":"2021-04-21T09:47:32.163+02:00",` + 46 `"status":{"inhibitedBy":[],"silencedBy":[],"state":"unprocessed"},` + 47 `"updatedAt":"2021-04-21T07:47:32.165Z","labels":{"group":"group_1","name":"alert_2"}}` + 48 `]`) 49 50 out, err := V2Alerts{}.MergeResponses(in) 51 require.NoError(t, err) 52 require.Equal(t, expected, out) 53 } 54 55 func v2ParseTime(s string) *strfmt.DateTime { 56 t, _ := time.Parse(time.RFC3339, s) 57 dt := strfmt.DateTime(t) 58 return &dt 59 } 60 61 // v2alert is a convenience function to create alert structures with certain important fields set 62 // and with sensible defaults for the remaining fields to test they are passed through. 63 func v2alert(fingerprint, annotation, updatedAt string) *v2_models.GettableAlert { 64 receiver := "dummy" 65 return &v2_models.GettableAlert{ 66 Annotations: v2_models.LabelSet{ 67 "annotation1": annotation, 68 }, 69 EndsAt: v2ParseTime("2020-01-01T12:00:00.000Z"), 70 Fingerprint: &fingerprint, 71 Receivers: []*v2_models.Receiver{ 72 { 73 Name: &receiver, 74 }, 75 }, 76 StartsAt: v2ParseTime("2020-01-01T12:00:00.000Z"), 77 Status: &v2_models.AlertStatus{}, 78 UpdatedAt: v2ParseTime(updatedAt), 79 Alert: v2_models.Alert{ 80 GeneratorURL: strfmt.URI("something"), 81 Labels: v2_models.LabelSet{"label1": "foo"}, 82 }, 83 } 84 } 85 86 func v2alerts(alerts ...*v2_models.GettableAlert) v2_models.GettableAlerts { 87 return alerts 88 } 89 90 func TestMergeV2Alerts(t *testing.T) { 91 var ( 92 alert1 = v2alert("1111111111111111", "a1-", "2020-01-01T12:00:00.000Z") 93 newerAlert1 = v2alert("1111111111111111", "a1+x", "2020-01-01T12:00:00.001Z") 94 alert2 = v2alert("2222222222222222", "a2-", "2020-01-01T12:00:00.000Z") 95 alert3 = v2alert("3333333333333333", "a3-", "2020-01-01T12:00:00.000Z") 96 ) 97 cases := []struct { 98 name string 99 in v2_models.GettableAlerts 100 err error 101 out v2_models.GettableAlerts 102 }{ 103 { 104 name: "no alerts, should return an empty list", 105 in: v2alerts(), 106 out: v2_models.GettableAlerts{}, 107 }, 108 { 109 name: "one alert, should return the alert", 110 in: v2alerts(alert1), 111 out: v2alerts(alert1), 112 }, 113 { 114 name: "two alerts, should return two alerts", 115 in: v2alerts(alert1, alert2), 116 out: v2alerts(alert1, alert2), 117 }, 118 { 119 name: "three alerts, should return three alerts", 120 in: v2alerts(alert1, alert2, alert3), 121 out: v2alerts(alert1, alert2, alert3), 122 }, 123 { 124 name: "three alerts out of order, should return three alerts in fingerprint order", 125 in: v2alerts(alert3, alert2, alert1), 126 out: v2alerts(alert1, alert2, alert3), 127 }, 128 { 129 name: "two identical alerts, should return one alert", 130 in: v2alerts(alert1, alert1), 131 out: v2alerts(alert1), 132 }, 133 { 134 name: "two identical alerts plus another, should return two alerts", 135 in: v2alerts(alert1, alert1, alert2), 136 out: v2alerts(alert1, alert2), 137 }, 138 { 139 name: "two duplicates out of sync alerts, should return newer alert", 140 in: v2alerts(alert1, newerAlert1), 141 out: v2alerts(newerAlert1), 142 }, 143 { 144 name: "two duplicates out of sync alerts (newer first), should return newer alert", 145 in: v2alerts(newerAlert1, alert1), 146 out: v2alerts(newerAlert1), 147 }, 148 { 149 name: "two duplicates plus others, should return newer alert and others", 150 in: v2alerts(newerAlert1, alert3, alert1, alert2), 151 out: v2alerts(newerAlert1, alert2, alert3), 152 }, 153 } 154 155 for _, c := range cases { 156 t.Run(c.name, func(t *testing.T) { 157 out, err := mergeV2Alerts(c.in) 158 require.Equal(t, c.err, err) 159 require.Equal(t, c.out, out) 160 }) 161 } 162 }