Skip to content

Commit 1bf620c

Browse files
committed
chore: add unit test to ensure metrics are correct
1 parent 352cb4f commit 1bf620c

File tree

1 file changed

+63
-13
lines changed

1 file changed

+63
-13
lines changed

coderd/files/cache_internal_test.go

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,28 @@ import (
1313
"github.com/stretchr/testify/require"
1414
"golang.org/x/sync/errgroup"
1515

16+
"github.com/coder/coder/v2/coderd/coderdtest/promhelp"
1617
"github.com/coder/coder/v2/testutil"
1718
)
1819

20+
func cachePromMetricName(metric string) string {
21+
return "coderd_file_cache_" + metric
22+
}
23+
1924
func TestConcurrency(t *testing.T) {
2025
t.Parallel()
2126

27+
const fileSize = 10
2228
emptyFS := afero.NewIOFS(afero.NewReadOnlyFs(afero.NewMemMapFs()))
2329
var fetches atomic.Int64
24-
c := newTestCache(func(_ context.Context, _ uuid.UUID) (fs.FS, int64, error) {
30+
reg := prometheus.NewRegistry()
31+
c := New(func(_ context.Context, _ uuid.UUID) (fs.FS, int64, error) {
2532
fetches.Add(1)
2633
// Wait long enough before returning to make sure that all of the goroutines
2734
// will be waiting in line, ensuring that no one duplicated a fetch.
2835
time.Sleep(testutil.IntervalMedium)
29-
return emptyFS, 0, nil
30-
})
36+
return emptyFS, fileSize, nil
37+
}, reg)
3138

3239
batches := 1000
3340
groups := make([]*errgroup.Group, 0, batches)
@@ -55,15 +62,26 @@ func TestConcurrency(t *testing.T) {
5562
require.NoError(t, g.Wait())
5663
}
5764
require.Equal(t, int64(batches), fetches.Load())
65+
66+
// Verify all the counts & metrics are correct.
67+
require.Equal(t, batches, c.Count())
68+
require.Equal(t, batches*fileSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_size_current"), nil))
69+
require.Equal(t, batches*fileSize, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_size_total"), nil))
70+
require.Equal(t, batches, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_current"), nil))
71+
require.Equal(t, batches, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_total"), nil))
72+
require.Equal(t, batches*batchSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))
73+
require.Equal(t, batches*batchSize, promhelp.CounterValue(t, reg, cachePromMetricName("open_file_refs_total"), nil))
5874
}
5975

6076
func TestRelease(t *testing.T) {
6177
t.Parallel()
6278

79+
const fileSize = 10
6380
emptyFS := afero.NewIOFS(afero.NewReadOnlyFs(afero.NewMemMapFs()))
64-
c := newTestCache(func(_ context.Context, _ uuid.UUID) (fs.FS, int64, error) {
65-
return emptyFS, 0, nil
66-
})
81+
reg := prometheus.NewRegistry()
82+
c := New(func(_ context.Context, _ uuid.UUID) (fs.FS, int64, error) {
83+
return emptyFS, fileSize, nil
84+
}, reg)
6785

6886
batches := 100
6987
ids := make([]uuid.UUID, 0, batches)
@@ -73,28 +91,60 @@ func TestRelease(t *testing.T) {
7391

7492
// Acquire a bunch of references
7593
batchSize := 10
76-
for _, id := range ids {
77-
for range batchSize {
94+
for openedIdx, id := range ids {
95+
for batchIdx := range batchSize {
7896
it, err := c.Acquire(t.Context(), id)
7997
require.NoError(t, err)
8098
require.Equal(t, emptyFS, it)
99+
100+
// Each time a new file is opened, the metrics should be updated as so:
101+
opened := openedIdx + 1
102+
// Number of unique files opened is equal to the idx of the ids.
103+
require.Equal(t, opened, c.Count())
104+
require.Equal(t, opened, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_current"), nil))
105+
// Current file size is unique files * file size.
106+
require.Equal(t, opened*fileSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_size_current"), nil))
107+
// The number of refs is the current iteration of both loops.
108+
require.Equal(t, ((opened-1)*batchSize)+(batchIdx+1), promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))
81109
}
82110
}
83111

84112
// Make sure cache is fully loaded
85113
require.Equal(t, len(c.data), batches)
86114

87115
// Now release all of the references
88-
for _, id := range ids {
89-
for range batchSize {
116+
for closedIdx, id := range ids {
117+
stillOpen := len(ids) - closedIdx
118+
for closingIdx := range batchSize {
90119
c.Release(id)
120+
121+
// Each time a file is released, the metrics should decrement the file refs
122+
require.Equal(t, (stillOpen*batchSize)-(closingIdx+1), promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))
123+
124+
closed := closingIdx+1 == batchSize
125+
if closed {
126+
continue
127+
}
128+
129+
// File ref still exists, so the counts should not change yet.
130+
require.Equal(t, stillOpen, c.Count())
131+
require.Equal(t, stillOpen, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_current"), nil))
132+
require.Equal(t, stillOpen*fileSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_size_current"), nil))
91133
}
92134
}
93135

94136
// ...and make sure that the cache has emptied itself.
95137
require.Equal(t, len(c.data), 0)
96-
}
97138

98-
func newTestCache(fetcher func(context.Context, uuid.UUID) (fs.FS, int64, error)) *Cache {
99-
return New(fetcher, prometheus.NewRegistry())
139+
// Verify all the counts & metrics are correct.
140+
// All existing files are closed
141+
require.Equal(t, 0, c.Count())
142+
require.Equal(t, 0, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_size_current"), nil))
143+
require.Equal(t, 0, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_current"), nil))
144+
require.Equal(t, 0, promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))
145+
146+
// Total counts remain
147+
require.Equal(t, batches*fileSize, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_size_total"), nil))
148+
require.Equal(t, batches, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_total"), nil))
149+
require.Equal(t, batches*batchSize, promhelp.CounterValue(t, reg, cachePromMetricName("open_file_refs_total"), nil))
100150
}

0 commit comments

Comments
 (0)