Skip to content

Commit 3c49d7c

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 30472d0 commit 3c49d7c

File tree

1 file changed

+63
-23
lines changed

1 file changed

+63
-23
lines changed

staticaddr/deposit/manager_test.go

Lines changed: 63 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,87 @@ 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()
233224

234225
// Create the test context with required mocks.
235226
testContext := newManagerTestContext(t)
236227

237228
// Start the deposit manager.
238229
initChan := make(chan struct{})
230+
runErrChan := make(chan error, 1)
239231
go func() {
240-
require.NoError(t, testContext.manager.Run(ctx, initChan))
232+
runErrChan <- testContext.manager.Run(ctx, initChan)
241233
}()
242234

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

246245
// Notify about the last block before the expiry.
247-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
246+
testContext.blockChan <- int32(
247+
defaultDepositConfirmations + defaultExpiry - 1,
248+
)
248249

249250
// Ensure that the deposit state machine didn't sign for the expiry tx.
250251
select {
251252
case <-testContext.mockLnd.SignOutputRawChannel:
252253
t.Fatal("received unexpected sign request")
253254

254-
default:
255+
case <-time.After(test.Timeout / 10):
255256
}
256257

257258
// Mine the expiry tx height.
258-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
259+
testContext.blockChan <- int32(
260+
defaultDepositConfirmations + defaultExpiry,
261+
)
259262

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

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

266280
// Ensure that the deposit is waiting for a confirmation notification.
267-
confChan <- &chainntnfs.TxConfirmation{
281+
testContext.confChan <- &chainntnfs.TxConfirmation{
268282
BlockHeight: defaultDepositConfirmations + defaultExpiry + 3,
269283
Tx: expiryTx,
270284
}
271285

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

276305
// ManagerTestContext is a helper struct that contains all the necessary
@@ -281,6 +310,10 @@ type ManagerTestContext struct {
281310
mockLnd *test.LndMockServices
282311
mockStaticAddressClient *mockStaticAddressClient
283312
mockAddressManager *mockAddressManager
313+
confChan chan *chainntnfs.TxConfirmation
314+
confErrChan chan error
315+
blockChan chan int32
316+
blockErrChan chan error
284317
}
285318

286319
// newManagerTestContext creates a new test context for the reservation manager.
@@ -292,6 +325,10 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
292325
mockAddressManager := new(mockAddressManager)
293326
mockStore := new(mockStore)
294327
mockChainNotifier := new(MockChainNotifier)
328+
confChan := make(chan *chainntnfs.TxConfirmation)
329+
confErrChan := make(chan error)
330+
blockChan := make(chan int32)
331+
blockErrChan := make(chan error)
295332

296333
ID, err := GetRandomDepositID()
297334
utxo := &lnwallet.Utxo{
@@ -353,14 +390,17 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
353390
}
354391

355392
manager := NewManager(cfg)
356-
manager.finalizedDepositChan = finalizedDepositChan
357393

358394
testContext := &ManagerTestContext{
359395
manager: manager,
360396
context: lndContext,
361397
mockLnd: mockLnd,
362398
mockStaticAddressClient: mockStaticAddressClient,
363399
mockAddressManager: mockAddressManager,
400+
confChan: confChan,
401+
confErrChan: confErrChan,
402+
blockChan: blockChan,
403+
blockErrChan: blockErrChan,
364404
}
365405

366406
staticAddress := generateStaticAddress(

0 commit comments

Comments
 (0)