Skip to content

Commit 67f6f30

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 67f6f30

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

staticaddr/deposit/manager_test.go

Lines changed: 47 additions & 22 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,72 @@ 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.
244236
<-initChan
245237

246238
// Notify about the last block before the expiry.
247-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
239+
testContext.blockChan <- int32(
240+
defaultDepositConfirmations + defaultExpiry - 1,
241+
)
248242

249243
// Ensure that the deposit state machine didn't sign for the expiry tx.
250244
select {
251245
case <-testContext.mockLnd.SignOutputRawChannel:
252246
t.Fatal("received unexpected sign request")
253247

254-
default:
248+
case <-time.After(100 * time.Millisecond):
255249
}
256250

257251
// Mine the expiry tx height.
258-
blockChan <- int32(defaultDepositConfirmations + defaultExpiry)
252+
testContext.blockChan <- int32(
253+
defaultDepositConfirmations + defaultExpiry,
254+
)
259255

260-
// Ensure that the deposit state machine didn't sign for the expiry tx.
261-
<-testContext.mockLnd.SignOutputRawChannel
256+
// Ensure that the deposit state machine signed the expiry tx.
257+
select {
258+
case <-testContext.mockLnd.SignOutputRawChannel:
259+
case <-time.After(test.Timeout):
260+
t.Fatal("did not receive sign request")
261+
}
262262

263263
// Ensure that the signed expiry transaction is published.
264-
expiryTx := <-testContext.mockLnd.TxPublishChannel
264+
var expiryTx *wire.MsgTx
265+
select {
266+
case expiryTx = <-testContext.mockLnd.TxPublishChannel:
267+
case <-time.After(test.Timeout):
268+
t.Fatal("did not receive published expiry tx")
269+
}
265270

266271
// Ensure that the deposit is waiting for a confirmation notification.
267-
confChan <- &chainntnfs.TxConfirmation{
272+
testContext.confChan <- &chainntnfs.TxConfirmation{
268273
BlockHeight: defaultDepositConfirmations + defaultExpiry + 3,
269274
Tx: expiryTx,
270275
}
271276

272-
// Ensure that the deposit is finalized.
273-
<-finalizedDepositChan
277+
// Ensure that the manager observed the finalization and removed the
278+
// deposit from its active set.
279+
require.Eventually(t, func() bool {
280+
testContext.manager.mu.Lock()
281+
defer testContext.manager.mu.Unlock()
282+
283+
return len(testContext.manager.activeDeposits) == 0
284+
}, test.Timeout, 10*time.Millisecond)
285+
286+
cancel()
287+
require.ErrorIs(t, <-runErrChan, context.Canceled)
274288
}
275289

276290
// ManagerTestContext is a helper struct that contains all the necessary
@@ -281,6 +295,10 @@ type ManagerTestContext struct {
281295
mockLnd *test.LndMockServices
282296
mockStaticAddressClient *mockStaticAddressClient
283297
mockAddressManager *mockAddressManager
298+
confChan chan *chainntnfs.TxConfirmation
299+
confErrChan chan error
300+
blockChan chan int32
301+
blockErrChan chan error
284302
}
285303

286304
// newManagerTestContext creates a new test context for the reservation manager.
@@ -292,6 +310,10 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
292310
mockAddressManager := new(mockAddressManager)
293311
mockStore := new(mockStore)
294312
mockChainNotifier := new(MockChainNotifier)
313+
confChan := make(chan *chainntnfs.TxConfirmation)
314+
confErrChan := make(chan error)
315+
blockChan := make(chan int32)
316+
blockErrChan := make(chan error)
295317

296318
ID, err := GetRandomDepositID()
297319
utxo := &lnwallet.Utxo{
@@ -353,14 +375,17 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
353375
}
354376

355377
manager := NewManager(cfg)
356-
manager.finalizedDepositChan = finalizedDepositChan
357378

358379
testContext := &ManagerTestContext{
359380
manager: manager,
360381
context: lndContext,
361382
mockLnd: mockLnd,
362383
mockStaticAddressClient: mockStaticAddressClient,
363384
mockAddressManager: mockAddressManager,
385+
confChan: confChan,
386+
confErrChan: confErrChan,
387+
blockChan: blockChan,
388+
blockErrChan: blockErrChan,
364389
}
365390

366391
staticAddress := generateStaticAddress(

0 commit comments

Comments
 (0)