lntest: Refactor set up calls to NetworkHarness.

This commit is contained in:
Jim Posen 2017-11-16 17:31:41 -08:00 committed by Olaoluwa Osuntokun
parent 02177a3f1c
commit 84d7c7ee2c
2 changed files with 51 additions and 90 deletions

@ -4478,29 +4478,33 @@ var testsCases = []*testCase{
func TestLightningNetworkDaemon(t *testing.T) { func TestLightningNetworkDaemon(t *testing.T) {
ht := newHarnessTest(t) ht := newHarnessTest(t)
var lndHarness *lntest.NetworkHarness
// First create an instance 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. Revert the default
// setting of accepting non-standard transactions on simnet to reject them.
// Transactions on the lightning network should always be standard to get
// better guarantees of getting included in to blocks.
args := []string{"--rejectnonstd"}
handlers := &rpcclient.NotificationHandlers{
OnTxAccepted: func(hash *chainhash.Hash, amt btcutil.Amount) {
lndHarness.OnTxAccepted(hash)
},
}
btcdHarness, err := rpctest.New(harnessNetParams, handlers, args)
if err != nil {
ht.Fatalf("unable to create mining node: %v", err)
}
defer btcdHarness.TearDown()
// 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 := lntest.NewNetworkHarness() lndHarness, err = lntest.NewNetworkHarness(btcdHarness)
if err != nil { if err != nil {
ht.Fatalf("unable to create lightning network harness: %v", err) ht.Fatalf("unable to create lightning network harness: %v", err)
} }
defer lndHarness.TearDownAll()
// Set up teardowns. While it's easier to set up the lnd harness before
// the btcd harness, they should be torn down in reverse order to
// prevent certain types of hangs.
var btcdHarness *rpctest.Harness
defer func() {
if lndHarness != nil {
lndHarness.TearDownAll()
}
if btcdHarness != nil {
btcdHarness.TearDown()
}
}()
handlers := &rpcclient.NotificationHandlers{
OnTxAccepted: lndHarness.OnTxAccepted,
}
// Spawn a new goroutine to watch for any fatal errors that any of the // Spawn a new goroutine to watch for any fatal errors that any of the
// running lnd processes encounter. If an error occurs, then the test // running lnd processes encounter. If an error occurs, then the test
@ -4518,18 +4522,6 @@ func TestLightningNetworkDaemon(t *testing.T) {
} }
}() }()
// First create an instance 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. Revert the default
// setting of accepting non-standard transactions on simnet to reject them.
// Transactions on the lightning network should always be standard to get
// better guarantees of getting included in to blocks.
args := []string{"--rejectnonstd"}
btcdHarness, err = rpctest.New(harnessNetParams, handlers, args)
if err != nil {
ht.Fatalf("unable to create mining node: %v", err)
}
// Turn off the btcd rpc logging, otherwise it will lead to panic. // Turn off the btcd rpc logging, otherwise it will lead to panic.
// TODO(andrew.shvv|roasbeef) Remove the hack after re-work the way the log // TODO(andrew.shvv|roasbeef) Remove the hack after re-work the way the log
// rotator os work. // rotator os work.
@ -4553,10 +4545,7 @@ func TestLightningNetworkDaemon(t *testing.T) {
// initialization of the network. args - list of lnd arguments, // initialization of the network. args - list of lnd arguments,
// 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.SetUp(nil); err != nil {
ht.Fatalf("unable to initialize seed nodes: %v", err)
}
if err = lndHarness.SetUp(); err != nil {
ht.Fatalf("unable to set up test lightning network: %v", err) ht.Fatalf("unable to set up test lightning network: %v", err)
} }

@ -37,7 +37,7 @@ type NetworkHarness struct {
Alice *HarnessNode Alice *HarnessNode
Bob *HarnessNode Bob *HarnessNode
seenTxns chan chainhash.Hash seenTxns chan *chainhash.Hash
bitcoinWatchRequests chan *txWatchRequest bitcoinWatchRequests chan *txWatchRequest
// Channel for transmitting stderr output from failed lightning node // Channel for transmitting stderr output from failed lightning node
@ -46,51 +46,26 @@ type NetworkHarness struct {
quit chan struct{} quit chan struct{}
sync.Mutex mtx sync.Mutex
} }
// NewNetworkHarness creates a new network test harness. // NewNetworkHarness creates a new network test harness.
// TODO(roasbeef): add option to use golang's build library to a binary of the // TODO(roasbeef): add option to use golang's build library to a binary of the
// current repo. This'll save developers from having to manually `go install` // current repo. This'll save developers from having to manually `go install`
// within the repo each time before changes // within the repo each time before changes
func NewNetworkHarness() (*NetworkHarness, error) { func NewNetworkHarness(r *rpctest.Harness) (*NetworkHarness, error) {
return &NetworkHarness{ n := NetworkHarness{
activeNodes: make(map[int]*HarnessNode), activeNodes: make(map[int]*HarnessNode),
seenTxns: make(chan chainhash.Hash), seenTxns: make(chan *chainhash.Hash),
bitcoinWatchRequests: make(chan *txWatchRequest), bitcoinWatchRequests: make(chan *txWatchRequest),
lndErrorChan: make(chan error), lndErrorChan: make(chan error),
netParams: r.ActiveNet,
Miner: r,
rpcConfig: r.RPCConfig(),
quit: make(chan struct{}), quit: make(chan struct{}),
}, nil
}
// InitializeSeedNodes initializes alice and bob nodes given an already
// running instance of btcd's rpctest harness and extra command line flags,
// which should be formatted properly - "--arg=value".
func (n *NetworkHarness) InitializeSeedNodes(r *rpctest.Harness, lndArgs []string) error {
n.netParams = r.ActiveNet
n.Miner = r
n.rpcConfig = r.RPCConfig()
config := nodeConfig{
RPCConfig: &n.rpcConfig,
NetParams: n.netParams,
ExtraArgs: lndArgs,
} }
go n.networkWatcher()
var err error return &n, nil
n.Alice, err = newNode(config)
if err != nil {
return err
}
n.Bob, err = newNode(config)
if err != nil {
return err
}
n.activeNodes[n.Alice.NodeID] = n.Alice
n.activeNodes[n.Bob.NodeID] = n.Bob
return err
} }
// ProcessErrors returns a channel used for reporting any fatal process errors. // ProcessErrors returns a channel used for reporting any fatal process errors.
@ -114,8 +89,9 @@ func (f *fakeLogger) Println(args ...interface{}) {}
// SetUp starts the initial seeder nodes within the test harness. The initial // SetUp starts the initial seeder nodes within the test harness. The initial
// node's wallets will be funded wallets with ten 1 BTC outputs each. Finally // node's wallets will be funded wallets with ten 1 BTC outputs each. Finally
// rpc clients capable of communicating with the initial seeder nodes are // rpc clients capable of communicating with the initial seeder nodes are
// created. // created. Nodes are initialized with the given extra command line flags, which
func (n *NetworkHarness) SetUp() error { // should be formatted properly - "--arg=value".
func (n *NetworkHarness) SetUp(lndArgs []string) error {
// Swap out grpc's default logger with out fake logger which drops the // Swap out grpc's default logger with out fake logger which drops the
// statements on the floor. // statements on the floor.
grpclog.SetLogger(&fakeLogger{}) grpclog.SetLogger(&fakeLogger{})
@ -127,15 +103,21 @@ func (n *NetworkHarness) SetUp() error {
wg.Add(2) wg.Add(2)
go func() { go func() {
defer wg.Done() defer wg.Done()
if err := n.Alice.start(n.lndErrorChan); err != nil { node, err := n.NewNode(lndArgs)
if err != nil {
errChan <- err errChan <- err
return
} }
n.Alice = node
}() }()
go func() { go func() {
defer wg.Done() defer wg.Done()
if err := n.Bob.start(n.lndErrorChan); err != nil { node, err := n.NewNode(lndArgs)
if err != nil {
errChan <- err errChan <- err
return
} }
n.Bob = node
}() }()
wg.Wait() wg.Wait()
select { select {
@ -214,10 +196,6 @@ out:
} }
} }
// Now that the initial test network has been initialized, launch the
// network watcher.
go n.networkWatcher()
return nil return nil
} }
@ -239,9 +217,6 @@ func (n *NetworkHarness) TearDownAll() error {
// current instance of the network harness. The created node is running, but // current instance of the network harness. The created node is running, but
// not yet connected to other nodes within the network. // not yet connected to other nodes within the network.
func (n *NetworkHarness) NewNode(extraArgs []string) (*HarnessNode, error) { func (n *NetworkHarness) NewNode(extraArgs []string) (*HarnessNode, error) {
n.Lock()
defer n.Unlock()
node, err := newNode(nodeConfig{ node, err := newNode(nodeConfig{
RPCConfig: &n.rpcConfig, RPCConfig: &n.rpcConfig,
NetParams: n.netParams, NetParams: n.netParams,
@ -253,7 +228,9 @@ func (n *NetworkHarness) NewNode(extraArgs []string) (*HarnessNode, error) {
// Put node in activeNodes to ensure Shutdown is called even if Start // Put node in activeNodes to ensure Shutdown is called even if Start
// returns an error. // returns an error.
n.mtx.Lock()
n.activeNodes[node.NodeID] = node n.activeNodes[node.NodeID] = node
n.mtx.Unlock()
if err := node.start(n.lndErrorChan); err != nil { if err := node.start(n.lndErrorChan); err != nil {
return nil, err return nil, err
@ -403,11 +380,11 @@ func (n *NetworkHarness) networkWatcher() {
// we're able to dispatch any notifications for this // we're able to dispatch any notifications for this
// txid which arrive *after* it's seen within the // txid which arrive *after* it's seen within the
// network. // network.
seenTxns[txid] = struct{}{} seenTxns[*txid] = struct{}{}
// If there isn't a registered notification for this // If there isn't a registered notification for this
// transaction then ignore it. // transaction then ignore it.
txClients, ok := clients[txid] txClients, ok := clients[*txid]
if !ok { if !ok {
continue continue
} }
@ -417,24 +394,19 @@ func (n *NetworkHarness) networkWatcher() {
for _, client := range txClients { for _, client := range txClients {
close(client) close(client)
} }
delete(clients, txid) delete(clients, *txid)
} }
} }
} }
// OnTxAccepted is a callback to be called each time a new transaction has been // OnTxAccepted is a callback to be called each time a new transaction has been
// broadcast on the network. // broadcast on the network.
func (n *NetworkHarness) OnTxAccepted(hash *chainhash.Hash, amt btcutil.Amount) { func (n *NetworkHarness) OnTxAccepted(hash *chainhash.Hash) {
// Return immediately if harness has been torn down.
select { select {
case n.seenTxns <- hash:
case <-n.quit: case <-n.quit:
return return
default:
} }
go func() {
n.seenTxns <- *hash
}()
} }
// WaitForTxBroadcast blocks until the target txid is seen on the network. If // WaitForTxBroadcast blocks until the target txid is seen on the network. If