lntest: fix timing related flakes

This commit is contained in:
Oliver Gugger committed 2021-08-04 19:42:13 +02:00
1 parent 2eb0a4600f
commit 66ed64da48
4 files changed
+98 -21

No files matched your search

+12 -12
View File
@@ -65,10 +65,7 @@ func testCommitmentTransactionDeadline(net *lntest.NetworkHarness,
// transaction to CPFP our commitment transaction. // transaction to CPFP our commitment transaction.
feeRateLarge := maxPerKw * 2 feeRateLarge := maxPerKw * 2
ctxt, cancel := context.WithTimeout( ctxb := context.Background()
context.Background(), defaultTimeout,
)
defer cancel()
// Before we start, set up the default fee rate and we will test the // Before we start, set up the default fee rate and we will test the
// actual fee rate against it to decide whether we are using the // actual fee rate against it to decide whether we are using the
@@ -76,25 +73,28 @@ func testCommitmentTransactionDeadline(net *lntest.NetworkHarness,
net.SetFeeEstimate(feeRateDefault) net.SetFeeEstimate(feeRateDefault)
// setupNode creates a new node and sends 1 btc to the node. // setupNode creates a new node and sends 1 btc to the node.
setupNode := func(name string) *lntest.HarnessNode { setupNode := func(ctx context.Context, name string) *lntest.HarnessNode {
// Create the node. // Create the node.
args := []string{"--hodl.exit-settle"} args := []string{"--hodl.exit-settle"}
args = append(args, commitTypeAnchors.Args()...) args = append(args, commitTypeAnchors.Args()...)
node := net.NewNode(t.t, name, args) node := net.NewNode(t.t, name, args)
// Send some coins to the node. // Send some coins to the node.
net.SendCoins(ctxt, t.t, btcutil.SatoshiPerBitcoin, node) net.SendCoins(ctx, t.t, btcutil.SatoshiPerBitcoin, node)
return node return node
} }
// calculateSweepFeeRate runs multiple steps to calculate the fee rate // calculateSweepFeeRate runs multiple steps to calculate the fee rate
// used in sweeping the transactions. // used in sweeping the transactions.
calculateSweepFeeRate := func(expectedSweepTxNum int) int64 { calculateSweepFeeRate := func(expectedSweepTxNum int) int64 {
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
// Create two nodes, Alice and Bob. // Create two nodes, Alice and Bob.
alice := setupNode("Alice") alice := setupNode(ctxt, "Alice")
defer shutdownAndAssert(net, t, alice) defer shutdownAndAssert(net, t, alice)
bob := setupNode("Bob") bob := setupNode(ctxt, "Bob")
defer shutdownAndAssert(net, t, bob) defer shutdownAndAssert(net, t, bob)
// Connect Alice to Bob. // Connect Alice to Bob.
@@ -102,8 +102,7 @@ func testCommitmentTransactionDeadline(net *lntest.NetworkHarness,
// Open a channel between Alice and Bob. // Open a channel between Alice and Bob.
chanPoint := openChannelAndAssert( chanPoint := openChannelAndAssert(
ctxt, t, net, alice, bob, ctxt, t, net, alice, bob, lntest.OpenChannelParams{
lntest.OpenChannelParams{
Amt: 10e6, Amt: 10e6,
PushAmt: 5e6, PushAmt: 5e6,
}, },
@@ -113,8 +112,7 @@ func testCommitmentTransactionDeadline(net *lntest.NetworkHarness,
// be used as our deadline later on when Alice force closes the // be used as our deadline later on when Alice force closes the
// channel. // channel.
_, err := alice.RouterClient.SendPaymentV2( _, err := alice.RouterClient.SendPaymentV2(
ctxt, ctxt, &routerrpc.SendPaymentRequest{
&routerrpc.SendPaymentRequest{
Dest: bob.PubKey[:], Dest: bob.PubKey[:],
Amt: 10e4, Amt: 10e4,
PaymentHash: makeFakePayHash(t), PaymentHash: makeFakePayHash(t),
@@ -134,6 +132,8 @@ func testCommitmentTransactionDeadline(net *lntest.NetworkHarness,
require.NoError(t.t, err, "htlc mismatch") require.NoError(t.t, err, "htlc mismatch")
// Alice force closes the channel. // Alice force closes the channel.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
_, _, err = net.CloseChannel(ctxt, alice, chanPoint, true) _, _, err = net.CloseChannel(ctxt, alice, chanPoint, true)
require.NoError(t.t, err, "unable to force close channel") require.NoError(t.t, err, "unable to force close channel")
+19 -8
View File
@@ -25,8 +25,11 @@ func testHoldInvoiceForceClose(net *lntest.NetworkHarness, t *harnessTest) {
Amt: 300000, Amt: 300000,
} }
ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout) ctxt, cancel := context.WithTimeout(ctxb, channelOpenTimeout)
chanPoint := openChannelAndAssert(ctxt, t, net, net.Alice, net.Bob, chanReq) defer cancel()
chanPoint := openChannelAndAssert(
ctxt, t, net, net.Alice, net.Bob, chanReq,
)
// Create a non-dust hold invoice for bob. // Create a non-dust hold invoice for bob.
var ( var (
@@ -39,7 +42,8 @@ func testHoldInvoiceForceClose(net *lntest.NetworkHarness, t *harnessTest) {
Hash: payHash[:], Hash: payHash[:],
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
bobInvoice, err := net.Bob.AddHoldInvoice(ctxt, invoiceReq) bobInvoice, err := net.Bob.AddHoldInvoice(ctxt, invoiceReq)
require.NoError(t.t, err) require.NoError(t.t, err)
@@ -72,23 +76,30 @@ func testHoldInvoiceForceClose(net *lntest.NetworkHarness, t *harnessTest) {
require.Len(t.t, chans.Channels[0].PendingHtlcs, 1) require.Len(t.t, chans.Channels[0].PendingHtlcs, 1)
activeHtlc := chans.Channels[0].PendingHtlcs[0] activeHtlc := chans.Channels[0].PendingHtlcs[0]
require.NoError(t.t, net.Alice.WaitForBlockchainSync(ctxb))
require.NoError(t.t, net.Bob.WaitForBlockchainSync(ctxb))
info, err := net.Alice.GetInfo(ctxb, &lnrpc.GetInfoRequest{}) info, err := net.Alice.GetInfo(ctxb, &lnrpc.GetInfoRequest{})
require.NoError(t.t, err) require.NoError(t.t, err)
// Now we will mine blocks until the htlc expires, and wait for each // Now we will mine blocks until the htlc expires, and wait for each
// node to sync to our latest height. Sanity check that we won't // node to sync to our latest height. Sanity check that we won't
// underflow. // underflow.
require.Greater(t.t, activeHtlc.ExpirationHeight, info.BlockHeight, require.Greater(
"expected expiry after current height") t.t, activeHtlc.ExpirationHeight, info.BlockHeight,
"expected expiry after current height",
)
blocksTillExpiry := activeHtlc.ExpirationHeight - info.BlockHeight blocksTillExpiry := activeHtlc.ExpirationHeight - info.BlockHeight
// Alice will go to chain with some delta, sanity check that we won't // Alice will go to chain with some delta, sanity check that we won't
// underflow and subtract this from our mined blocks. // underflow and subtract this from our mined blocks.
require.Greater(t.t, blocksTillExpiry, require.Greater(
uint32(lncfg.DefaultOutgoingBroadcastDelta)) t.t, blocksTillExpiry,
uint32(lncfg.DefaultOutgoingBroadcastDelta),
)
blocksTillForce := blocksTillExpiry - lncfg.DefaultOutgoingBroadcastDelta blocksTillForce := blocksTillExpiry - lncfg.DefaultOutgoingBroadcastDelta
mineBlocks(t, net, blocksTillForce, 0) mineBlocksSlow(t, net, blocksTillForce, 0)
require.NoError(t.t, net.Alice.WaitForBlockchainSync(ctxb)) require.NoError(t.t, net.Alice.WaitForBlockchainSync(ctxb))
require.NoError(t.t, net.Bob.WaitForBlockchainSync(ctxb)) require.NoError(t.t, net.Bob.WaitForBlockchainSync(ctxb))
+51
View File
@@ -20,6 +20,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
) )
var ( var (
@@ -29,6 +30,8 @@ var (
lndExecutable = flag.String( lndExecutable = flag.String(
"lndexec", itestLndBinary, "full path to lnd binary", "lndexec", itestLndBinary, "full path to lnd binary",
) )
slowMineDelay = 50 * time.Millisecond
) )
const ( const (
@@ -238,6 +241,54 @@ func mineBlocks(t *harnessTest, net *lntest.NetworkHarness,
return blocks return blocks
} }
// mineBlocksSlow mines 'num' of blocks and checks that blocks are present in
// the mining node's blockchain. numTxs should be set to the number of
// transactions (excluding the coinbase) we expect to be included in the first
// mined block. Between each mined block an artificial delay is introduced to
// give all network participants time to catch up.
func mineBlocksSlow(t *harnessTest, net *lntest.NetworkHarness,
num uint32, numTxs int) []*wire.MsgBlock {
t.t.Helper()
// If we expect transactions to be included in the blocks we'll mine,
// we wait here until they are seen in the miner's mempool.
var txids []*chainhash.Hash
var err error
if numTxs > 0 {
txids, err = waitForNTxsInMempool(
net.Miner.Client, numTxs, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find txns in mempool")
}
blocks := make([]*wire.MsgBlock, num)
blockHashes := make([]*chainhash.Hash, 0, num)
for i := uint32(0); i < num; i++ {
generatedHashes, err := net.Miner.Client.Generate(1)
require.NoError(t.t, err, "generate blocks")
blockHashes = append(blockHashes, generatedHashes...)
time.Sleep(slowMineDelay)
}
for i, blockHash := range blockHashes {
block, err := net.Miner.Client.GetBlock(blockHash)
require.NoError(t.t, err, "get blocks")
blocks[i] = block
}
// Finally, assert that all the transactions were included in the first
// block.
for _, txid := range txids {
assertTxInBlock(t, blocks[0], txid)
}
return blocks
}
func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash) { func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash) {
for _, tx := range block.Transactions { for _, tx := range block.Transactions {
sha := tx.TxHash() sha := tx.TxHash()
+16 -1
View File
@@ -12,6 +12,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -1125,7 +1126,21 @@ func (hn *HarnessNode) stop() error {
// closed before a response is returned. // closed before a response is returned.
req := lnrpc.StopRequest{} req := lnrpc.StopRequest{}
ctx := context.Background() ctx := context.Background()
_, err := hn.LightningClient.StopDaemon(ctx, &req)
err := wait.NoError(func() error {
_, err := hn.LightningClient.StopDaemon(ctx, &req)
switch {
case err == nil:
return nil
// Try again if a recovery/rescan is in progress.
case strings.Contains(err.Error(), "recovery in progress"):
return err
default:
return nil
}
}, DefaultTimeout)
if err != nil { if err != nil {
return err return err
} }