...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package test
15
16 import (
17 "fmt"
18 "sync"
19 "testing"
20 "time"
21
22 "github.com/prometheus/common/model"
23 )
24
25
26
27 type Collector struct {
28 t *testing.T
29 name string
30 opts *AcceptanceOpts
31
32 collected map[float64][]model.Alerts
33 expected map[Interval][]model.Alerts
34
35 mtx sync.RWMutex
36 }
37
38 func (c *Collector) String() string {
39 return c.name
40 }
41
42 func batchesEqual(as, bs model.Alerts, opts *AcceptanceOpts) bool {
43 if len(as) != len(bs) {
44 return false
45 }
46
47 for _, a := range as {
48 found := false
49 for _, b := range bs {
50 if equalAlerts(a, b, opts) {
51 found = true
52 break
53 }
54 }
55 if !found {
56 return false
57 }
58 }
59 return true
60 }
61
62
63
64 func (c *Collector) latest() float64 {
65 c.mtx.RLock()
66 defer c.mtx.RUnlock()
67 var latest float64
68 for iv := range c.expected {
69 if iv.end > latest {
70 latest = iv.end
71 }
72 }
73 return latest
74 }
75
76
77
78 func (c *Collector) Want(iv Interval, alerts ...*TestAlert) {
79 c.mtx.Lock()
80 defer c.mtx.Unlock()
81 var nas model.Alerts
82 for _, a := range alerts {
83 nas = append(nas, a.nativeAlert(c.opts))
84 }
85
86 c.expected[iv] = append(c.expected[iv], nas)
87 }
88
89
90 func (c *Collector) add(alerts ...*model.Alert) {
91 c.mtx.Lock()
92 defer c.mtx.Unlock()
93 arrival := c.opts.relativeTime(time.Now())
94
95 c.collected[arrival] = append(c.collected[arrival], model.Alerts(alerts))
96 }
97
98 func (c *Collector) check() string {
99 report := fmt.Sprintf("\ncollector %q:\n\n", c)
100
101 c.mtx.RLock()
102 defer c.mtx.RUnlock()
103 for iv, expected := range c.expected {
104 report += fmt.Sprintf("interval %v\n", iv)
105
106 var alerts []model.Alerts
107 for at, got := range c.collected {
108 if iv.contains(at) {
109 alerts = append(alerts, got...)
110 }
111 }
112
113 for _, exp := range expected {
114 found := len(exp) == 0 && len(alerts) == 0
115
116 report += "---\n"
117
118 for _, e := range exp {
119 report += fmt.Sprintf("- %v\n", c.opts.alertString(e))
120 }
121
122 for _, a := range alerts {
123 if batchesEqual(exp, a, c.opts) {
124 found = true
125 break
126 }
127 }
128
129 if found {
130 report += " [ ✓ ]\n"
131 } else {
132 c.t.Fail()
133 report += " [ ✗ ]\n"
134 }
135 }
136 }
137
138
139 var totalExp, totalAct int
140 for _, exp := range c.expected {
141 for _, e := range exp {
142 totalExp += len(e)
143 }
144 }
145 for _, act := range c.collected {
146 for _, a := range act {
147 if len(a) == 0 {
148 c.t.Error("received empty notifications")
149 }
150 totalAct += len(a)
151 }
152 }
153 if totalExp != totalAct {
154 c.t.Fail()
155 report += fmt.Sprintf("\nExpected total of %d alerts, got %d", totalExp, totalAct)
156 }
157
158 if c.t.Failed() {
159 report += "\nreceived:\n"
160
161 for at, col := range c.collected {
162 for _, alerts := range col {
163 report += fmt.Sprintf("@ %v\n", at)
164 for _, a := range alerts {
165 report += fmt.Sprintf("- %v\n", c.opts.alertString(a))
166 }
167 }
168 }
169 }
170
171 return report
172 }
173
View as plain text