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  }