From 6ea99cde424b13d07dd5496e2da2e73b97aef813 Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Wed, 17 Dec 2025 18:15:36 +0100 Subject: [PATCH 1/2] invoices: increase timeout parallel Postgres tests Increase the test timeout from 10s to 60s to accommodate slow Postgres database setup and migrations when running tests in parallel. This prevents false-positive test failures on slower CI runners. --- invoices/test_utils_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/invoices/test_utils_test.go b/invoices/test_utils_test.go index 6062b3b80..3ee8e965e 100644 --- a/invoices/test_utils_test.go +++ b/invoices/test_utils_test.go @@ -100,6 +100,8 @@ const ( var ( testTimeout = 5 * time.Second + testTimeoutLong = time.Minute + testTime = time.Date(2018, time.February, 2, 14, 0, 0, 0, time.UTC) testInvoicePreimage = lntypes.Preimage{1} @@ -255,7 +257,9 @@ func timeout() func() { go func() { select { - case <-time.After(10 * time.Second): + // Use a longer timeout to accommodate slow Postgres database + // setup and migrations when running tests in parallel. + case <-time.After(testTimeoutLong): err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) if err != nil { panic(fmt.Sprintf("error writing to std out "+ From 09379d03814c30f087e9da59b533343a9ef3c741 Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Wed, 17 Dec 2025 17:09:00 +0100 Subject: [PATCH 2/2] wtclient: fix race conditions locking tests This commit fixes two flaky test scenarios: 1. testRemoveLockedAddr: Add synchronization to wait for the dial to start before asserting that the address is locked. Previously, the test could race and check the lock state before session negotiation began. 2. testTowerSwitch: Use wait.Predicate for RemoveTower since the address may still be locked by an active session, causing intermittent failures. --- watchtower/wtclient/client_test.go | 33 ++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/watchtower/wtclient/client_test.go b/watchtower/wtclient/client_test.go index e842876b6..1b50600ae 100644 --- a/watchtower/wtclient/client_test.go +++ b/watchtower/wtclient/client_test.go @@ -1811,8 +1811,10 @@ var clientTests = []clientTest{ require.NoError(h.t, err) cancel := make(chan struct{}) + dialStarted := make(chan struct{}) h.net.registerConnCallback( h.server.addr, func(peer wtserver.Peer) { + close(dialStarted) select { case <-h.quit: case <-cancel: @@ -1847,6 +1849,16 @@ var clientTests = []clientTest{ err = h.clientMgr.AddTower(towerAddr) require.NoError(h.t, err) + // Wait for the dial to start so that we know the + // session negotiation has begun and the address is + // locked. + select { + case <-dialStarted: + + case <-time.After(waitTime): + h.t.Fatal("timeout waiting for dial to start") + } + // Assert that if the client attempts to remove the // tower's first address, then it will error due to // address currently being locked for session @@ -2354,10 +2366,23 @@ var clientTests = []clientTest{ }, waitTime) require.NoError(h.t, err) - // Now remove the tower. - err = h.clientMgr.RemoveTower( - h.server.addr.IdentityKey, nil, - ) + // Now remove the tower. We use wait.Predicate here + // because the address may still be locked by an active + // session. + err = wait.Predicate(func() bool { + err := h.clientMgr.RemoveTower( + h.server.addr.IdentityKey, nil, + ) + if err != nil { + require.ErrorIs( + h.t, err, wtclient.ErrAddrInUse, + ) + + return false + } + + return true + }, waitTime) require.NoError(h.t, err) // Add a new tower.