MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / TestSequenceAllocatorDeadlock

Function TestSequenceAllocatorDeadlock

db/sequence_allocator_test.go:151–208  ·  view source on GitHub ↗

Reproduces deadlock from CBG-663. Required adding a sleep inside the <-time.After case in releaseSequenceMonitor to reliably queue up a large number of sequence allocation requests between <-time.After fires and releaseUnusedSequences is called (where previously reserveNotify would block)

(t *testing.T)

Source from the content-addressed store, hash-verified

149// releaseSequenceMonitor to reliably queue up a large number of sequence allocation requests
150// between <-time.After fires and releaseUnusedSequences is called (where previously reserveNotify would block)
151func TestSequenceAllocatorDeadlock(t *testing.T) {
152
153 t.Skip("Requires additional sleep in production code to reliably hit race")
154
155 var a *sequenceAllocator
156 var err error
157
158 var wg sync.WaitGroup
159 ctx := base.TestCtx(t)
160 callbackCount := 0
161 incrCallback := func() {
162 callbackCount++
163 if callbackCount == 2 {
164 // queue up a number of sequence requests
165 // Wait for 500ms for releaseSequenceMonitor time.After to trigger
166 time.Sleep(100 * time.Millisecond)
167
168 for i := 0; i < 500; i++ {
169 wg.Add(1)
170 go func(a *sequenceAllocator) {
171 _, err := a.nextSequence(ctx)
172 assert.NoError(t, err)
173 wg.Done()
174 }(a)
175 }
176 }
177 }
178
179 bucket := base.NewLeakyBucket(base.GetTestBucket(t), base.LeakyBucketConfig{IncrCallback: incrCallback})
180 defer bucket.Close(ctx)
181
182 sgw, err := base.NewSyncGatewayStats()
183 require.NoError(t, err)
184 dbstats, err := sgw.NewDBStats("", false, false, false, nil, nil)
185 require.NoError(t, err)
186 testStats := dbstats.Database()
187
188 oldFrequency := MaxSequenceIncrFrequency
189 defer func() { MaxSequenceIncrFrequency = oldFrequency }()
190 MaxSequenceIncrFrequency = 1000 * time.Millisecond
191
192 a, err = newSequenceAllocator(ctx, bucket.DefaultDataStore(), testStats, base.DefaultMetadataKeys)
193 // Reduce sequence wait for Stop testing
194 a.releaseSequenceWait = 10 * time.Millisecond
195 assert.NoError(t, err, "error creating allocator")
196
197 nextSequence, err := a.nextSequence(ctx)
198 assert.NoError(t, err)
199 assert.Equal(t, uint64(1), nextSequence)
200
201 nextSequence, err = a.nextSequence(ctx)
202 assert.NoError(t, err)
203 assert.Equal(t, uint64(2), nextSequence)
204
205 wg.Wait()
206
207 a.Stop(ctx)
208}

Callers

nothing calls this directly

Calls 15

nextSequenceMethod · 0.95
CloseMethod · 0.95
DefaultDataStoreMethod · 0.95
StopMethod · 0.95
TestCtxFunction · 0.92
NewLeakyBucketFunction · 0.92
GetTestBucketFunction · 0.92
NewSyncGatewayStatsFunction · 0.92
DoneMethod · 0.80
NewDBStatsMethod · 0.80
newSequenceAllocatorFunction · 0.70
AddMethod · 0.45

Tested by

no test coverage detected