From 51f5c816a57b1e09a90df3f939495cc9b59f5d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 21 Apr 2020 16:15:06 +0100 Subject: [PATCH] fix(tests): more test coverage --- cmd/karma/views_test.go | 130 ++++++++++++++++++++++++++++++ internal/alertmanager/upstream.go | 5 ++ 2 files changed, 135 insertions(+) diff --git a/cmd/karma/views_test.go b/cmd/karma/views_test.go index 6f9951f33..6a48522d2 100644 --- a/cmd/karma/views_test.go +++ b/cmd/karma/views_test.go @@ -7,10 +7,13 @@ import ( "net/http" "net/http/httptest" "os" + "regexp" "sort" + "strings" "testing" "time" + "github.com/prymitive/karma/internal/alertmanager" "github.com/prymitive/karma/internal/config" "github.com/prymitive/karma/internal/mock" "github.com/prymitive/karma/internal/models" @@ -922,3 +925,130 @@ func TestAuthentication(t *testing.T) { }) } } + +func TestUpstreamStatus(t *testing.T) { + log.SetLevel(log.FatalLevel) + + type mockT struct { + uri string + code int + body string + } + + type testCaseT struct { + Name string + mocks []mockT + upstreams []config.AlertmanagerConfig + status models.AlertmanagerAPISummary + } + + testCases := []testCaseT{ + { + Name: "404 from upstream", + mocks: []mockT{ + { + uri: "http://localhost:9093/metrics", + code: 404, + body: "not found", + }, + { + uri: "http://localhost:9093/api/v2/status", + code: 404, + body: "not found", + }, + }, + upstreams: []config.AlertmanagerConfig{ + { + Name: "default", + URI: "http://localhost:9093", + ExternalURI: "http://example.com", + ReadOnly: true, + Headers: map[string]string{ + "X-Foo": "Bar", + "X-Bar": "Foo", + }, + CORS: config.AlertmanagerCORS{ + Credentials: "include", + }, + }, + }, + status: models.AlertmanagerAPISummary{ + Counters: models.AlertmanagerAPICounters{ + Total: 1, + Healthy: 0, + Failed: 1, + }, + Instances: []models.AlertmanagerAPIStatus{ + { + Name: "default", + URI: "http://example.com", + PublicURI: "http://example.com", + ReadOnly: true, + Headers: map[string]string{ + "X-Foo": "Bar", + "X-Bar": "Foo", + }, + CORSCredentials: "include", + Error: `^unknown error \(status 404\): .+`, + Version: "", + Cluster: "843c4a11660fe38ea61e6960a29d4f4796da6488", + ClusterMembers: []string{"default"}, + }, + }, + Clusters: map[string][]string{ + "843c4a11660fe38ea61e6960a29d4f4796da6488": {"default"}, + }, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + for _, m := range testCase.mocks { + httpmock.RegisterResponder("GET", m.uri, httpmock.NewStringResponder(m.code, m.body)) + } + + alertmanager.UnregisterAll() + mockConfig() + config.Config.Alertmanager.Servers = testCase.upstreams + _ = setupUpstreams() + log.SetLevel(log.FatalLevel) + pullFromAlertmanager() + r := ginTestEngine() + + req := httptest.NewRequest("GET", "/alerts.json?q=@receiver=by-cluster-service&q=alertname=HTTP_Probe_Failed&q=instance=web1", nil) + resp := httptest.NewRecorder() + r.ServeHTTP(resp, req) + if resp.Code != http.StatusOK { + t.Errorf("GET /alerts.json returned status %d", resp.Code) + } + + ur := models.AlertsResponse{} + err := json.Unmarshal(resp.Body.Bytes(), &ur) + if err != nil { + t.Errorf("Failed to unmarshal response: %s", err) + } + if diff := cmp.Diff(testCase.status, ur.Upstreams, cmp.Comparer( + func(x, y string) bool { + if strings.HasPrefix(x, "^") { + reX, err := regexp.Compile(x) + if err == nil { + return reX.MatchString(y) + } + } + if strings.HasPrefix(y, "^") { + reY, err := regexp.Compile(y) + if err == nil { + return reY.MatchString(x) + } + } + return x == y + }), + ); diff != "" { + t.Errorf("Wrong upstream summary returned (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/alertmanager/upstream.go b/internal/alertmanager/upstream.go index 60fe54844..36272c30e 100644 --- a/internal/alertmanager/upstream.go +++ b/internal/alertmanager/upstream.go @@ -60,6 +60,11 @@ func NewAlertmanager(name, upstreamURI string, opts ...Option) (*Alertmanager, e return am, nil } +// UnregisterAll will remove all registered alertmanager instances +func UnregisterAll() { + upstreams = map[string]*Alertmanager{} +} + // RegisterAlertmanager will add an Alertmanager instance to the list of // instances used when pulling alerts from upstreams func RegisterAlertmanager(am *Alertmanager) error {