test: rename CT to harnessTest, ensure all RPC's get distinct timeouts
This commit slightly modifies the existing CT struct in order to maintain consistency with code-style. As a result of the name change, all references have also been renamed from `ct` to `t`. The Error and Errorf methods have been removed in favor of forcing everything to be reported via `Fatalf`. Additionally a new method (ProcessErrors) has been introduced to the networkHarness class in order to encapsulate the underlying channel.
This commit is contained in:
parent
5d6b8e49a3
commit
517255fdb1
@ -611,11 +611,14 @@ func (h *htlcSwitch) RegisterLink(p *peer, linkInfo *channeldb.ChannelSnapshot,
|
|||||||
return h.htlcPlex
|
return h.htlcPlex
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregisterLinkMsg is a message which requests the active ink be unregistered.
|
// unregisterLinkMsg is a message which requests the active link be unregistered.
|
||||||
type unregisterLinkMsg struct {
|
type unregisterLinkMsg struct {
|
||||||
chanInterface [32]byte
|
chanInterface [32]byte
|
||||||
chanPoint *wire.OutPoint
|
chanPoint *wire.OutPoint
|
||||||
|
|
||||||
|
// remoteID is the identity public key of the node we're removing the
|
||||||
|
// link between. The public key is expected to be serialized in
|
||||||
|
// compressed form.
|
||||||
// TODO(roasbeef): redo interface map
|
// TODO(roasbeef): redo interface map
|
||||||
remoteID []byte
|
remoteID []byte
|
||||||
|
|
||||||
|
368
lnd_test.go
368
lnd_test.go
@ -3,9 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
@ -13,94 +14,94 @@ import (
|
|||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcrpcclient"
|
"github.com/roasbeef/btcrpcclient"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CT is needed for:
|
// harnessTest wraps a regular testing.T providing enchanced error detection
|
||||||
// - have uniform way of handling panic and fatal error from test cases.
|
// and propagation. Any fatal errors encurred by any running lnd processes will
|
||||||
// - have ability to properly wrap errors in order to see stack trace.
|
// bubble up to the error channel embedded within this struct. Additionally,
|
||||||
// - have nice and elegant way to handle lnd process errors in one
|
// any panics caused by active test cases will also be proxied over the
|
||||||
// select structure with test cases.
|
// errChan. Finally, all error sent through the error channel will be augmented
|
||||||
type CT struct {
|
// with a full stack-trace in order to aide in debugging.
|
||||||
|
type harnessTest struct {
|
||||||
*testing.T
|
*testing.T
|
||||||
|
|
||||||
// Channel for sending retransmitted panic errors and fatal error which
|
// errChan is a channel for sending retransmitted panic errors and
|
||||||
// happens in test case.
|
// fatal errors which occur while running an integration tests.
|
||||||
errChan chan error
|
ErrChan chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCT(t *testing.T) *CT {
|
// newHarnessTest creates a new instance of a harnessTest from a regular
|
||||||
return &CT{t, nil}
|
// testing.T instance.
|
||||||
|
func newHarnessTest(t *testing.T) *harnessTest {
|
||||||
|
return &harnessTest{t, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *CT) Error(err error) {
|
// Fatalf causes the current active test-case to fail with a fatal error. All
|
||||||
if ct.errChan != nil {
|
// integration tests should mark test failures soley with this method due to
|
||||||
ct.errChan <- fmt.Errorf(errors.Wrap(err, 1).ErrorStack())
|
// the error stack traces it produces.
|
||||||
ct.FailNow()
|
func (h *harnessTest) Fatalf(format string, a ...interface{}) {
|
||||||
} else {
|
if h.ErrChan != nil {
|
||||||
ct.Fatal("can't sen error when test isn't running")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf create and send the description about the error in the error channel
|
|
||||||
// and exit.
|
|
||||||
func (ct *CT) Errorf(format string, a ...interface{}) {
|
|
||||||
if ct.errChan != nil {
|
|
||||||
description := fmt.Sprintf(format, a...)
|
description := fmt.Sprintf(format, a...)
|
||||||
ct.errChan <- fmt.Errorf(errors.Wrap(description, 1).ErrorStack())
|
h.ErrChan <- fmt.Errorf(errors.Wrap(description, 1).ErrorStack())
|
||||||
ct.FailNow()
|
|
||||||
} else {
|
h.FailNow()
|
||||||
ct.Fatal("can't sen error when test isn't running")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.Fatal("cannot send an error when a test isn't running")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunTest wraps test case function in goroutine and also redirects the panic
|
// RunTest executes a harness test-case. Any errors or panics will be
|
||||||
// error from test case into error channel.
|
// re-directed to the structs' errChan.
|
||||||
func (ct *CT) RunTest(net *networkHarness, test testCase) chan error {
|
func (h *harnessTest) RunTest(net *networkHarness, test testCase) chan error {
|
||||||
// a channel to signal that test was exited with error
|
h.ErrChan = make(chan error)
|
||||||
ct.errChan = make(chan error)
|
|
||||||
|
|
||||||
|
// Launch a goroutine to execute the acutal test-case. If the test
|
||||||
|
// pases then the error channel returned will be closed. Otherwise, a
|
||||||
|
// non-nil error will be sent over the error channel.
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
// Retransmit test panic into main "process"
|
h.ErrChan <- fmt.Errorf(err.(string))
|
||||||
ct.errChan <- fmt.Errorf(err.(string))
|
|
||||||
}
|
}
|
||||||
close(ct.errChan)
|
|
||||||
ct.errChan = nil
|
close(h.ErrChan)
|
||||||
|
|
||||||
|
h.ErrChan = nil
|
||||||
}()
|
}()
|
||||||
test(net, ct)
|
|
||||||
|
test(net, h)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return ct.errChan
|
return h.ErrChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertTxInBlock(ct *CT, block *btcutil.Block, txid *wire.ShaHash) {
|
func assertTxInBlock(t *harnessTest, block *btcutil.Block, txid *wire.ShaHash) {
|
||||||
for _, tx := range block.Transactions() {
|
for _, tx := range block.Transactions() {
|
||||||
if bytes.Equal(txid[:], tx.Sha()[:]) {
|
if bytes.Equal(txid[:], tx.Sha()[:]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.Errorf("funding tx was not included in block")
|
t.Fatalf("funding tx was not included in block")
|
||||||
}
|
}
|
||||||
|
|
||||||
// mineBlocks mine 'num' of blocks and check that blocks are present in
|
// mineBlocks mine 'num' of blocks and check that blocks are present in
|
||||||
// node blockchain.
|
// node blockchain.
|
||||||
func mineBlocks(ct *CT, net *networkHarness, num uint32) []*btcutil.Block {
|
func mineBlocks(t *harnessTest, net *networkHarness, num uint32) []*btcutil.Block {
|
||||||
blocks := make([]*btcutil.Block, num)
|
blocks := make([]*btcutil.Block, num)
|
||||||
|
|
||||||
blockHashes, err := net.Miner.Node.Generate(num)
|
blockHashes, err := net.Miner.Node.Generate(num)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to generate blocks: %v", err)
|
t.Fatalf("unable to generate blocks: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, blockHash := range blockHashes {
|
for i, blockHash := range blockHashes {
|
||||||
block, err := net.Miner.Node.GetBlock(blockHash)
|
block, err := net.Miner.Node.GetBlock(blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to get block: %v", err)
|
t.Fatalf("unable to get block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks[i] = block
|
blocks[i] = block
|
||||||
@ -109,34 +110,33 @@ func mineBlocks(ct *CT, net *networkHarness, num uint32) []*btcutil.Block {
|
|||||||
return blocks
|
return blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// openChannelAndAssert attempts to open a channel with the specified
|
// openChannelAndAssert attempts to open a channel with the specified
|
||||||
// parameters extended from Alice to Bob. Additionally, two items are asserted
|
// parameters extended from Alice to Bob. Additionally, two items are asserted
|
||||||
// after the channel is considered open: the funding transaction should be
|
// after the channel is considered open: the funding transaction should be
|
||||||
// found within a block, and that Alice can report the status of the new
|
// found within a block, and that Alice can report the status of the new
|
||||||
// channel.
|
// channel.
|
||||||
func openChannelAndAssert(ct *CT, net *networkHarness, ctx context.Context,
|
func openChannelAndAssert(t *harnessTest, net *networkHarness, ctx context.Context,
|
||||||
alice, bob *lightningNode, amount btcutil.Amount) *lnrpc.ChannelPoint {
|
alice, bob *lightningNode, amount btcutil.Amount) *lnrpc.ChannelPoint {
|
||||||
|
|
||||||
chanOpenUpdate, err := net.OpenChannel(ctx, alice, bob, amount, 1)
|
chanOpenUpdate, err := net.OpenChannel(ctx, alice, bob, amount, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to open channel: %v", err)
|
t.Fatalf("unable to open channel: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mine a block, then wait for Alice's node to notify us that the
|
// Mine a block, then wait for Alice's node to notify us that the
|
||||||
// channel has been opened. The funding transaction should be found
|
// channel has been opened. The funding transaction should be found
|
||||||
// within the newly mined block.
|
// within the newly mined block.
|
||||||
block := mineBlocks(ct, net, 1)[0]
|
block := mineBlocks(t, net, 1)[0]
|
||||||
|
|
||||||
fundingChanPoint, err := net.WaitForChannelOpen(ctx, chanOpenUpdate)
|
fundingChanPoint, err := net.WaitForChannelOpen(ctx, chanOpenUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("error while waiting for channel open: %v", err)
|
t.Fatalf("error while waiting for channel open: %v", err)
|
||||||
}
|
}
|
||||||
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create sha hash: %v", err)
|
t.Fatalf("unable to create sha hash: %v", err)
|
||||||
}
|
}
|
||||||
assertTxInBlock(ct, block, fundingTxID)
|
assertTxInBlock(t, block, fundingTxID)
|
||||||
|
|
||||||
// The channel should be listed in the peer information returned by
|
// The channel should be listed in the peer information returned by
|
||||||
// both peers.
|
// both peers.
|
||||||
@ -145,7 +145,7 @@ func openChannelAndAssert(ct *CT, net *networkHarness, ctx context.Context,
|
|||||||
Index: fundingChanPoint.OutputIndex,
|
Index: fundingChanPoint.OutputIndex,
|
||||||
}
|
}
|
||||||
if err := net.AssertChannelExists(ctx, alice, &chanPoint); err != nil {
|
if err := net.AssertChannelExists(ctx, alice, &chanPoint); err != nil {
|
||||||
ct.Errorf("unable to assert channel existence: %v", err)
|
t.Fatalf("unable to assert channel existence: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fundingChanPoint
|
return fundingChanPoint
|
||||||
@ -157,25 +157,25 @@ func openChannelAndAssert(ct *CT, net *networkHarness, ctx context.Context,
|
|||||||
// via timeout from a base parent. Additionally, once the channel has been
|
// via timeout from a base parent. Additionally, once the channel has been
|
||||||
// detected as closed, an assertion checks that the transaction is found within
|
// detected as closed, an assertion checks that the transaction is found within
|
||||||
// a block.
|
// a block.
|
||||||
func closeChannelAndAssert(ct *CT, net *networkHarness, ctx context.Context,
|
func closeChannelAndAssert(t *harnessTest, net *networkHarness, ctx context.Context,
|
||||||
node *lightningNode, fundingChanPoint *lnrpc.ChannelPoint) {
|
node *lightningNode, fundingChanPoint *lnrpc.ChannelPoint) {
|
||||||
|
|
||||||
closeUpdates, err := net.CloseChannel(ctx, node, fundingChanPoint, false)
|
closeUpdates, err := net.CloseChannel(ctx, node, fundingChanPoint, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to close channel: %v", err)
|
t.Fatalf("unable to close channel: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, generate a single block, wait for the final close status
|
// Finally, generate a single block, wait for the final close status
|
||||||
// update, then ensure that the closing transaction was included in the
|
// update, then ensure that the closing transaction was included in the
|
||||||
// block.
|
// block.
|
||||||
block := mineBlocks(ct, net, 1)[0]
|
block := mineBlocks(t, net, 1)[0]
|
||||||
|
|
||||||
closingTxid, err := net.WaitForChannelClose(ctx, closeUpdates)
|
closingTxid, err := net.WaitForChannelClose(ctx, closeUpdates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("error while waiting for channel close: %v", err)
|
t.Fatalf("error while waiting for channel close: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTxInBlock(ct, block, closingTxid)
|
assertTxInBlock(t, block, closingTxid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testBasicChannelFunding performs a test exercising expected behavior from a
|
// testBasicChannelFunding performs a test exercising expected behavior from a
|
||||||
@ -183,7 +183,7 @@ func closeChannelAndAssert(ct *CT, net *networkHarness, ctx context.Context,
|
|||||||
// Bob, then immediately closes the channel after asserting some expected post
|
// Bob, then immediately closes the channel after asserting some expected post
|
||||||
// conditions. Finally, the chain itself is checked to ensure the closing
|
// conditions. Finally, the chain itself is checked to ensure the closing
|
||||||
// transaction was mined.
|
// transaction was mined.
|
||||||
func testBasicChannelFunding(net *networkHarness, ct *CT) {
|
func testBasicChannelFunding(net *networkHarness, t *harnessTest) {
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
|
|
||||||
@ -195,18 +195,18 @@ func testBasicChannelFunding(net *networkHarness, ct *CT) {
|
|||||||
// assertions will be executed to ensure the funding process completed
|
// assertions will be executed to ensure the funding process completed
|
||||||
// successfully.
|
// successfully.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||||
chanPoint := openChannelAndAssert(ct, net, ctxt, net.Alice, net.Bob, chanAmt)
|
chanPoint := openChannelAndAssert(t, net, ctxt, net.Alice, net.Bob, chanAmt)
|
||||||
|
|
||||||
// Finally, immediately close the channel. This function will also
|
// Finally, immediately close the channel. This function will also
|
||||||
// block until the channel is closed and will additionally assert the
|
// block until the channel is closed and will additionally assert the
|
||||||
// relevant channel closing post conditions.
|
// relevant channel closing post conditions.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closeChannelAndAssert(ct, net, ctxt, net.Alice, chanPoint)
|
closeChannelAndAssert(t, net, ctxt, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testChannelBalance creates a new channel between Alice and Bob, then
|
// testChannelBalance creates a new channel between Alice and Bob, then
|
||||||
// checks channel balance to be equal amount specified while creation of channel.
|
// checks channel balance to be equal amount specified while creation of channel.
|
||||||
func testChannelBalance(net *networkHarness, ct *CT) {
|
func testChannelBalance(net *networkHarness, t *harnessTest) {
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
|
|
||||||
// Open a channel with 0.5 BTC between Alice and Bob, ensuring the
|
// Open a channel with 0.5 BTC between Alice and Bob, ensuring the
|
||||||
@ -221,17 +221,17 @@ func testChannelBalance(net *networkHarness, ct *CT) {
|
|||||||
|
|
||||||
response, err := node.ChannelBalance(ctx, &lnrpc.ChannelBalanceRequest{})
|
response, err := node.ChannelBalance(ctx, &lnrpc.ChannelBalanceRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to get channel balance: %v", err)
|
t.Fatalf("unable to get channel balance: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
balance := btcutil.Amount(response.Balance)
|
balance := btcutil.Amount(response.Balance)
|
||||||
if balance != amount {
|
if balance != amount {
|
||||||
ct.Errorf("channel balance wrong: %v != %v", balance,
|
t.Fatalf("channel balance wrong: %v != %v", balance,
|
||||||
amount)
|
amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chanPoint := openChannelAndAssert(ct, net, ctx, net.Alice, net.Bob,
|
chanPoint := openChannelAndAssert(t, net, ctx, net.Alice, net.Bob,
|
||||||
amount)
|
amount)
|
||||||
|
|
||||||
// As this is a single funder channel, Alice's balance should be
|
// As this is a single funder channel, Alice's balance should be
|
||||||
@ -252,7 +252,7 @@ func testChannelBalance(net *networkHarness, ct *CT) {
|
|||||||
// Finally close the channel between Alice and Bob, asserting that the
|
// Finally close the channel between Alice and Bob, asserting that the
|
||||||
// channel has been properly closed on-chain.
|
// channel has been properly closed on-chain.
|
||||||
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
closeChannelAndAssert(ct, net, ctx, net.Alice, chanPoint)
|
closeChannelAndAssert(t, net, ctx, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testChannelForceClosure performs a test to exercise the behavior of "force"
|
// testChannelForceClosure performs a test to exercise the behavior of "force"
|
||||||
@ -264,7 +264,7 @@ func testChannelBalance(net *networkHarness, ct *CT) {
|
|||||||
// once the output(s) become mature.
|
// once the output(s) become mature.
|
||||||
//
|
//
|
||||||
// TODO(roabeef): also add an unsettled HTLC before force closing.
|
// TODO(roabeef): also add an unsettled HTLC before force closing.
|
||||||
func testChannelForceClosure(net *networkHarness, ct *CT) {
|
func testChannelForceClosure(net *networkHarness, t *harnessTest) {
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
|
|
||||||
@ -275,17 +275,17 @@ func testChannelForceClosure(net *networkHarness, ct *CT) {
|
|||||||
chanOpenUpdate, err := net.OpenChannel(ctxb, net.Alice, net.Bob,
|
chanOpenUpdate, err := net.OpenChannel(ctxb, net.Alice, net.Bob,
|
||||||
chanAmt, numFundingConfs)
|
chanAmt, numFundingConfs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to open channel: %v", err)
|
t.Fatalf("unable to open channel: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := net.Miner.Node.Generate(numFundingConfs); err != nil {
|
if _, err := net.Miner.Node.Generate(numFundingConfs); err != nil {
|
||||||
ct.Errorf("unable to mine block: %v", err)
|
t.Fatalf("unable to mine block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||||
chanPoint, err := net.WaitForChannelOpen(ctxt, chanOpenUpdate)
|
chanPoint, err := net.WaitForChannelOpen(ctxt, chanOpenUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("error while waiting for channel to open: %v", err)
|
t.Fatalf("error while waiting for channel to open: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the channel is open, immediately execute a force closure of
|
// Now that the channel is open, immediately execute a force closure of
|
||||||
@ -294,18 +294,18 @@ func testChannelForceClosure(net *networkHarness, ct *CT) {
|
|||||||
// request.
|
// request.
|
||||||
closeUpdate, err := net.CloseChannel(ctxb, net.Alice, chanPoint, true)
|
closeUpdate, err := net.CloseChannel(ctxb, net.Alice, chanPoint, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to execute force channel closure: %v", err)
|
t.Fatalf("unable to execute force channel closure: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mine a block which should confirm the commitment transaction
|
// Mine a block which should confirm the commitment transaction
|
||||||
// broadcast as a result of the force closure.
|
// broadcast as a result of the force closure.
|
||||||
if _, err := net.Miner.Node.Generate(1); err != nil {
|
if _, err := net.Miner.Node.Generate(1); err != nil {
|
||||||
ct.Errorf("unable to generate block: %v", err)
|
t.Fatalf("unable to generate block: %v", err)
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closingTxID, err := net.WaitForChannelClose(ctxt, closeUpdate)
|
closingTxID, err := net.WaitForChannelClose(ctxt, closeUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("error while waiting for channel close: %v", err)
|
t.Fatalf("error while waiting for channel close: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently within the codebase, the default CSV is 4 relative blocks.
|
// Currently within the codebase, the default CSV is 4 relative blocks.
|
||||||
@ -314,7 +314,7 @@ func testChannelForceClosure(net *networkHarness, ct *CT) {
|
|||||||
// or make delay a param
|
// or make delay a param
|
||||||
const defaultCSV = 4
|
const defaultCSV = 4
|
||||||
if _, err := net.Miner.Node.Generate(defaultCSV); err != nil {
|
if _, err := net.Miner.Node.Generate(defaultCSV); err != nil {
|
||||||
ct.Errorf("unable to mine blocks: %v", err)
|
t.Fatalf("unable to mine blocks: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, the sweeping transaction should now be broadcast. So
|
// At this point, the sweeping transaction should now be broadcast. So
|
||||||
@ -326,11 +326,11 @@ mempoolPoll:
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Second * 5):
|
case <-time.After(time.Second * 5):
|
||||||
ct.Errorf("sweep tx not found in mempool")
|
t.Fatalf("sweep tx not found in mempool")
|
||||||
default:
|
default:
|
||||||
mempool, err = net.Miner.Node.GetRawMempool()
|
mempool, err = net.Miner.Node.GetRawMempool()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to fetch node's mempool: %v", err)
|
t.Fatalf("unable to fetch node's mempool: %v", err)
|
||||||
}
|
}
|
||||||
if len(mempool) == 0 {
|
if len(mempool) == 0 {
|
||||||
continue
|
continue
|
||||||
@ -344,7 +344,7 @@ mempoolPoll:
|
|||||||
// TODO(roasbeef): assertion may not necessarily hold with concurrent
|
// TODO(roasbeef): assertion may not necessarily hold with concurrent
|
||||||
// test executions
|
// test executions
|
||||||
if len(mempool) != 1 {
|
if len(mempool) != 1 {
|
||||||
ct.Errorf("node's mempool is wrong size, expected 1 got %v",
|
t.Fatalf("node's mempool is wrong size, expected 1 got %v",
|
||||||
len(mempool))
|
len(mempool))
|
||||||
}
|
}
|
||||||
sweepingTXID = mempool[0]
|
sweepingTXID = mempool[0]
|
||||||
@ -353,11 +353,11 @@ mempoolPoll:
|
|||||||
// the commitment transaction which was broadcast on-chain.
|
// the commitment transaction which was broadcast on-chain.
|
||||||
sweepTx, err := net.Miner.Node.GetRawTransaction(sweepingTXID)
|
sweepTx, err := net.Miner.Node.GetRawTransaction(sweepingTXID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to fetch sweep tx: %v", err)
|
t.Fatalf("unable to fetch sweep tx: %v", err)
|
||||||
}
|
}
|
||||||
for _, txIn := range sweepTx.MsgTx().TxIn {
|
for _, txIn := range sweepTx.MsgTx().TxIn {
|
||||||
if !closingTxID.IsEqual(&txIn.PreviousOutPoint.Hash) {
|
if !closingTxID.IsEqual(&txIn.PreviousOutPoint.Hash) {
|
||||||
ct.Errorf("sweep transaction not spending from commit "+
|
t.Fatalf("sweep transaction not spending from commit "+
|
||||||
"tx %v, instead spending %v",
|
"tx %v, instead spending %v",
|
||||||
closingTxID, txIn.PreviousOutPoint)
|
closingTxID, txIn.PreviousOutPoint)
|
||||||
}
|
}
|
||||||
@ -368,17 +368,17 @@ mempoolPoll:
|
|||||||
// inputs should be properly met.
|
// inputs should be properly met.
|
||||||
blockHash, err := net.Miner.Node.Generate(1)
|
blockHash, err := net.Miner.Node.Generate(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to generate block: %v", err)
|
t.Fatalf("unable to generate block: %v", err)
|
||||||
}
|
}
|
||||||
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to get block: %v", err)
|
t.Fatalf("unable to get block: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTxInBlock(ct, block, sweepTx.Sha())
|
assertTxInBlock(t, block, sweepTx.Sha())
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSingleHopInvoice(net *networkHarness, ct *CT) {
|
func testSingleHopInvoice(net *networkHarness, t *harnessTest) {
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
|
|
||||||
@ -386,7 +386,7 @@ func testSingleHopInvoice(net *networkHarness, ct *CT) {
|
|||||||
// the sole funder of the channel.
|
// the sole funder of the channel.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
chanPoint := openChannelAndAssert(ct, net, ctxt, net.Alice, net.Bob, chanAmt)
|
chanPoint := openChannelAndAssert(t, net, ctxt, net.Alice, net.Bob, chanAmt)
|
||||||
|
|
||||||
// Now that the channel is open, create an invoice for Bob which
|
// Now that the channel is open, create an invoice for Bob which
|
||||||
// expects a payment of 1000 satoshis from Alice paid via a particular
|
// expects a payment of 1000 satoshis from Alice paid via a particular
|
||||||
@ -400,14 +400,14 @@ func testSingleHopInvoice(net *networkHarness, ct *CT) {
|
|||||||
}
|
}
|
||||||
invoiceResp, err := net.Bob.AddInvoice(ctxb, invoice)
|
invoiceResp, err := net.Bob.AddInvoice(ctxb, invoice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to add invoice: %v", err)
|
t.Fatalf("unable to add invoice: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the invoice for Bob added, send a payment towards Alice paying
|
// With the invoice for Bob added, send a payment towards Alice paying
|
||||||
// to the above generated invoice.
|
// to the above generated invoice.
|
||||||
sendStream, err := net.Alice.SendPayment(ctxb)
|
sendStream, err := net.Alice.SendPayment(ctxb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create alice payment stream: %v", err)
|
t.Fatalf("unable to create alice payment stream: %v", err)
|
||||||
}
|
}
|
||||||
sendReq := &lnrpc.SendRequest{
|
sendReq := &lnrpc.SendRequest{
|
||||||
PaymentHash: invoiceResp.RHash,
|
PaymentHash: invoiceResp.RHash,
|
||||||
@ -415,10 +415,10 @@ func testSingleHopInvoice(net *networkHarness, ct *CT) {
|
|||||||
Amt: paymentAmt,
|
Amt: paymentAmt,
|
||||||
}
|
}
|
||||||
if err := sendStream.Send(sendReq); err != nil {
|
if err := sendStream.Send(sendReq); err != nil {
|
||||||
ct.Errorf("unable to send payment: %v", err)
|
t.Fatalf("unable to send payment: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := sendStream.Recv(); err != nil {
|
if _, err := sendStream.Recv(); err != nil {
|
||||||
ct.Errorf("error when attempting recv: %v", err)
|
t.Fatalf("error when attempting recv: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bob's invoice should now be found and marked as settled.
|
// Bob's invoice should now be found and marked as settled.
|
||||||
@ -429,38 +429,37 @@ func testSingleHopInvoice(net *networkHarness, ct *CT) {
|
|||||||
}
|
}
|
||||||
dbInvoice, err := net.Bob.LookupInvoice(ctxb, payHash)
|
dbInvoice, err := net.Bob.LookupInvoice(ctxb, payHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to lookup invoice: %v", err)
|
t.Fatalf("unable to lookup invoice: %v", err)
|
||||||
}
|
}
|
||||||
if !dbInvoice.Settled {
|
if !dbInvoice.Settled {
|
||||||
ct.Errorf("bob's invoice should be marked as settled: %v",
|
t.Fatalf("bob's invoice should be marked as settled: %v",
|
||||||
spew.Sdump(dbInvoice))
|
spew.Sdump(dbInvoice))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The balances of Alice and Bob should be updated accordingly.
|
// The balances of Alice and Bob should be updated accordingly.
|
||||||
aliceBalance, err := net.Alice.ChannelBalance(ctxb, &lnrpc.ChannelBalanceRequest{})
|
aliceBalance, err := net.Alice.ChannelBalance(ctxb, &lnrpc.ChannelBalanceRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to query for alice's balance: %v", err)
|
t.Fatalf("unable to query for alice's balance: %v", err)
|
||||||
}
|
}
|
||||||
bobBalance, err := net.Bob.ChannelBalance(ctxb, &lnrpc.ChannelBalanceRequest{})
|
bobBalance, err := net.Bob.ChannelBalance(ctxb, &lnrpc.ChannelBalanceRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to query for bob's balance: %v", err)
|
t.Fatalf("unable to query for bob's balance: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if aliceBalance.Balance != int64(chanAmt-paymentAmt) {
|
if aliceBalance.Balance != int64(chanAmt-paymentAmt) {
|
||||||
ct.Errorf("Alice's balance is incorrect got %v, expected %v",
|
t.Fatalf("Alice's balance is incorrect got %v, expected %v",
|
||||||
aliceBalance, int64(chanAmt-paymentAmt))
|
aliceBalance, int64(chanAmt-paymentAmt))
|
||||||
}
|
}
|
||||||
if bobBalance.Balance != paymentAmt {
|
if bobBalance.Balance != paymentAmt {
|
||||||
ct.Errorf("Bob's balance is incorrect got %v, expected %v",
|
t.Fatalf("Bob's balance is incorrect got %v, expected %v",
|
||||||
bobBalance, paymentAmt)
|
bobBalance, paymentAmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closeChannelAndAssert(ct, net, ctxt, net.Alice, chanPoint)
|
closeChannelAndAssert(t, net, ctxt, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMultiHopPayments(net *networkHarness, ct *CT) {
|
func testMultiHopPayments(net *networkHarness, t *harnessTest) {
|
||||||
|
|
||||||
const chanAmt = btcutil.Amount(100000)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
@ -468,12 +467,12 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||||
chanPointAlice := openChannelAndAssert(ct, net, ctxt, net.Alice,
|
chanPointAlice := openChannelAndAssert(t, net, ctxt, net.Alice,
|
||||||
net.Bob, chanAmt)
|
net.Bob, chanAmt)
|
||||||
|
|
||||||
aliceChanTXID, err := wire.NewShaHash(chanPointAlice.FundingTxid)
|
aliceChanTXID, err := wire.NewShaHash(chanPointAlice.FundingTxid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create sha hash: %v", err)
|
t.Fatalf("unable to create sha hash: %v", err)
|
||||||
}
|
}
|
||||||
aliceFundPoint := wire.OutPoint{
|
aliceFundPoint := wire.OutPoint{
|
||||||
Hash: *aliceChanTXID,
|
Hash: *aliceChanTXID,
|
||||||
@ -487,22 +486,22 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
// The network topology should now look like: Carol -> Alice -> Bob
|
// The network topology should now look like: Carol -> Alice -> Bob
|
||||||
carol, err := net.NewNode(nil)
|
carol, err := net.NewNode(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create new nodes: %v", err)
|
t.Fatalf("unable to create new nodes: %v", err)
|
||||||
}
|
}
|
||||||
if err := net.ConnectNodes(ctxb, carol, net.Alice); err != nil {
|
if err := net.ConnectNodes(ctxb, carol, net.Alice); err != nil {
|
||||||
ct.Errorf("unable to connect carol to alice: %v", err)
|
t.Fatalf("unable to connect carol to alice: %v", err)
|
||||||
}
|
}
|
||||||
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, carol)
|
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, carol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to send coins to carol: %v", err)
|
t.Fatalf("unable to send coins to carol: %v", err)
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
chanPointCarol := openChannelAndAssert(ct, net, ctxt, carol,
|
chanPointCarol := openChannelAndAssert(t, net, ctxt, carol,
|
||||||
net.Alice, chanAmt)
|
net.Alice, chanAmt)
|
||||||
|
|
||||||
carolChanTXID, err := wire.NewShaHash(chanPointCarol.FundingTxid)
|
carolChanTXID, err := wire.NewShaHash(chanPointCarol.FundingTxid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create sha hash: %v", err)
|
t.Fatalf("unable to create sha hash: %v", err)
|
||||||
}
|
}
|
||||||
carolFundPoint := wire.OutPoint{
|
carolFundPoint := wire.OutPoint{
|
||||||
Hash: *carolChanTXID,
|
Hash: *carolChanTXID,
|
||||||
@ -523,7 +522,7 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
}
|
}
|
||||||
resp, err := net.Bob.AddInvoice(ctxb, invoice)
|
resp, err := net.Bob.AddInvoice(ctxb, invoice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to add invoice: %v", err)
|
t.Fatalf("unable to add invoice: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rHashes[i] = resp.RHash
|
rHashes[i] = resp.RHash
|
||||||
@ -536,10 +535,10 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
req := &lnrpc.ShowRoutingTableRequest{}
|
req := &lnrpc.ShowRoutingTableRequest{}
|
||||||
routingResp, err := carol.ShowRoutingTable(ctxb, req)
|
routingResp, err := carol.ShowRoutingTable(ctxb, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to query for carol's routing table: %v", err)
|
t.Fatalf("unable to query for carol's routing table: %v", err)
|
||||||
}
|
}
|
||||||
if len(routingResp.Channels) != 2 {
|
if len(routingResp.Channels) != 2 {
|
||||||
ct.Errorf("only two channels should be seen as active in the "+
|
t.Fatalf("only two channels should be seen as active in the "+
|
||||||
"network, instead %v are", len(routingResp.Channels))
|
"network, instead %v are", len(routingResp.Channels))
|
||||||
}
|
}
|
||||||
for _, link := range routingResp.Channels {
|
for _, link := range routingResp.Channels {
|
||||||
@ -553,7 +552,7 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
link.Id2 == net.Alice.PubKeyStr:
|
link.Id2 == net.Alice.PubKeyStr:
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
ct.Errorf("unkown link within routing "+
|
t.Fatalf("unkown link within routing "+
|
||||||
"table: %v", spew.Sdump(link))
|
"table: %v", spew.Sdump(link))
|
||||||
}
|
}
|
||||||
case link.Outpoint == carolFundPoint.String():
|
case link.Outpoint == carolFundPoint.String():
|
||||||
@ -565,11 +564,11 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
link.Id2 == net.Alice.PubKeyStr:
|
link.Id2 == net.Alice.PubKeyStr:
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
ct.Errorf("unkown link within routing "+
|
t.Fatalf("unkown link within routing "+
|
||||||
"table: %v", spew.Sdump(link))
|
"table: %v", spew.Sdump(link))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ct.Errorf("unkown channel %v found in routing table, "+
|
t.Fatalf("unkown channel %v found in routing table, "+
|
||||||
"only %v and %v should exist", link.Outpoint,
|
"only %v and %v should exist", link.Outpoint,
|
||||||
aliceFundPoint, carolFundPoint)
|
aliceFundPoint, carolFundPoint)
|
||||||
}
|
}
|
||||||
@ -578,7 +577,7 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
// Using Carol as the source, pay to the 5 invoices from Bob created above.
|
// Using Carol as the source, pay to the 5 invoices from Bob created above.
|
||||||
carolPayStream, err := carol.SendPayment(ctxb)
|
carolPayStream, err := carol.SendPayment(ctxb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create payment stream for carol: %v", err)
|
t.Fatalf("unable to create payment stream for carol: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concurrently pay off all 5 of Bob's invoices. Each of the goroutines
|
// Concurrently pay off all 5 of Bob's invoices. Each of the goroutines
|
||||||
@ -595,10 +594,10 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
if err := carolPayStream.Send(sendReq); err != nil {
|
if err := carolPayStream.Send(sendReq); err != nil {
|
||||||
ct.Errorf("unable to send payment: %v", err)
|
t.Fatalf("unable to send payment: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := carolPayStream.Recv(); err != nil {
|
if _, err := carolPayStream.Recv(); err != nil {
|
||||||
ct.Errorf("unable to recv pay resp: %v", err)
|
t.Fatalf("unable to recv pay resp: %v", err)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
@ -612,7 +611,7 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Second * 10):
|
case <-time.After(time.Second * 10):
|
||||||
ct.Errorf("HLTC's not cleared after 10 seconds")
|
t.Fatalf("HTLC's not cleared after 10 seconds")
|
||||||
case <-finClear:
|
case <-finClear:
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +622,7 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
listReq := &lnrpc.ListChannelsRequest{}
|
listReq := &lnrpc.ListChannelsRequest{}
|
||||||
resp, err := node.ListChannels(ctxb, listReq)
|
resp, err := node.ListChannels(ctxb, listReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to for node's channels: %v", err)
|
t.Fatalf("unable to for node's channels: %v", err)
|
||||||
}
|
}
|
||||||
for _, channel := range resp.Channels {
|
for _, channel := range resp.Channels {
|
||||||
if channel.ChannelPoint != chanPoint.String() {
|
if channel.ChannelPoint != chanPoint.String() {
|
||||||
@ -632,12 +631,12 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
|
|
||||||
if channel.LocalBalance != localBalance ||
|
if channel.LocalBalance != localBalance ||
|
||||||
channel.RemoteBalance != remoteBalance {
|
channel.RemoteBalance != remoteBalance {
|
||||||
ct.Errorf("incorrect balances: %v",
|
t.Fatalf("incorrect balances: %v",
|
||||||
spew.Sdump(channel))
|
spew.Sdump(channel))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ct.Errorf("channel not found")
|
t.Fatalf("channel not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point all the channels within our proto network should be
|
// At this point all the channels within our proto network should be
|
||||||
@ -654,12 +653,12 @@ func testMultiHopPayments(net *networkHarness, ct *CT) {
|
|||||||
assertAsymmetricBalance(net.Bob, &aliceFundPoint, sinkBal, sourceBal)
|
assertAsymmetricBalance(net.Bob, &aliceFundPoint, sinkBal, sourceBal)
|
||||||
|
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closeChannelAndAssert(ct, net, ctxt, net.Alice, chanPointAlice)
|
closeChannelAndAssert(t, net, ctxt, net.Alice, chanPointAlice)
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closeChannelAndAssert(ct, net, ctxt, carol, chanPointCarol)
|
closeChannelAndAssert(t, net, ctxt, carol, chanPointCarol)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
func testInvoiceSubscriptions(net *networkHarness, t *harnessTest) {
|
||||||
const chanAmt = btcutil.Amount(500000)
|
const chanAmt = btcutil.Amount(500000)
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
timeout := time.Duration(time.Second * 5)
|
timeout := time.Duration(time.Second * 5)
|
||||||
@ -667,7 +666,7 @@ func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
|||||||
// Open a channel with 500k satoshis between Alice and Bob with Alice
|
// Open a channel with 500k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||||
chanPoint := openChannelAndAssert(ct, net, ctxt, net.Alice, net.Bob,
|
chanPoint := openChannelAndAssert(t, net, ctxt, net.Alice, net.Bob,
|
||||||
chanAmt)
|
chanAmt)
|
||||||
|
|
||||||
// Next create a new invoice for Bob requesting 1k satoshis.
|
// Next create a new invoice for Bob requesting 1k satoshis.
|
||||||
@ -680,7 +679,7 @@ func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
|||||||
}
|
}
|
||||||
invoiceResp, err := net.Bob.AddInvoice(ctxb, invoice)
|
invoiceResp, err := net.Bob.AddInvoice(ctxb, invoice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to add invoice: %v", err)
|
t.Fatalf("unable to add invoice: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new invoice subscription client for Bob, the notification
|
// Create a new invoice subscription client for Bob, the notification
|
||||||
@ -688,23 +687,23 @@ func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
|||||||
req := &lnrpc.InvoiceSubscription{}
|
req := &lnrpc.InvoiceSubscription{}
|
||||||
bobInvoiceSubscription, err := net.Bob.SubscribeInvoices(ctxb, req)
|
bobInvoiceSubscription, err := net.Bob.SubscribeInvoices(ctxb, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to subscribe to bob's invoice updates: %v", err)
|
t.Fatalf("unable to subscribe to bob's invoice updates: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSent := make(chan struct{})
|
updateSent := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
invoiceUpdate, err := bobInvoiceSubscription.Recv()
|
invoiceUpdate, err := bobInvoiceSubscription.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to recv invoice update: %v", err)
|
t.Fatalf("unable to recv invoice update: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The invoice update should exactly match the invoice created
|
// The invoice update should exactly match the invoice created
|
||||||
// above, but should now be settled.
|
// above, but should now be settled.
|
||||||
if !invoiceUpdate.Settled {
|
if !invoiceUpdate.Settled {
|
||||||
ct.Errorf("invoice not settled but shoudl be")
|
t.Fatalf("invoice not settled but shoudl be")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(invoiceUpdate.RPreimage, invoice.RPreimage) {
|
if !bytes.Equal(invoiceUpdate.RPreimage, invoice.RPreimage) {
|
||||||
ct.Errorf("payment preimages don't match: expected %v, got %v",
|
t.Fatalf("payment preimages don't match: expected %v, got %v",
|
||||||
invoice.RPreimage, invoiceUpdate.RPreimage)
|
invoice.RPreimage, invoiceUpdate.RPreimage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,7 +714,7 @@ func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
|||||||
// which should finalize and settle the invoice.
|
// which should finalize and settle the invoice.
|
||||||
sendStream, err := net.Alice.SendPayment(ctxb)
|
sendStream, err := net.Alice.SendPayment(ctxb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create alice payment stream: %v", err)
|
t.Fatalf("unable to create alice payment stream: %v", err)
|
||||||
}
|
}
|
||||||
sendReq := &lnrpc.SendRequest{
|
sendReq := &lnrpc.SendRequest{
|
||||||
PaymentHash: invoiceResp.RHash,
|
PaymentHash: invoiceResp.RHash,
|
||||||
@ -723,50 +722,51 @@ func testInvoiceSubscriptions(net *networkHarness, ct *CT) {
|
|||||||
Amt: paymentAmt,
|
Amt: paymentAmt,
|
||||||
}
|
}
|
||||||
if err := sendStream.Send(sendReq); err != nil {
|
if err := sendStream.Send(sendReq); err != nil {
|
||||||
ct.Errorf("unable to send payment: %v", err)
|
t.Fatalf("unable to send payment: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := sendStream.Recv(); err != nil {
|
if _, err := sendStream.Recv(); err != nil {
|
||||||
ct.Errorf("error when attempting recv: %v", err)
|
t.Fatalf("error when attempting recv: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Second * 5):
|
case <-time.After(time.Second * 5):
|
||||||
ct.Errorf("update not sent after 5 seconds")
|
t.Fatalf("update not sent after 5 seconds")
|
||||||
case <-updateSent: // Fall through on success
|
case <-updateSent: // Fall through on success
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||||
closeChannelAndAssert(ct, net, ctxt, net.Alice, chanPoint)
|
closeChannelAndAssert(t, net, ctxt, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testBasicChannelCreation test multiple channel opening and closing.
|
// testBasicChannelCreation test multiple channel opening and closing.
|
||||||
func testBasicChannelCreation(net *networkHarness, ct *CT) {
|
func testBasicChannelCreation(net *networkHarness, t *harnessTest) {
|
||||||
timeout := time.Duration(time.Second * 5)
|
const (
|
||||||
ctx, _ := context.WithTimeout(context.Background(), timeout)
|
numChannels = 2
|
||||||
|
timeout = time.Duration(time.Second * 5)
|
||||||
amount := btcutil.Amount(btcutil.SatoshiPerBitcoin)
|
amount = btcutil.Amount(btcutil.SatoshiPerBitcoin)
|
||||||
|
)
|
||||||
num := 2
|
|
||||||
|
|
||||||
// Open the channel between Alice and Bob, asserting that the
|
// Open the channel between Alice and Bob, asserting that the
|
||||||
// channel has been properly open on-chain.
|
// channel has been properly open on-chain.
|
||||||
chanPoints := make([]*lnrpc.ChannelPoint, num)
|
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < numChannels; i++ {
|
||||||
chanPoints[i] = openChannelAndAssert(ct, net, ctx, net.Alice,
|
ctx, _ := context.WithTimeout(context.Background(), timeout)
|
||||||
|
chanPoints[i] = openChannelAndAssert(t, net, ctx, net.Alice,
|
||||||
net.Bob, amount)
|
net.Bob, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the channel between Alice and Bob, asserting that the
|
// Close the channel between Alice and Bob, asserting that the
|
||||||
// channel has been properly closed on-chain.
|
// channel has been properly closed on-chain.
|
||||||
for _, chanPoint := range chanPoints {
|
for _, chanPoint := range chanPoints {
|
||||||
closeChannelAndAssert(ct, net, ctx, net.Alice, chanPoint)
|
ctx, _ := context.WithTimeout(context.Background(), timeout)
|
||||||
|
closeChannelAndAssert(t, net, ctx, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// testMaxPendingChannels checks that error is returned from remote peer if
|
// testMaxPendingChannels checks that error is returned from remote peer if
|
||||||
// max pending channel number was exceeded and that '--maxpendingchannels' flag
|
// max pending channel number was exceeded and that '--maxpendingchannels' flag
|
||||||
// exists and works properly.
|
// exists and works properly.
|
||||||
func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
func testMaxPendingChannels(net *networkHarness, t *harnessTest) {
|
||||||
maxPendingChannels := defaultMaxPendingChannels + 1
|
maxPendingChannels := defaultMaxPendingChannels + 1
|
||||||
amount := btcutil.Amount(btcutil.SatoshiPerBitcoin)
|
amount := btcutil.Amount(btcutil.SatoshiPerBitcoin)
|
||||||
|
|
||||||
@ -778,19 +778,20 @@ func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
|||||||
args := []string{
|
args := []string{
|
||||||
fmt.Sprintf("--maxpendingchannels=%v", maxPendingChannels),
|
fmt.Sprintf("--maxpendingchannels=%v", maxPendingChannels),
|
||||||
}
|
}
|
||||||
|
|
||||||
carol, err := net.NewNode(args)
|
carol, err := net.NewNode(args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create new nodes: %v", err)
|
t.Fatalf("unable to create new nodes: %v", err)
|
||||||
}
|
|
||||||
if err := net.ConnectNodes(ctx, net.Alice, carol); err != nil {
|
|
||||||
ct.Errorf("unable to connect carol to alice: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
|
if err := net.ConnectNodes(ctx, net.Alice, carol); err != nil {
|
||||||
|
t.Fatalf("unable to connect carol to alice: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
carolBalance := btcutil.Amount(maxPendingChannels) * amount
|
carolBalance := btcutil.Amount(maxPendingChannels) * amount
|
||||||
if err := net.SendCoins(ctx, carolBalance, carol); err != nil {
|
if err := net.SendCoins(ctx, carolBalance, carol); err != nil {
|
||||||
ct.Errorf("unable to send coins to carol: %v", err)
|
t.Fatalf("unable to send coins to carol: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send open channel requests without generating new blocks thereby
|
// Send open channel requests without generating new blocks thereby
|
||||||
@ -799,20 +800,22 @@ func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
|||||||
// max value.
|
// max value.
|
||||||
openStreams := make([]lnrpc.Lightning_OpenChannelClient, maxPendingChannels)
|
openStreams := make([]lnrpc.Lightning_OpenChannelClient, maxPendingChannels)
|
||||||
for i := 0; i < maxPendingChannels; i++ {
|
for i := 0; i < maxPendingChannels; i++ {
|
||||||
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
stream, err := net.OpenChannel(ctx, net.Alice, carol, amount, 1)
|
stream, err := net.OpenChannel(ctx, net.Alice, carol, amount, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to open channel: %v", err)
|
t.Fatalf("unable to open channel: %v", err)
|
||||||
}
|
}
|
||||||
openStreams[i] = stream
|
openStreams[i] = stream
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carol exhausted available amount of pending channels, next open
|
// Carol exhausted available amount of pending channels, next open
|
||||||
// channel request should cause ErrorGeneric to be sent back to Alice.
|
// channel request should cause ErrorGeneric to be sent back to Alice.
|
||||||
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
_, err = net.OpenChannel(ctx, net.Alice, carol, amount, 1)
|
_, err = net.OpenChannel(ctx, net.Alice, carol, amount, 1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ct.Errorf("error wasn't received")
|
t.Fatalf("error wasn't received")
|
||||||
} else if grpc.Code(err) != OpenChannelFundingError {
|
} else if grpc.Code(err) != OpenChannelFundingError {
|
||||||
ct.Errorf("not expected error was received : %v", err)
|
t.Fatalf("not expected error was received : %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now our channels are in pending state, in order to not
|
// For now our channels are in pending state, in order to not
|
||||||
@ -822,22 +825,22 @@ func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
|||||||
// Mine a block, then wait for node's to notify us that the channel
|
// Mine a block, then wait for node's to notify us that the channel
|
||||||
// has been opened. The funding transactions should be found within the
|
// has been opened. The funding transactions should be found within the
|
||||||
// newly mined block.
|
// newly mined block.
|
||||||
block := mineBlocks(ct, net, 1)[0]
|
block := mineBlocks(t, net, 1)[0]
|
||||||
|
|
||||||
chanPoints := make([]*lnrpc.ChannelPoint, maxPendingChannels)
|
chanPoints := make([]*lnrpc.ChannelPoint, maxPendingChannels)
|
||||||
|
|
||||||
for i, stream := range openStreams {
|
for i, stream := range openStreams {
|
||||||
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
fundingChanPoint, err := net.WaitForChannelOpen(ctx, stream)
|
fundingChanPoint, err := net.WaitForChannelOpen(ctx, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("error while waiting for channel open: %v", err)
|
t.Fatalf("error while waiting for channel open: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Errorf("unable to create sha hash: %v", err)
|
t.Fatalf("unable to create sha hash: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTxInBlock(ct, block, fundingTxID)
|
assertTxInBlock(t, block, fundingTxID)
|
||||||
|
|
||||||
// The channel should be listed in the peer information
|
// The channel should be listed in the peer information
|
||||||
// returned by both peers.
|
// returned by both peers.
|
||||||
@ -846,7 +849,7 @@ func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
|||||||
Index: fundingChanPoint.OutputIndex,
|
Index: fundingChanPoint.OutputIndex,
|
||||||
}
|
}
|
||||||
if err := net.AssertChannelExists(ctx, net.Alice, &chanPoint); err != nil {
|
if err := net.AssertChannelExists(ctx, net.Alice, &chanPoint); err != nil {
|
||||||
ct.Errorf("unable to assert channel existence: %v", err)
|
t.Fatalf("unable to assert channel existence: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chanPoints[i] = fundingChanPoint
|
chanPoints[i] = fundingChanPoint
|
||||||
@ -855,12 +858,12 @@ func testMaxPendingChannels(net *networkHarness, ct *CT) {
|
|||||||
// Finally close the channel between Alice and Carol, asserting that the
|
// Finally close the channel between Alice and Carol, asserting that the
|
||||||
// channel has been properly closed on-chain.
|
// channel has been properly closed on-chain.
|
||||||
for _, chanPoint := range chanPoints {
|
for _, chanPoint := range chanPoints {
|
||||||
closeChannelAndAssert(ct, net, ctx, net.Alice, chanPoint)
|
ctx, _ = context.WithTimeout(context.Background(), timeout)
|
||||||
|
closeChannelAndAssert(t, net, ctx, net.Alice, chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCase func(net *networkHarness, ct *CT)
|
type testCase func(net *networkHarness, t *harnessTest)
|
||||||
|
|
||||||
var testCases = map[string]testCase{
|
var testCases = map[string]testCase{
|
||||||
"basic funding flow": testBasicChannelFunding,
|
"basic funding flow": testBasicChannelFunding,
|
||||||
@ -876,13 +879,13 @@ var testCases = map[string]testCase{
|
|||||||
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
||||||
// programmatically driven network of lnd nodes.
|
// programmatically driven network of lnd nodes.
|
||||||
func TestLightningNetworkDaemon(t *testing.T) {
|
func TestLightningNetworkDaemon(t *testing.T) {
|
||||||
ct := NewCT(t)
|
ht := newHarnessTest(t)
|
||||||
|
|
||||||
// First create the network harness to gain access to its
|
// First create the network harness to gain access to its
|
||||||
// 'OnTxAccepted' call back.
|
// 'OnTxAccepted' call back.
|
||||||
lndHarness, err := newNetworkHarness()
|
lndHarness, err := newNetworkHarness()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Fatalf("unable to create lightning network harness: %v", err)
|
ht.Fatalf("unable to create lightning network harness: %v", err)
|
||||||
}
|
}
|
||||||
defer lndHarness.TearDownAll()
|
defer lndHarness.TearDownAll()
|
||||||
|
|
||||||
@ -895,14 +898,14 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
|||||||
// drive blockchain related events within the network.
|
// drive blockchain related events within the network.
|
||||||
btcdHarness, err := rpctest.New(harnessNetParams, handlers, nil)
|
btcdHarness, err := rpctest.New(harnessNetParams, handlers, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Fatalf("unable to create mining node: %v", err)
|
ht.Fatalf("unable to create mining node: %v", err)
|
||||||
}
|
}
|
||||||
defer btcdHarness.TearDown()
|
defer btcdHarness.TearDown()
|
||||||
if err := btcdHarness.SetUp(true, 50); err != nil {
|
if err := btcdHarness.SetUp(true, 50); err != nil {
|
||||||
ct.Fatalf("unable to set up mining node: %v", err)
|
ht.Fatalf("unable to set up mining node: %v", err)
|
||||||
}
|
}
|
||||||
if err := btcdHarness.Node.NotifyNewTransactions(false); err != nil {
|
if err := btcdHarness.Node.NotifyNewTransactions(false); err != nil {
|
||||||
ct.Fatalf("unable to request transaction notifications: %v", err)
|
ht.Fatalf("unable to request transaction notifications: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the btcd harness created, we can now complete the
|
// With the btcd harness created, we can now complete the
|
||||||
@ -910,34 +913,31 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
|||||||
// example: "--debuglevel=debug"
|
// example: "--debuglevel=debug"
|
||||||
// TODO(roasbeef): create master balanced channel with all the monies?
|
// TODO(roasbeef): create master balanced channel with all the monies?
|
||||||
if err := lndHarness.InitializeSeedNodes(btcdHarness, nil); err != nil {
|
if err := lndHarness.InitializeSeedNodes(btcdHarness, nil); err != nil {
|
||||||
ct.Fatalf("unable to initialize seed nodes: %v", err)
|
ht.Fatalf("unable to initialize seed nodes: %v", err)
|
||||||
}
|
}
|
||||||
if err = lndHarness.SetUp(); err != nil {
|
if err = lndHarness.SetUp(); err != nil {
|
||||||
ct.Fatalf("unable to set up test lightning network: %v", err)
|
ht.Fatalf("unable to set up test lightning network: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.Logf("Running %v integration tests", len(testCases))
|
ht.Logf("Running %v integration tests", len(testCases))
|
||||||
|
|
||||||
for name, test := range testCases {
|
for name, test := range testCases {
|
||||||
errChan := ct.RunTest(lndHarness, test)
|
errChan := ht.RunTest(lndHarness, test)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
// Receive both types of err - panic and fatal from
|
// Attempt to read from the error channel created for this
|
||||||
// one channel and raise the fatal in main goroutine.
|
// specific test. If this error is non-nil then the test passed
|
||||||
|
// without any problems.
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Fatalf("Fail: (%v): exited with error: \n%v",
|
ht.Fatalf("Fail: (%v): exited with error: \n%v",
|
||||||
name, err)
|
name, err)
|
||||||
}
|
}
|
||||||
ct.Logf("Successed: (%v)", name)
|
ht.Logf("Passed: (%v)", name)
|
||||||
|
|
||||||
// In this case lightning node process finished with error
|
// If a read from this channel succeeeds then one of the
|
||||||
// status. It might be because of wrong flag, or it might
|
// running lnd nodes has exited with a fatal erorr.
|
||||||
// be because of nil pointer access. Who knows!? Who knows...
|
case err := <-lndHarness.ProcessErrors():
|
||||||
// TODO(andrew.shvv) When two nodes are closing simultanisly
|
ht.Fatalf("Fail: (%v): lnd finished with error "+
|
||||||
// it leads to panic - 'sending to the closed channel'. Fix it?
|
|
||||||
case err := <-lndHarness.lndErrorChan:
|
|
||||||
ct.Fatalf("Fail: (%v): lnd finished with error "+
|
|
||||||
"(stderr): \n%v", name, err)
|
"(stderr): \n%v", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/roasbeef/btcd/chaincfg"
|
"github.com/roasbeef/btcd/chaincfg"
|
||||||
@ -174,9 +175,9 @@ func (l *lightningNode) start(lndError chan error) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Launch a new goroutine which that bubbles up any potential fatal
|
||||||
|
// process errors to the goroutine running the tests.
|
||||||
go func() {
|
go func() {
|
||||||
// If lightning node process exited with error status
|
|
||||||
// then we should transmit stderr output in main process.
|
|
||||||
if err := l.cmd.Wait(); err != nil {
|
if err := l.cmd.Wait(); err != nil {
|
||||||
lndError <- errors.New(errb.String())
|
lndError <- errors.New(errb.String())
|
||||||
}
|
}
|
||||||
@ -249,14 +250,13 @@ func (l *lightningNode) cleanup() error {
|
|||||||
|
|
||||||
// stop attempts to stop the active lnd process.
|
// stop attempts to stop the active lnd process.
|
||||||
func (l *lightningNode) stop() error {
|
func (l *lightningNode) stop() error {
|
||||||
|
|
||||||
// We should skip node stop in case:
|
// We should skip node stop in case:
|
||||||
// - start of the node wasn't initiated
|
// - start of the node wasn't initiated
|
||||||
// - process wasn't spawned
|
// - process wasn't spawned
|
||||||
// - process already finished
|
// - process already finished
|
||||||
if l.cmd == nil ||
|
processFinished := l.cmd.ProcessState != nil &&
|
||||||
l.cmd.Process == nil ||
|
l.cmd.ProcessState.Exited()
|
||||||
(l.cmd.ProcessState != nil && l.cmd.ProcessState.Exited()) {
|
if l.cmd == nil || l.cmd.Process == nil || processFinished {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +344,13 @@ func (n *networkHarness) InitializeSeedNodes(r *rpctest.Harness, lndArgs []strin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProcessErrors returns a channel used for reporting any fatal process errors.
|
||||||
|
// If any of the active nodes within the harness' test network incur a fatal
|
||||||
|
// error, that error is sent over this channel.
|
||||||
|
func (n *networkHarness) ProcessErrors() chan error {
|
||||||
|
return n.lndErrorChan
|
||||||
|
}
|
||||||
|
|
||||||
// fakeLogger is a fake grpclog.Logger implementation. This is used to stop
|
// fakeLogger is a fake grpclog.Logger implementation. This is used to stop
|
||||||
// grpc's logger from printing directly to stdout.
|
// grpc's logger from printing directly to stdout.
|
||||||
type fakeLogger struct{}
|
type fakeLogger struct{}
|
||||||
|
Loading…
Reference in New Issue
Block a user