Skip to content

Commit aa699b1

Browse files
committed
staticaddr: deflake deposit manager test
The sqlite and postgres race jobs were both hanging in deposit.TestManager. The test was observing the manager through implementation details that were not safe to share with the manager itself: - it replaced the manager's internal finalizedDepositChan and then waited on the same channel the manager consumes - it reused package-level block and confirmation channels across runs - it treated confirmationHeight+expiry as the last pre-expiry block even though the production IsExpired check uses >= - it relied on scheduler timing when asserting that no sign request had happened yet Make the test assert on stable effects instead of internal channel ownership: - create per-test notifier channels in the test context - run the manager from a cancellable t.Context-derived context and assert clean shutdown - send the actual last pre-expiry height, then the expiry height - wait for the expiry sign and publish steps with bounded timeouts - verify finalization by waiting for the manager to remove the deposit from activeDeposits instead of racing its private finalization channel This keeps the test aligned with the production expiry semantics and removes the race that only showed up reliably under -race.
1 parent bf47c92 commit aa699b1

1 file changed

Lines changed: 65 additions & 23 deletions

File tree

staticaddr/deposit/manager_test.go

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,6 @@ var (
3333
defaultExpiry = uint32(100)
3434

3535
defaultDepositConfirmations = uint32(3)
36-
37-
confChan = make(chan *chainntnfs.TxConfirmation)
38-
39-
confErrChan = make(chan error)
40-
41-
blockChan = make(chan int32)
42-
43-
blockErrChan = make(chan error)
44-
45-
finalizedDepositChan = make(chan wire.OutPoint)
4636
)
4737

4838
type mockStaticAddressClient struct {
@@ -229,48 +219,89 @@ func (m *MockChainNotifier) RegisterSpendNtfn(ctx context.Context,
229219
// TestManager checks that the manager processes the right channel notifications
230220
// while a deposit is expiring.
231221
func TestManager(t *testing.T) {
232-
ctx := context.Background()
222+
ctx, cancel := context.WithCancel(t.Context())
223+
defer cancel()
224+
225+
const defaultTimeout = 30 * time.Second
233226

234227
// Create the test context with required mocks.
235228
testContext := newManagerTestContext(t)
236229

237230
// Start the deposit manager.
238231
initChan := make(chan struct{})
232+
runErrChan := make(chan error, 1)
239233
go func() {
240-
require.NoError(t, testContext.manager.Run(ctx, initChan))
234+
runErrChan <- testContext.manager.Run(ctx, initChan)
241235
}()
242236

243237
// Ensure that the manager has been initialized.
244-
<-initChan
238+
select {
239+
case <-initChan:
240+
case err := <-runErrChan:
241+
require.NoError(t, err, "manager failed to start")
242+
243+
case <-time.After(defaultTimeout):
244+
t.Fatal("manager timed out starting")
245+
}
245246

246247
// Notify about the last block before the expiry.
247-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
248+
testContext.blockChan <- int32(
249+
defaultDepositConfirmations + defaultExpiry - 1,
250+
)
248251

249252
// Ensure that the deposit state machine didn't sign for the expiry tx.
250253
select {
251254
case <-testContext.mockLnd.SignOutputRawChannel:
252255
t.Fatal("received unexpected sign request")
253256

254-
default:
257+
case <-time.After(defaultTimeout):
255258
}
256259

257260
// Mine the expiry tx height.
258-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
261+
testContext.blockChan <- int32(
262+
defaultDepositConfirmations + defaultExpiry,
263+
)
259264

260-
// Ensure that the deposit state machine didn't sign for the expiry tx.
261-
<-testContext.mockLnd.SignOutputRawChannel
265+
// Ensure that the deposit state machine signed the expiry tx.
266+
select {
267+
case <-testContext.mockLnd.SignOutputRawChannel:
268+
269+
case <-time.After(defaultTimeout):
270+
t.Fatal("did not receive sign request")
271+
}
262272

263273
// Ensure that the signed expiry transaction is published.
264-
expiryTx := <-testContext.mockLnd.TxPublishChannel
274+
var expiryTx *wire.MsgTx
275+
select {
276+
case expiryTx = <-testContext.mockLnd.TxPublishChannel:
277+
278+
case <-time.After(defaultTimeout):
279+
t.Fatal("did not receive published expiry tx")
280+
}
265281

266282
// Ensure that the deposit is waiting for a confirmation notification.
267-
confChan <- &chainntnfs.TxConfirmation{
283+
testContext.confChan <- &chainntnfs.TxConfirmation{
268284
BlockHeight: defaultDepositConfirmations + defaultExpiry + 3,
269285
Tx: expiryTx,
270286
}
271287

272-
// Ensure that the deposit is finalized.
273-
<-finalizedDepositChan
288+
// Ensure that the manager observed the finalization and removed the
289+
// deposit from its active set.
290+
require.Eventually(t, func() bool {
291+
testContext.manager.mu.Lock()
292+
defer testContext.manager.mu.Unlock()
293+
294+
return len(testContext.manager.activeDeposits) == 0
295+
}, defaultTimeout, 10*time.Millisecond)
296+
297+
cancel()
298+
select {
299+
case err := <-runErrChan:
300+
require.ErrorIs(t, err, context.Canceled)
301+
302+
case <-time.After(defaultTimeout):
303+
t.Fatal("manager did not stop")
304+
}
274305
}
275306

276307
// ManagerTestContext is a helper struct that contains all the necessary
@@ -281,6 +312,10 @@ type ManagerTestContext struct {
281312
mockLnd *test.LndMockServices
282313
mockStaticAddressClient *mockStaticAddressClient
283314
mockAddressManager *mockAddressManager
315+
confChan chan *chainntnfs.TxConfirmation
316+
confErrChan chan error
317+
blockChan chan int32
318+
blockErrChan chan error
284319
}
285320

286321
// newManagerTestContext creates a new test context for the reservation manager.
@@ -292,6 +327,10 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
292327
mockAddressManager := new(mockAddressManager)
293328
mockStore := new(mockStore)
294329
mockChainNotifier := new(MockChainNotifier)
330+
confChan := make(chan *chainntnfs.TxConfirmation)
331+
confErrChan := make(chan error)
332+
blockChan := make(chan int32)
333+
blockErrChan := make(chan error)
295334

296335
ID, err := GetRandomDepositID()
297336
utxo := &lnwallet.Utxo{
@@ -353,14 +392,17 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
353392
}
354393

355394
manager := NewManager(cfg)
356-
manager.finalizedDepositChan = finalizedDepositChan
357395

358396
testContext := &ManagerTestContext{
359397
manager: manager,
360398
context: lndContext,
361399
mockLnd: mockLnd,
362400
mockStaticAddressClient: mockStaticAddressClient,
363401
mockAddressManager: mockAddressManager,
402+
confChan: confChan,
403+
confErrChan: confErrChan,
404+
blockChan: blockChan,
405+
blockErrChan: blockErrChan,
364406
}
365407

366408
staticAddress := generateStaticAddress(

0 commit comments

Comments
 (0)