MCPcopy Index your code
hub / github.com/coder/coder / TestConcurrency

Function TestConcurrency

coderd/files/cache_test.go:198–256  ·  view source on GitHub ↗
(t *testing.T)

Source from the content-addressed store, hash-verified

196}
197
198func TestConcurrency(t *testing.T) {
199 t.Parallel()
200 ctx := dbauthz.AsFileReader(t.Context())
201
202 const fileSize = 10
203 var fetches atomic.Int64
204 reg := prometheus.NewRegistry()
205
206 dbM := dbmock.NewMockStore(gomock.NewController(t))
207 dbM.EXPECT().GetFileByID(gomock.Any(), gomock.Any()).DoAndReturn(func(mTx context.Context, fileID uuid.UUID) (database.File, error) {
208 fetches.Add(1)
209 // Wait long enough before returning to make sure that all the goroutines
210 // will be waiting in line, ensuring that no one duplicated a fetch.
211 time.Sleep(testutil.IntervalMedium)
212 return database.File{
213 Data: make([]byte, fileSize),
214 }, nil
215 }).AnyTimes()
216
217 c := files.New(reg, &coderdtest.FakeAuthorizer{})
218
219 batches := 1000
220 groups := make([]*errgroup.Group, 0, batches)
221 for range batches {
222 groups = append(groups, new(errgroup.Group))
223 }
224
225 // Call Acquire with a unique ID per batch, many times per batch, with many
226 // batches all in parallel. This is pretty much the worst-case scenario:
227 // thousands of concurrent reads, with both warm and cold loads happening.
228 batchSize := 10
229 for _, g := range groups {
230 id := uuid.New()
231 for range batchSize {
232 g.Go(func() error {
233 // We don't bother to Release these references because the Cache will be
234 // released at the end of the test anyway.
235 _, err := c.Acquire(ctx, dbM, id)
236 return err
237 })
238 }
239 }
240
241 for _, g := range groups {
242 require.NoError(t, g.Wait())
243 }
244 require.Equal(t, int64(batches), fetches.Load())
245
246 // Verify all the counts & metrics are correct.
247 require.Equal(t, batches, c.Count())
248 require.Equal(t, batches*fileSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_size_bytes_current"), nil))
249 require.Equal(t, batches*fileSize, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_size_bytes_total"), nil))
250 require.Equal(t, batches, promhelp.GaugeValue(t, reg, cachePromMetricName("open_files_current"), nil))
251 require.Equal(t, batches, promhelp.CounterValue(t, reg, cachePromMetricName("open_files_total"), nil))
252 require.Equal(t, batches*batchSize, promhelp.GaugeValue(t, reg, cachePromMetricName("open_file_refs_current"), nil))
253 hit, miss := promhelp.CounterValue(t, reg, cachePromMetricName("open_file_refs_total"), prometheus.Labels{"hit": "false"}),
254 promhelp.CounterValue(t, reg, cachePromMetricName("open_file_refs_total"), prometheus.Labels{"hit": "true"})
255 require.Equal(t, batches*batchSize, hit+miss)

Callers

nothing calls this directly

Calls 15

EXPECTMethod · 0.95
AsFileReaderFunction · 0.92
NewMockStoreFunction · 0.92
NewFunction · 0.92
GaugeValueFunction · 0.92
CounterValueFunction · 0.92
cachePromMetricNameFunction · 0.85
GoMethod · 0.80
CountMethod · 0.80
ContextMethod · 0.65
GetFileByIDMethod · 0.65
AddMethod · 0.65

Tested by

no test coverage detected