Skip to content

Commit fd58cbf

Browse files
authored
Merge pull request #7954 from yyforyongyu/fix-chainfee-unit-test
multi: fix unit test flakes
2 parents 84b2f2d + 50f2c27 commit fd58cbf

File tree

5 files changed

+122
-81
lines changed

5 files changed

+122
-81
lines changed

aezeed/cipherseed_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,17 @@ func TestDecipherIncorrectMnemonic(t *testing.T) {
533533
// a checksum failure.
534534
swapIndex1 := 9
535535
swapIndex2 := 13
536-
mnemonic[swapIndex1], mnemonic[swapIndex2] = mnemonic[swapIndex2], mnemonic[swapIndex1]
536+
537+
mnemonic[swapIndex1], mnemonic[swapIndex2] =
538+
mnemonic[swapIndex2], mnemonic[swapIndex1]
539+
540+
// If the words happen to be the same by pure chance, we'll try again
541+
// with different indexes.
542+
if mnemonic[swapIndex1] == mnemonic[swapIndex2] {
543+
swapIndex1 = 3
544+
mnemonic[swapIndex1], mnemonic[swapIndex2] =
545+
mnemonic[swapIndex2], mnemonic[swapIndex1]
546+
}
537547

538548
// If we attempt to decrypt now, we should get a checksum failure.
539549
// If we attempt to map back to the original cipher seed now, then we

chainntnfs/bitcoindnotify/bitcoind_test.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package bitcoindnotify
55

66
import (
77
"bytes"
8+
"fmt"
89
"testing"
910
"time"
1011

@@ -14,6 +15,7 @@ import (
1415
"github.com/lightningnetwork/lnd/blockcache"
1516
"github.com/lightningnetwork/lnd/chainntnfs"
1617
"github.com/lightningnetwork/lnd/channeldb"
18+
"github.com/lightningnetwork/lnd/lntest/wait"
1719
"github.com/stretchr/testify/require"
1820
)
1921

@@ -162,18 +164,21 @@ func testHistoricalConfDetailsTxIndex(t *testing.T, rpcPolling bool) {
162164
confReq, err := chainntnfs.NewConfRequest(txid, pkScript)
163165
require.NoError(t, err, "unable to create conf request")
164166

165-
// The transaction should be found in the mempool at this point.
166-
_, txStatus, err = notifier.historicalConfDetails(confReq, 0, 0)
167-
require.NoError(t, err, "unable to retrieve historical conf details")
167+
// The transaction should be found in the mempool at this point. We use
168+
// wait here to give miner some time to propagate the tx to our node.
169+
err = wait.NoError(func() error {
170+
// The call should return no error.
171+
_, txStatus, err = notifier.historicalConfDetails(confReq, 0, 0)
172+
require.NoError(t, err)
168173

169-
// Since it has yet to be included in a block, it should have been found
170-
// within the mempool.
171-
switch txStatus {
172-
case chainntnfs.TxFoundMempool:
173-
default:
174-
t.Fatalf("should have found the transaction within the "+
175-
"mempool, but did not: %v", txStatus)
176-
}
174+
if txStatus != chainntnfs.TxFoundMempool {
175+
return fmt.Errorf("cannot the tx in mempool, status "+
176+
"is: %v", txStatus)
177+
}
178+
179+
return nil
180+
}, wait.DefaultTimeout)
181+
require.NoError(t, err, "timeout waitinfg for historicalConfDetails")
177182

178183
if _, err := miner.Client.Generate(1); err != nil {
179184
t.Fatalf("unable to generate block: %v", err)

contractcourt/taproot_briefcase_test.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,14 @@ func randResolverCtrlBlocks(t *testing.T) resolverCtrlBlocks {
2929

3030
func randHtlcTweaks(t *testing.T) htlcTapTweaks {
3131
numTweaks := rand.Int() % 256
32-
tweaks := make(htlcTapTweaks, numTweaks)
3332

33+
// If the numTweaks happens to be zero, we return a nil to avoid
34+
// initializing the map.
35+
if numTweaks == 0 {
36+
return nil
37+
}
38+
39+
tweaks := make(htlcTapTweaks, numTweaks)
3440
for i := 0; i < numTweaks; i++ {
3541
var id resolverID
3642
_, err := rand.Read(id[:])

lnwallet/chainfee/estimator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) (
610610
// returned. We will log the error and return the fall back fee rate
611611
// instead.
612612
if err != nil {
613-
log.Errorf("unable to query estimator: %v", err)
613+
log.Errorf("Unable to query estimator: %v", err)
614614
}
615615

616616
// If the result is too low, then we'll clamp it to our current fee

lnwallet/chainfee/estimator_test.go

+87-67
Original file line numberDiff line numberDiff line change
@@ -155,92 +155,91 @@ func TestSparseConfFeeSource(t *testing.T) {
155155
// as expected.
156156
func TestWebAPIFeeEstimator(t *testing.T) {
157157
t.Parallel()
158-
feeFloor := uint32(FeePerKwFloor.FeePerKVByte())
159-
testFeeRate := feeFloor * 100
158+
159+
var (
160+
minTarget uint32 = 2
161+
maxTarget uint32 = 6
162+
163+
// Fee rates are in sat/kb.
164+
minFeeRate uint32 = 2000 // 500 sat/kw
165+
maxFeeRate uint32 = 4000 // 1000 sat/kw
166+
)
160167

161168
testCases := []struct {
162-
name string
163-
target uint32
164-
apiEst uint32
165-
est uint32
166-
err string
169+
name string
170+
target uint32
171+
expectedFeeRate uint32
172+
expectedErr string
167173
}{
168174
{
169-
name: "target_below_min",
170-
target: 0,
171-
apiEst: 0,
172-
est: 0,
173-
err: "too low, minimum",
174-
},
175-
{
176-
name: "target_w_too-low_fee",
177-
target: 100,
178-
apiEst: 42,
179-
est: feeFloor,
180-
err: "",
175+
// When requested target is below minBlockTarget, an
176+
// error is returned.
177+
name: "target_below_min",
178+
target: 0,
179+
expectedFeeRate: 0,
180+
expectedErr: "too low, minimum",
181181
},
182182
{
183-
name: "API-omitted_target",
184-
target: 2,
185-
apiEst: 0,
186-
est: testFeeRate,
187-
err: "",
183+
// When requested target is larger than the max cached
184+
// target, the fee rate of the max cached target is
185+
// returned.
186+
name: "target_w_too-low_fee",
187+
target: maxTarget + 100,
188+
expectedFeeRate: minFeeRate,
189+
expectedErr: "",
188190
},
189191
{
190-
name: "valid_target",
191-
target: 20,
192-
apiEst: testFeeRate,
193-
est: testFeeRate,
194-
err: "",
192+
// When requested target is smaller than the min cahced
193+
// target, the fee rate of the min cached target is
194+
// returned.
195+
name: "API-omitted_target",
196+
target: minTarget - 1,
197+
expectedFeeRate: maxFeeRate,
198+
expectedErr: "",
195199
},
196200
{
197-
name: "valid_target_extrapolated_fee",
198-
target: 25,
199-
apiEst: 0,
200-
est: testFeeRate,
201-
err: "",
201+
// When the target is found, return it.
202+
name: "valid_target",
203+
target: maxTarget,
204+
expectedFeeRate: minFeeRate,
205+
expectedErr: "",
202206
},
203207
}
204208

205209
// Construct mock fee source for the Estimator to pull fees from.
206210
//
207211
// This will create a `feeByBlockTarget` map with the following values,
208-
// - 20: testFeeRate
209-
// - 100: 42, which will be floored to feeFloor.
210-
testFees := make(map[uint32]uint32)
211-
for _, tc := range testCases {
212-
if tc.apiEst != 0 {
213-
testFees[tc.target] = tc.apiEst
214-
}
212+
// - 2: 4000 sat/kb
213+
// - 6: 2000 sat/kb.
214+
feeRateResp := map[uint32]uint32{
215+
minTarget: maxFeeRate,
216+
maxTarget: minFeeRate,
215217
}
216218

217219
feeSource := mockSparseConfFeeSource{
218220
url: "https://www.github.com",
219-
fees: testFees,
221+
fees: feeRateResp,
220222
}
221223

222224
estimator := NewWebAPIEstimator(feeSource, false)
223225

224-
// Test that requesting a fee when no fees have been cached fails.
226+
// Test that requesting a fee when no fees have been cached won't fail.
225227
feeRate, err := estimator.EstimateFeePerKW(5)
226228
require.NoErrorf(t, err, "expected no error")
227229
require.Equalf(t, FeePerKwFloor, feeRate, "expected fee rate floor "+
228230
"returned when no cached fee rate found")
229231

230-
if err := estimator.Start(); err != nil {
231-
t.Fatalf("unable to start fee estimator, got: %v", err)
232-
}
233-
defer estimator.Stop()
232+
require.NoError(t, estimator.Start(), "unable to start fee estimator")
234233

235234
for _, tc := range testCases {
236235
tc := tc
237236
t.Run(tc.name, func(t *testing.T) {
238237
est, err := estimator.EstimateFeePerKW(tc.target)
239238

240239
// Test an error case.
241-
if tc.err != "" {
240+
if tc.expectedErr != "" {
242241
require.Error(t, err, "expected error")
243-
require.ErrorContains(t, err, tc.err)
242+
require.ErrorContains(t, err, tc.expectedErr)
244243

245244
return
246245
}
@@ -249,57 +248,78 @@ func TestWebAPIFeeEstimator(t *testing.T) {
249248
require.NoErrorf(t, err, "error from target %v",
250249
tc.target)
251250

252-
exp := SatPerKVByte(tc.est).FeePerKWeight()
251+
exp := SatPerKVByte(tc.expectedFeeRate).FeePerKWeight()
253252
require.Equalf(t, exp, est, "target %v failed, fee "+
254253
"map is %v", tc.target, feeSource.fees)
255254
})
256255
}
256+
257+
// Stop the estimator when test ends.
258+
require.NoError(t, estimator.Stop(), "unable to stop fee estimator")
257259
}
258260

259261
// TestGetCachedFee checks that the fee caching logic works as expected.
260262
func TestGetCachedFee(t *testing.T) {
261-
target := uint32(2)
262-
fee := uint32(100)
263+
var (
264+
minTarget uint32 = 2
265+
maxTarget uint32 = 6
266+
267+
minFeeRate uint32 = 100
268+
maxFeeRate uint32 = 1000
269+
)
263270

264271
// Create a dummy estimator without WebAPIFeeSource.
265272
estimator := NewWebAPIEstimator(nil, false)
266273

267274
// When the cache is empty, an error should be returned.
268-
cachedFee, err := estimator.getCachedFee(target)
275+
cachedFee, err := estimator.getCachedFee(minTarget)
269276
require.Zero(t, cachedFee)
270277
require.ErrorIs(t, err, errEmptyCache)
271278

272-
// Store a fee rate inside the cache.
273-
estimator.feeByBlockTarget[target] = fee
279+
// Store a fee rate inside the cache. The cache map now looks like,
280+
// {2: 1000, 6: 100}
281+
estimator.feeByBlockTarget = map[uint32]uint32{
282+
minTarget: maxFeeRate,
283+
maxTarget: minFeeRate,
284+
}
274285

275286
testCases := []struct {
276287
name string
277288
confTarget uint32
278289
expectedFee uint32
279-
expectErr error
280290
}{
281291
{
282292
// When the target is cached, return it.
283293
name: "return cached fee",
284-
confTarget: target,
285-
expectedFee: fee,
286-
expectErr: nil,
294+
confTarget: minTarget,
295+
expectedFee: maxFeeRate,
296+
},
297+
{
298+
// When the target is not cached, return the next
299+
// lowest target that's cached. In this case,
300+
// requesting fee rate for target 7 will give the
301+
// result for target 6.
302+
name: "return lowest cached fee",
303+
confTarget: maxTarget + 1,
304+
expectedFee: minFeeRate,
287305
},
288306
{
289307
// When the target is not cached, return the next
290-
// lowest target that's cached.
308+
// lowest target that's cached. In this case,
309+
// requesting fee rate for target 5 will give the
310+
// result for target 2.
291311
name: "return next cached fee",
292-
confTarget: target + 1,
293-
expectedFee: fee,
294-
expectErr: nil,
312+
confTarget: maxTarget - 1,
313+
expectedFee: maxFeeRate,
295314
},
296315
{
297316
// When the target is not cached, and the next lowest
298317
// target is not cached, return the nearest fee rate.
318+
// In this case, requesting fee rate for target 1 will
319+
// give the result for target 2.
299320
name: "return highest cached fee",
300-
confTarget: target - 1,
301-
expectedFee: fee,
302-
expectErr: nil,
321+
confTarget: minTarget - 1,
322+
expectedFee: maxFeeRate,
303323
},
304324
}
305325

@@ -309,8 +329,8 @@ func TestGetCachedFee(t *testing.T) {
309329
t.Run(tc.name, func(t *testing.T) {
310330
cachedFee, err := estimator.getCachedFee(tc.confTarget)
311331

332+
require.NoError(t, err)
312333
require.Equal(t, tc.expectedFee, cachedFee)
313-
require.ErrorIs(t, err, tc.expectErr)
314334
})
315335
}
316336
}

0 commit comments

Comments
 (0)