cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.32.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/promapi/cache_test.go

313lines · modecode

1package promapi
2
3import (
4 "errors"
5 "fmt"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/prometheus/client_golang/prometheus/testutil"
11 "github.com/stretchr/testify/require"
12)
13
14func TestQueryCacheGetAndSet(t *testing.T) {
15 const maxSize = 100
16 mockErr := errors.New("Fake Error")
17 cache := newQueryCache(maxSize, time.Hour)
18
19 var i uint64
20 for i = 1; i <= maxSize; i++ {
21 v, ok := cache.get(i, "/foo")
22 require.Equal(t, false, ok)
23 require.Zero(t, v)
24
25 cache.set(i, queryResult{err: mockErr}, 1)
26 v, ok = cache.get(i, "/foo")
27 require.Equal(t, false, ok)
28 require.Zero(t, v)
29
30 cache.set(i, queryResult{err: mockErr}, 1)
31 v, ok = cache.get(i, "/foo")
32 require.Equal(t, true, ok)
33 require.NotZero(t, v)
34 require.Equal(t, mockErr, v.err)
35 }
36
37 require.Equal(t, 100, len(cache.entries))
38 require.Equal(t, 100, cache.hits["/foo"])
39 require.Equal(t, 200, cache.misses["/foo"])
40 require.Equal(t, 0, cache.evictions)
41
42 cache.gc()
43 require.Equal(t, 100, len(cache.entries))
44 require.Equal(t, 100, cache.hits["/foo"])
45 require.Equal(t, 200, cache.misses["/foo"])
46 require.Equal(t, 0, cache.evictions)
47}
48
49func TestQueryCacheGetAndSetAfterZero(t *testing.T) {
50 const maxSize = 100
51 mockErr := errors.New("Fake Error")
52 cache := newQueryCache(maxSize, time.Hour)
53
54 v, ok := cache.get(1, "/foo")
55 require.Equal(t, false, ok)
56 require.Zero(t, v)
57
58 cache.set(1, queryResult{err: mockErr}, 0)
59 v, ok = cache.get(1, "/foo")
60 require.Equal(t, true, ok)
61 require.NotZero(t, v)
62 require.Equal(t, mockErr, v.err)
63}
64
65func TestQueryCachePurgeMaxSize(t *testing.T) {
66 const maxSize = 100
67 mockErr := errors.New("Fake Error")
68 cache := newQueryCache(maxSize, time.Hour)
69
70 var i uint64
71 for i = 1; i <= maxSize; i++ {
72 cache.set(i, queryResult{err: mockErr}, 0)
73 v, ok := cache.get(i, "/foo")
74 require.Equal(t, true, ok)
75 require.NotZero(t, v)
76 require.Equal(t, mockErr, v.err)
77 }
78
79 require.Equal(t, 100, len(cache.entries))
80 require.Equal(t, 100, cache.hits["/foo"])
81 require.Equal(t, 0, cache.misses["/foo"])
82 require.Equal(t, 0, cache.evictions)
83
84 for i = maxSize + 1; i <= maxSize+10; i++ {
85 v, ok := cache.get(i, "/foo")
86 require.Equal(t, false, ok)
87 require.Zero(t, v)
88
89 cache.set(i, queryResult{err: mockErr}, 0)
90 v, ok = cache.get(i, "/foo")
91 require.Equal(t, true, ok)
92 require.NotZero(t, v)
93 require.Equal(t, mockErr, v.err)
94 }
95
96 require.Equal(t, 100, len(cache.entries))
97 require.Equal(t, 110, cache.hits["/foo"])
98 require.Equal(t, 10, cache.misses["/foo"])
99 require.Equal(t, 10, cache.evictions)
100}
101
102func TestQueryCachePurgeNoRequests(t *testing.T) {
103 cache := newQueryCache(100, time.Second)
104
105 expires := time.Now().Add(time.Hour)
106
107 var i uint64
108 for i = 1; i <= 50; i++ {
109 cache.set(i, queryResult{expires: expires}, 0)
110 }
111 require.Equal(t, 50, len(cache.entries))
112 require.Equal(t, 0, cache.evictions)
113
114 cache.gc()
115 require.Equal(t, 0, len(cache.entries))
116 require.Equal(t, 50, cache.evictions)
117 for i = 1; i <= 50; i++ {
118 _, ok := cache.get(i, "/foo")
119 require.Equal(t, false, ok)
120 }
121}
122
123func TestQueryCachePurgeMaxLife(t *testing.T) {
124 cache := newQueryCache(100, time.Second)
125
126 expires := time.Now().Add(time.Hour)
127
128 var i uint64
129 for i = 1; i <= 50; i++ {
130 cache.set(i, queryResult{expires: expires}, 0)
131 _, ok := cache.get(i, "/foo")
132 require.Equal(t, true, ok)
133 }
134 require.Equal(t, 50, len(cache.entries))
135 require.Equal(t, 0, cache.evictions)
136
137 time.Sleep(time.Second * 2)
138 for i = 1; i <= 50; i++ {
139 _, ok := cache.get(i, "/foo")
140 require.Equal(t, true, ok)
141 }
142 require.Equal(t, 50, len(cache.entries))
143 require.Equal(t, 0, cache.evictions)
144
145 time.Sleep(time.Second * 2)
146 cache.gc()
147 require.Equal(t, 0, len(cache.entries))
148 require.Equal(t, 50, cache.evictions)
149 for i = 1; i <= 50; i++ {
150 _, ok := cache.get(i, "/foo")
151 require.Equal(t, false, ok)
152 }
153}
154
155func TestQueryCachePurgeRequests(t *testing.T) {
156 cache := newQueryCache(100, time.Second)
157
158 var i uint64
159 for i = 1; i <= 50; i++ {
160 _, ok := cache.get(i, "/foo")
161 require.Equal(t, false, ok)
162 }
163
164 cache.gc()
165 require.Equal(t, 50, len(cache.requests))
166
167 time.Sleep(time.Second * 2)
168 for i = 1; i <= 25; i++ {
169 _, ok := cache.get(i, "/foo")
170 require.Equal(t, false, ok)
171 }
172 cache.gc()
173 require.Equal(t, 25, len(cache.requests))
174}
175
176func TestQueryCachePurgeExpired(t *testing.T) {
177 cache := newQueryCache(100, time.Hour)
178
179 expires := time.Now().Add(time.Second)
180
181 var i uint64
182 for i = 1; i <= 50; i++ {
183 cache.set(i, queryResult{expires: expires}, 0)
184 _, ok := cache.get(i, "/foo")
185 require.Equal(t, true, ok)
186 }
187 require.Equal(t, 50, len(cache.entries))
188 require.Equal(t, 0, cache.evictions)
189
190 cache.gc()
191 require.Equal(t, 50, len(cache.entries))
192 require.Equal(t, 0, cache.evictions)
193
194 time.Sleep(time.Second * 2)
195 cache.gc()
196 require.Equal(t, 0, len(cache.entries))
197 require.Equal(t, 50, cache.evictions)
198 for i = 1; i <= 50; i++ {
199 _, ok := cache.get(i, "/foo")
200 require.Equal(t, false, ok)
201 }
202}
203
204func TestCacheCollector(t *testing.T) {
205 const maxSize = 100
206 cache := newQueryCache(maxSize, time.Hour)
207
208 names := []string{
209 "pint_prometheus_cache_size",
210 "pint_prometheus_cache_hits_total",
211 "pint_prometheus_cache_miss_total",
212 "pint_prometheus_cache_evictions_total",
213 }
214
215 collector := newCacheCollector(cache, "prom")
216 require.NoError(t, testutil.CollectAndCompare(
217 collector, strings.NewReader(`
218# HELP pint_prometheus_cache_evictions_total Total number of times an entry was evicted from query cache due to size limit or TTL
219# TYPE pint_prometheus_cache_evictions_total counter
220pint_prometheus_cache_evictions_total{name="prom"} 0
221# HELP pint_prometheus_cache_size Total number of entries currently stored in Prometheus query cache
222# TYPE pint_prometheus_cache_size gauge
223pint_prometheus_cache_size{name="prom"} 0
224`),
225 names...,
226 ))
227
228 var i uint64
229 for i = 1; i <= maxSize; i++ {
230 endpoint := fmt.Sprintf("/foo/%d", i%10)
231 _, _ = cache.get(i, endpoint)
232 cache.set(i, queryResult{}, 1)
233 _, _ = cache.get(i, endpoint)
234 cache.set(i, queryResult{}, 1)
235 _, _ = cache.get(i, endpoint)
236 }
237
238 require.NoError(t, testutil.CollectAndCompare(
239 collector, strings.NewReader(`
240# HELP pint_prometheus_cache_evictions_total Total number of times an entry was evicted from query cache due to size limit or TTL
241# TYPE pint_prometheus_cache_evictions_total counter
242pint_prometheus_cache_evictions_total{name="prom"} 0
243# HELP pint_prometheus_cache_hits_total Total number of query cache hits
244# TYPE pint_prometheus_cache_hits_total counter
245pint_prometheus_cache_hits_total{endpoint="/foo/0",name="prom"} 10
246pint_prometheus_cache_hits_total{endpoint="/foo/1",name="prom"} 10
247pint_prometheus_cache_hits_total{endpoint="/foo/2",name="prom"} 10
248pint_prometheus_cache_hits_total{endpoint="/foo/3",name="prom"} 10
249pint_prometheus_cache_hits_total{endpoint="/foo/4",name="prom"} 10
250pint_prometheus_cache_hits_total{endpoint="/foo/5",name="prom"} 10
251pint_prometheus_cache_hits_total{endpoint="/foo/6",name="prom"} 10
252pint_prometheus_cache_hits_total{endpoint="/foo/7",name="prom"} 10
253pint_prometheus_cache_hits_total{endpoint="/foo/8",name="prom"} 10
254pint_prometheus_cache_hits_total{endpoint="/foo/9",name="prom"} 10
255# HELP pint_prometheus_cache_miss_total Total number of query cache misses
256# TYPE pint_prometheus_cache_miss_total counter
257pint_prometheus_cache_miss_total{endpoint="/foo/0",name="prom"} 20
258pint_prometheus_cache_miss_total{endpoint="/foo/1",name="prom"} 20
259pint_prometheus_cache_miss_total{endpoint="/foo/2",name="prom"} 20
260pint_prometheus_cache_miss_total{endpoint="/foo/3",name="prom"} 20
261pint_prometheus_cache_miss_total{endpoint="/foo/4",name="prom"} 20
262pint_prometheus_cache_miss_total{endpoint="/foo/5",name="prom"} 20
263pint_prometheus_cache_miss_total{endpoint="/foo/6",name="prom"} 20
264pint_prometheus_cache_miss_total{endpoint="/foo/7",name="prom"} 20
265pint_prometheus_cache_miss_total{endpoint="/foo/8",name="prom"} 20
266pint_prometheus_cache_miss_total{endpoint="/foo/9",name="prom"} 20
267# HELP pint_prometheus_cache_size Total number of entries currently stored in Prometheus query cache
268# TYPE pint_prometheus_cache_size gauge
269pint_prometheus_cache_size{name="prom"} 100
270`),
271 names...,
272 ))
273
274 for i = maxSize + 1; i <= maxSize+10; i++ {
275 cache.set(i, queryResult{}, 0)
276 }
277
278 require.NoError(t, testutil.CollectAndCompare(
279 collector, strings.NewReader(`
280# HELP pint_prometheus_cache_evictions_total Total number of times an entry was evicted from query cache due to size limit or TTL
281# TYPE pint_prometheus_cache_evictions_total counter
282pint_prometheus_cache_evictions_total{name="prom"} 10
283# HELP pint_prometheus_cache_hits_total Total number of query cache hits
284# TYPE pint_prometheus_cache_hits_total counter
285pint_prometheus_cache_hits_total{endpoint="/foo/0",name="prom"} 10
286pint_prometheus_cache_hits_total{endpoint="/foo/1",name="prom"} 10
287pint_prometheus_cache_hits_total{endpoint="/foo/2",name="prom"} 10
288pint_prometheus_cache_hits_total{endpoint="/foo/3",name="prom"} 10
289pint_prometheus_cache_hits_total{endpoint="/foo/4",name="prom"} 10
290pint_prometheus_cache_hits_total{endpoint="/foo/5",name="prom"} 10
291pint_prometheus_cache_hits_total{endpoint="/foo/6",name="prom"} 10
292pint_prometheus_cache_hits_total{endpoint="/foo/7",name="prom"} 10
293pint_prometheus_cache_hits_total{endpoint="/foo/8",name="prom"} 10
294pint_prometheus_cache_hits_total{endpoint="/foo/9",name="prom"} 10
295# HELP pint_prometheus_cache_miss_total Total number of query cache misses
296# TYPE pint_prometheus_cache_miss_total counter
297pint_prometheus_cache_miss_total{endpoint="/foo/0",name="prom"} 20
298pint_prometheus_cache_miss_total{endpoint="/foo/1",name="prom"} 20
299pint_prometheus_cache_miss_total{endpoint="/foo/2",name="prom"} 20
300pint_prometheus_cache_miss_total{endpoint="/foo/3",name="prom"} 20
301pint_prometheus_cache_miss_total{endpoint="/foo/4",name="prom"} 20
302pint_prometheus_cache_miss_total{endpoint="/foo/5",name="prom"} 20
303pint_prometheus_cache_miss_total{endpoint="/foo/6",name="prom"} 20
304pint_prometheus_cache_miss_total{endpoint="/foo/7",name="prom"} 20
305pint_prometheus_cache_miss_total{endpoint="/foo/8",name="prom"} 20
306pint_prometheus_cache_miss_total{endpoint="/foo/9",name="prom"} 20
307# HELP pint_prometheus_cache_size Total number of entries currently stored in Prometheus query cache
308# TYPE pint_prometheus_cache_size gauge
309pint_prometheus_cache_size{name="prom"} 100
310`),
311 names...,
312 ))
313}
314