mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
d2acb4336c
At times when testing one requires access to the logs of a particular node in order to aide with debugging. Before this commit, one needed to manually modify the networkHarness code in order to print either the location of the logs or the logs themselves. With this commit, tests can now programmatically examine the logs of any node created within the networkHarness. It’s worth noting that at times the logs dumped may not be the most up to date version of the logs files as the logging library employs intermediate buffering.
174 lines
5.4 KiB
Go
174 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"runtime/debug"
|
|
"testing"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
"github.com/roasbeef/btcd/rpctest"
|
|
"github.com/roasbeef/btcd/wire"
|
|
"github.com/roasbeef/btcrpcclient"
|
|
"github.com/roasbeef/btcutil"
|
|
)
|
|
|
|
type lndTestCase func(net *networkHarness, t *testing.T)
|
|
|
|
func assertTxInBlock(block *btcutil.Block, txid *wire.ShaHash, t *testing.T) {
|
|
for _, tx := range block.Transactions() {
|
|
if bytes.Equal(txid[:], tx.Sha()[:]) {
|
|
return
|
|
}
|
|
}
|
|
|
|
t.Fatalf("funding tx was not included in block")
|
|
}
|
|
|
|
// testBasicChannelFunding performs a test excercising expected behavior from a
|
|
// basic funding workflow. The test creates a new channel between Alice and
|
|
// Bob, then immediately closes the channel after asserting some expected post
|
|
// conditions. Finally, the chain itelf is checked to ensure the closing
|
|
// transaction was mined.
|
|
func testBasicChannelFunding(net *networkHarness, t *testing.T) {
|
|
ctxb := context.Background()
|
|
|
|
// First establish a channel ween with a capacity of 0.5 BTC between
|
|
// Alice and Bob.
|
|
chanAmt := btcutil.Amount(btcutil.SatoshiPerBitcoin / 2)
|
|
chanOpenUpdate, err := net.OpenChannel(ctxb, net.Alice, net.Bob, chanAmt, 1)
|
|
if err != nil {
|
|
t.Fatalf("unable to open channel: %v", err)
|
|
}
|
|
|
|
// Mine a block, then wait for Alice's node to notify us that the
|
|
// channel has been opened. The funding transaction should be found
|
|
// within the newly mined block.
|
|
blockHash, err := net.Miner.Node.Generate(1)
|
|
if err != nil {
|
|
t.Fatalf("unable to generate block: %v", err)
|
|
}
|
|
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
|
if err != nil {
|
|
t.Fatalf("unable to get block: %v", err)
|
|
}
|
|
fundingChanPoint, err := net.WaitForChannelOpen(chanOpenUpdate)
|
|
if err != nil {
|
|
t.Fatalf("error while waiting for channeel open: %v", err)
|
|
}
|
|
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
|
if err != nil {
|
|
t.Fatalf("unable to create sha hash: %v", err)
|
|
}
|
|
assertTxInBlock(block, fundingTxID, t)
|
|
|
|
// The channel should be listed in the peer information returned by
|
|
// both peers.
|
|
chanPoint := wire.OutPoint{
|
|
Hash: *fundingTxID,
|
|
Index: fundingChanPoint.OutputIndex,
|
|
}
|
|
err = net.AssertChannelExists(ctxb, net.Alice, &chanPoint)
|
|
if err != nil {
|
|
t.Fatalf("unable to assert channel existence: %v", err)
|
|
}
|
|
|
|
// Initiate a close from Alice's side.
|
|
closeUpdates, err := net.CloseChannel(ctxb, net.Alice, fundingChanPoint, false)
|
|
if err != nil {
|
|
t.Fatalf("unable to clsoe channel: %v", err)
|
|
}
|
|
|
|
// Finally, generate a single block, wait for the final close status
|
|
// update, then ensure that the closing transaction was included in the
|
|
// block.
|
|
blockHash, err = net.Miner.Node.Generate(1)
|
|
if err != nil {
|
|
t.Fatalf("unable to generate block: %v", err)
|
|
}
|
|
block, err = net.Miner.Node.GetBlock(blockHash[0])
|
|
if err != nil {
|
|
t.Fatalf("unable to get block: %v", err)
|
|
}
|
|
|
|
closingTxid, err := net.WaitForChannelClose(closeUpdates)
|
|
if err != nil {
|
|
t.Fatalf("error while waiting for channel close: %v", err)
|
|
}
|
|
assertTxInBlock(block, closingTxid, t)
|
|
}
|
|
|
|
var lndTestCases = map[string]lndTestCase{
|
|
"basic funding flow": testBasicChannelFunding,
|
|
}
|
|
|
|
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
|
// programatically driven network of lnd nodes.
|
|
func TestLightningNetworkDaemon(t *testing.T) {
|
|
var btcdHarness *rpctest.Harness
|
|
var lightningNetwork *networkHarness
|
|
var currentTest string
|
|
var err error
|
|
|
|
defer func() {
|
|
// If one of the integration tests caused a panic within the main
|
|
// goroutine, then tear down all the harnesses in order to avoid
|
|
// any leaked processes.
|
|
if r := recover(); r != nil {
|
|
fmt.Println("recovering from test panic: ", r)
|
|
if err := btcdHarness.TearDown(); err != nil {
|
|
fmt.Println("unable to tear btcd harnesses: ", err)
|
|
}
|
|
if err := lightningNetwork.TearDownAll(); err != nil {
|
|
fmt.Println("unable to tear lnd harnesses: ", err)
|
|
}
|
|
t.Fatalf("test %v panicked: %s", currentTest, debug.Stack())
|
|
}
|
|
}()
|
|
|
|
// First create the network harness to gain access to its
|
|
// 'OnTxAccepted' call back.
|
|
lightningNetwork, err = newNetworkHarness(nil)
|
|
if err != nil {
|
|
t.Fatalf("unable to create lightning network harness: %v", err)
|
|
}
|
|
defer lightningNetwork.TearDownAll()
|
|
|
|
handlers := &btcrpcclient.NotificationHandlers{
|
|
OnTxAccepted: lightningNetwork.OnTxAccepted,
|
|
}
|
|
|
|
// First create an intance of the btcd's rpctest.Harness. This will be
|
|
// used to fund the wallets of the nodes within the test network and to
|
|
// drive blockchain related events within the network.
|
|
btcdHarness, err = rpctest.New(harnessNetParams, handlers, nil)
|
|
if err != nil {
|
|
t.Fatalf("unable to create mining node: %v", err)
|
|
}
|
|
defer btcdHarness.TearDown()
|
|
if err = btcdHarness.SetUp(true, 50); err != nil {
|
|
t.Fatalf("unable to set up mining node: %v", err)
|
|
}
|
|
if err := btcdHarness.Node.NotifyNewTransactions(false); err != nil {
|
|
t.Fatalf("unable to request transaction notifications: %v", err)
|
|
}
|
|
|
|
// With the btcd harness created, we can now complete the
|
|
// initialization of the network.
|
|
if err := lightningNetwork.InitializeSeedNodes(btcdHarness); err != nil {
|
|
t.Fatalf("unable to initialize seed nodes: %v", err)
|
|
}
|
|
if err = lightningNetwork.SetUp(); err != nil {
|
|
t.Fatalf("unable to set up test lightning network: %v", err)
|
|
}
|
|
|
|
t.Logf("Running %v integration tests", len(lndTestCases))
|
|
for testName, lnTest := range lndTestCases {
|
|
t.Logf("Executing test %v", testName)
|
|
|
|
currentTest = testName
|
|
lnTest(lightningNetwork, t)
|
|
}
|
|
}
|