Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

itest: refactor for re-use in LiT #6139

Merged
merged 4 commits into from
Jan 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/release-notes/release-notes-0.14.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
using itest harness outside of
lnd](https://github.com/lightningnetwork/lnd/pull/6050).

* [Export `lntest` base node config so it can be re-used in LiT integration
tests](https://github.com/lightningnetwork/lnd/pull/6139).

## Bug fixes

* [Return the nearest known fee rate when a given conf target cannot be found
Expand Down
6 changes: 3 additions & 3 deletions lntest/harness_net.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
const DefaultCSV = 4

// NodeOption is a function for updating a node's configuration.
type NodeOption func(*NodeConfig)
type NodeOption func(*BaseNodeConfig)

// NetworkHarness is an integration testing harness for the lightning network.
// Building on top of HarnessNode, it is responsible for handling interactions
Expand Down Expand Up @@ -489,7 +489,7 @@ func (n *NetworkHarness) newNode(name string, extraArgs []string, hasSeed bool,
password []byte, dbBackend DatabaseBackend, wait bool, opts ...NodeOption) (
*HarnessNode, error) {

cfg := &NodeConfig{
cfg := &BaseNodeConfig{
Name: name,
LogFilenamePrefix: n.currentTestCase,
HasSeed: hasSeed,
Expand All @@ -504,7 +504,7 @@ func (n *NetworkHarness) newNode(name string, extraArgs []string, hasSeed bool,
opt(cfg)
}

node, err := newNode(*cfg)
node, err := newNode(cfg)
if err != nil {
return nil, err
}
Expand Down
95 changes: 57 additions & 38 deletions lntest/harness_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,6 @@ func postgresDatabaseDsn(dbName string) string {
return fmt.Sprintf(postgresDsn, dbName)
}

// generateListeningPorts returns four ints representing ports to listen on
// designated for the current lightning network test. This returns the next
// available ports for the p2p, rpc, rest and profiling services.
func generateListeningPorts(cfg *NodeConfig) {
if cfg.P2PPort == 0 {
cfg.P2PPort = NextAvailablePort()
}
if cfg.RPCPort == 0 {
cfg.RPCPort = NextAvailablePort()
}
if cfg.RESTPort == 0 {
cfg.RESTPort = NextAvailablePort()
}
if cfg.ProfilePort == 0 {
cfg.ProfilePort = NextAvailablePort()
}
}

// BackendConfig is an interface that abstracts away the specific chain backend
// node implementation.
type BackendConfig interface {
Expand All @@ -102,10 +84,25 @@ type BackendConfig interface {
Name() string
}

type NodeConfig struct {
// NodeConfig is the basic interface a node configuration must implement.
type NodeConfig interface {
// BaseConfig returns the base node configuration struct.
BaseConfig() *BaseNodeConfig

// GenerateListeningPorts generates the ports to listen on designated
// for the current lightning network test.
GenerateListeningPorts()

// GenArgs generates a slice of command line arguments from the
// lightning node config struct.
GenArgs() []string
}

// BaseNodeConfig is the base node configuration.
type BaseNodeConfig struct {
Name string

// LogFilenamePrefix is is used to prefix node log files. Can be used
// LogFilenamePrefix is used to prefix node log files. Can be used
// to store the current test case for simpler postmortem debugging.
LogFilenamePrefix string

Expand Down Expand Up @@ -139,28 +136,28 @@ type NodeConfig struct {
PostgresDsn string
}

func (cfg NodeConfig) P2PAddr() string {
return fmt.Sprintf(listenerFormat, cfg.P2PPort)
func (cfg BaseNodeConfig) P2PAddr() string {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we use pointer receivers?

return fmt.Sprintf(ListenerFormat, cfg.P2PPort)
}

func (cfg NodeConfig) RPCAddr() string {
return fmt.Sprintf(listenerFormat, cfg.RPCPort)
func (cfg BaseNodeConfig) RPCAddr() string {
return fmt.Sprintf(ListenerFormat, cfg.RPCPort)
}

func (cfg NodeConfig) RESTAddr() string {
return fmt.Sprintf(listenerFormat, cfg.RESTPort)
func (cfg BaseNodeConfig) RESTAddr() string {
return fmt.Sprintf(ListenerFormat, cfg.RESTPort)
}

// DBDir returns the holding directory path of the graph database.
func (cfg NodeConfig) DBDir() string {
func (cfg BaseNodeConfig) DBDir() string {
return filepath.Join(cfg.DataDir, "graph", cfg.NetParams.Name)
}

func (cfg NodeConfig) DBPath() string {
func (cfg BaseNodeConfig) DBPath() string {
return filepath.Join(cfg.DBDir(), "channel.db")
}

func (cfg NodeConfig) ChanBackupPath() string {
func (cfg BaseNodeConfig) ChanBackupPath() string {
return filepath.Join(
cfg.DataDir, "chain", "bitcoin",
fmt.Sprintf(
Expand All @@ -170,9 +167,31 @@ func (cfg NodeConfig) ChanBackupPath() string {
)
}

// genArgs generates a slice of command line arguments from the lightning node
// GenerateListeningPorts generates the ports to listen on designated for the
// current lightning network test.
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
if cfg.P2PPort == 0 {
cfg.P2PPort = NextAvailablePort()
}
if cfg.RPCPort == 0 {
cfg.RPCPort = NextAvailablePort()
}
if cfg.RESTPort == 0 {
cfg.RESTPort = NextAvailablePort()
}
if cfg.ProfilePort == 0 {
cfg.ProfilePort = NextAvailablePort()
}
}

// BaseConfig returns the base node configuration struct.
func (cfg *BaseNodeConfig) BaseConfig() *BaseNodeConfig {
return cfg
}

// GenArgs generates a slice of command line arguments from the lightning node
// config struct.
func (cfg NodeConfig) genArgs() []string {
func (cfg *BaseNodeConfig) GenArgs() []string {
var args []string

switch cfg.NetParams {
Expand Down Expand Up @@ -283,7 +302,7 @@ type policyUpdateMap map[string]map[string][]*lnrpc.RoutingPolicy
// harness. Each HarnessNode instance also fully embeds an RPC client in
// order to pragmatically drive the node.
type HarnessNode struct {
Cfg *NodeConfig
Cfg *BaseNodeConfig

// NodeID is a unique identifier for the node within a NetworkHarness.
NodeID int
Expand Down Expand Up @@ -377,7 +396,7 @@ func nextNodeID() int {
}

// newNode creates a new test lightning node instance from the passed config.
func newNode(cfg NodeConfig) (*HarnessNode, error) {
func newNode(cfg *BaseNodeConfig) (*HarnessNode, error) {
if cfg.BaseDir == "" {
var err error
cfg.BaseDir, err = ioutil.TempDir("", "lndtest-node")
Expand All @@ -397,7 +416,7 @@ func newNode(cfg NodeConfig) (*HarnessNode, error) {
cfg.ReadMacPath = filepath.Join(networkDir, "readonly.macaroon")
cfg.InvoiceMacPath = filepath.Join(networkDir, "invoice.macaroon")

generateListeningPorts(&cfg)
cfg.GenerateListeningPorts()

// Run all tests with accept keysend. The keysend code is very isolated
// and it is highly unlikely that it would affect regular itests when
Expand All @@ -416,7 +435,7 @@ func newNode(cfg NodeConfig) (*HarnessNode, error) {
}

return &HarnessNode{
Cfg: &cfg,
Cfg: cfg,
NodeID: nextNodeID(),
chanWatchRequests: make(chan *chanWatchRequest),
openChans: make(map[wire.OutPoint]int),
Expand Down Expand Up @@ -511,12 +530,12 @@ func (hn *HarnessNode) String() string {
nodeState.ClosedChans[outpoint.String()] = count
}

bytes, err := json.MarshalIndent(nodeState, "", "\t")
stateBytes, err := json.MarshalIndent(nodeState, "", "\t")
if err != nil {
return fmt.Sprintf("\n encode node state with err: %v", err)
}

return fmt.Sprintf("\nnode state: %s", bytes)
return fmt.Sprintf("\nnode state: %s", stateBytes)
}

// DBPath returns the filepath to the channeldb database file for this node.
Expand Down Expand Up @@ -569,7 +588,7 @@ func (hn *HarnessNode) InvoiceMacPath() string {
// startLnd handles the startup of lnd, creating log files, and possibly kills
// the process when needed.
func (hn *HarnessNode) startLnd(lndBinary string, lndError chan<- error) error {
args := hn.Cfg.genArgs()
args := hn.Cfg.GenArgs()
hn.cmd = exec.Command(lndBinary, args...)

// Redirect stderr output to buffer
Expand Down
2 changes: 1 addition & 1 deletion lntest/itest/lnd_channel_backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ func chanRestoreViaRPC(net *lntest.NetworkHarness, password []byte,
// copyPorts returns a node option function that copies the ports of an existing
// node over to the newly created one.
func copyPorts(oldNode *lntest.HarnessNode) lntest.NodeOption {
return func(cfg *lntest.NodeConfig) {
return func(cfg *lntest.BaseNodeConfig) {
cfg.P2PPort = oldNode.Cfg.P2PPort
cfg.RPCPort = oldNode.Cfg.RPCPort
cfg.RESTPort = oldNode.Cfg.RESTPort
Expand Down
2 changes: 1 addition & 1 deletion lntest/itest/lnd_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func testReconnectAfterIPChange(net *lntest.NetworkHarness, t *harnessTest) {
// withP2PPort is a helper closure used to set the P2P port that a node
// should use.
var withP2PPort = func(port int) lntest.NodeOption {
return func(cfg *lntest.NodeConfig) {
return func(cfg *lntest.BaseNodeConfig) {
cfg.P2PPort = port
}
}
Expand Down
10 changes: 5 additions & 5 deletions lntest/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const (
// number and are determined by the results of nextAvailablePort().
defaultNodePort = 5555

// listenerFormat is the format string that is used to generate local
// ListenerFormat is the format string that is used to generate local
// listener addresses.
listenerFormat = "127.0.0.1:%d"
ListenerFormat = "127.0.0.1:%d"

// NeutrinoBackendName is the name of the neutrino backend.
NeutrinoBackendName = "neutrino"
Expand Down Expand Up @@ -73,7 +73,7 @@ func NextAvailablePort() int {
// the harness node, in practice in CI servers this seems much
// less likely than simply some other process already being
// bound at the start of the tests.
addr := fmt.Sprintf(listenerFormat, port)
addr := fmt.Sprintf(ListenerFormat, port)
l, err := net.Listen("tcp4", addr)
if err == nil {
err := l.Close()
Expand Down Expand Up @@ -117,8 +117,8 @@ func GetBtcdBinary() string {
// addresses with unique ports and should be used to overwrite rpctest's
// default generator which is prone to use colliding ports.
func GenerateBtcdListenerAddresses() (string, string) {
return fmt.Sprintf(listenerFormat, NextAvailablePort()),
fmt.Sprintf(listenerFormat, NextAvailablePort())
return fmt.Sprintf(ListenerFormat, NextAvailablePort()),
fmt.Sprintf(ListenerFormat, NextAvailablePort())
}

// MakeOutpoint returns the outpoint of the channel's funding transaction.
Expand Down