1package configdb
2
3import (
4	"context"
5	fmt "fmt"
6	"testing"
7	time "time"
8
9	"github.com/cortexproject/cortex/pkg/configs/userconfig"
10
11	"github.com/stretchr/testify/assert"
12
13	"github.com/cortexproject/cortex/pkg/configs/client"
14)
15
16var zeroTime time.Time
17
18type MockClient struct {
19	cfgs map[string]userconfig.VersionedRulesConfig
20	err  error
21}
22
23func (c *MockClient) GetRules(ctx context.Context, since userconfig.ID) (map[string]userconfig.VersionedRulesConfig, error) {
24	return c.cfgs, c.err
25}
26
27func (c *MockClient) GetAlerts(ctx context.Context, since userconfig.ID) (*client.ConfigsResponse, error) {
28	return nil, nil
29}
30
31func Test_ConfigRuleStoreError(t *testing.T) {
32	mock := &MockClient{
33		cfgs: nil,
34		err:  fmt.Errorf("Error"),
35	}
36
37	store := NewConfigRuleStore(mock)
38	_, err := store.ListAllRuleGroups(context.Background())
39
40	assert.Equal(t, mock.err, err, "Unexpected error returned")
41}
42
43func Test_ConfigRuleStoreReturn(t *testing.T) {
44	id := userconfig.ID(10)
45	mock := &MockClient{
46		cfgs: map[string]userconfig.VersionedRulesConfig{
47			"user": {
48				ID:        id,
49				Config:    fakeRuleConfig(),
50				DeletedAt: zeroTime,
51			},
52		},
53		err: nil,
54	}
55
56	store := NewConfigRuleStore(mock)
57	rules, _ := store.ListAllRuleGroups(context.Background())
58
59	assert.Equal(t, 1, len(rules["user"]))
60	assert.Equal(t, id, store.since)
61}
62
63func Test_ConfigRuleStoreDelete(t *testing.T) {
64	mock := &MockClient{
65		cfgs: map[string]userconfig.VersionedRulesConfig{
66			"user": {
67				ID:        1,
68				Config:    fakeRuleConfig(),
69				DeletedAt: zeroTime,
70			},
71		},
72		err: nil,
73	}
74
75	store := NewConfigRuleStore(mock)
76	_, _ = store.ListAllRuleGroups(context.Background())
77
78	mock.cfgs["user"] = userconfig.VersionedRulesConfig{
79		ID:        1,
80		Config:    userconfig.RulesConfig{},
81		DeletedAt: time.Unix(0, 1),
82	}
83
84	rules, _ := store.ListAllRuleGroups(context.Background())
85
86	assert.Equal(t, 0, len(rules["user"]))
87}
88
89func Test_ConfigRuleStoreAppend(t *testing.T) {
90	mock := &MockClient{
91		cfgs: map[string]userconfig.VersionedRulesConfig{
92			"user": {
93				ID:        1,
94				Config:    fakeRuleConfig(),
95				DeletedAt: zeroTime,
96			},
97		},
98		err: nil,
99	}
100
101	store := NewConfigRuleStore(mock)
102	_, _ = store.ListAllRuleGroups(context.Background())
103
104	delete(mock.cfgs, "user")
105	mock.cfgs["user2"] = userconfig.VersionedRulesConfig{
106		ID:        1,
107		Config:    fakeRuleConfig(),
108		DeletedAt: zeroTime,
109	}
110
111	rules, _ := store.ListAllRuleGroups(context.Background())
112
113	assert.Equal(t, 2, len(rules))
114}
115
116func Test_ConfigRuleStoreSinceSet(t *testing.T) {
117	mock := &MockClient{
118		cfgs: map[string]userconfig.VersionedRulesConfig{
119			"user": {
120				ID:        1,
121				Config:    fakeRuleConfig(),
122				DeletedAt: zeroTime,
123			},
124			"user1": {
125				ID:        10,
126				Config:    fakeRuleConfig(),
127				DeletedAt: zeroTime,
128			},
129			"user2": {
130				ID:        100,
131				Config:    fakeRuleConfig(),
132				DeletedAt: zeroTime,
133			},
134		},
135		err: nil,
136	}
137
138	store := NewConfigRuleStore(mock)
139	_, _ = store.ListAllRuleGroups(context.Background())
140	assert.Equal(t, userconfig.ID(100), store.since)
141
142	delete(mock.cfgs, "user")
143	delete(mock.cfgs, "user1")
144	mock.cfgs["user2"] = userconfig.VersionedRulesConfig{
145		ID:        50,
146		Config:    fakeRuleConfig(),
147		DeletedAt: zeroTime,
148	}
149
150	_, _ = store.ListAllRuleGroups(context.Background())
151	assert.Equal(t, userconfig.ID(100), store.since)
152
153	mock.cfgs["user2"] = userconfig.VersionedRulesConfig{
154		ID:        101,
155		Config:    fakeRuleConfig(),
156		DeletedAt: zeroTime,
157	}
158
159	_, _ = store.ListAllRuleGroups(context.Background())
160	assert.Equal(t, userconfig.ID(101), store.since)
161}
162
163func fakeRuleConfig() userconfig.RulesConfig {
164	return userconfig.RulesConfig{
165		FormatVersion: userconfig.RuleFormatV2,
166		Files: map[string]string{
167			"test": `
168# Config no. 1.
169groups:
170- name: example
171  rules:
172  - alert: ScrapeFailed
173    expr: 'up != 1'
174    for: 10m
175    labels:
176      severity: warning
177    annotations:
178      summary: "Scrape of {{$labels.job}} (pod: {{$labels.instance}}) failed."
179      description: "Prometheus cannot reach the /metrics page on the {{$labels.instance}} pod."
180      impact: "We have no monitoring data for {{$labels.job}} - {{$labels.instance}}. At worst, it's completely down. At best, we cannot reliably respond to operational issues."
181      dashboardURL: "$${base_url}/admin/prometheus/targets"
182`,
183		},
184	}
185}
186