Merge pull request #6139 from guggero/itest-refactor
itest: refactor for re-use in LiT
This commit is contained in:
6 files changed
+70
-48
No files matched your search
@@ -21,6 +21,9 @@
|
|||||||
using itest harness outside of
|
using itest harness outside of
|
||||||
lnd](https://github.com/lightningnetwork/lnd/pull/6050).
|
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
|
## Bug fixes
|
||||||
|
|
||||||
* [Return the nearest known fee rate when a given conf target cannot be found
|
* [Return the nearest known fee rate when a given conf target cannot be found
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import (
|
|||||||
const DefaultCSV = 4
|
const DefaultCSV = 4
|
||||||
|
|
||||||
// NodeOption is a function for updating a node's configuration.
|
// 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.
|
// NetworkHarness is an integration testing harness for the lightning network.
|
||||||
// Building on top of HarnessNode, it is responsible for handling interactions
|
// Building on top of HarnessNode, it is responsible for handling interactions
|
||||||
@@ -489,7 +489,7 @@ func (n *NetworkHarness) newNode(name string, extraArgs []string, hasSeed bool,
|
|||||||
password []byte, dbBackend DatabaseBackend, wait bool, opts ...NodeOption) (
|
password []byte, dbBackend DatabaseBackend, wait bool, opts ...NodeOption) (
|
||||||
*HarnessNode, error) {
|
*HarnessNode, error) {
|
||||||
|
|
||||||
cfg := &NodeConfig{
|
cfg := &BaseNodeConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
LogFilenamePrefix: n.currentTestCase,
|
LogFilenamePrefix: n.currentTestCase,
|
||||||
HasSeed: hasSeed,
|
HasSeed: hasSeed,
|
||||||
@@ -504,7 +504,7 @@ func (n *NetworkHarness) newNode(name string, extraArgs []string, hasSeed bool,
|
|||||||
opt(cfg)
|
opt(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err := newNode(*cfg)
|
node, err := newNode(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-38
@@ -67,24 +67,6 @@ func postgresDatabaseDsn(dbName string) string {
|
|||||||
return fmt.Sprintf(postgresDsn, dbName)
|
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
|
// BackendConfig is an interface that abstracts away the specific chain backend
|
||||||
// node implementation.
|
// node implementation.
|
||||||
type BackendConfig interface {
|
type BackendConfig interface {
|
||||||
@@ -102,10 +84,25 @@ type BackendConfig interface {
|
|||||||
Name() string
|
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
|
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.
|
// to store the current test case for simpler postmortem debugging.
|
||||||
LogFilenamePrefix string
|
LogFilenamePrefix string
|
||||||
|
|
||||||
@@ -139,28 +136,28 @@ type NodeConfig struct {
|
|||||||
PostgresDsn string
|
PostgresDsn string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg NodeConfig) P2PAddr() string {
|
func (cfg BaseNodeConfig) P2PAddr() string {
|
||||||
return fmt.Sprintf(listenerFormat, cfg.P2PPort)
|
return fmt.Sprintf(ListenerFormat, cfg.P2PPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg NodeConfig) RPCAddr() string {
|
func (cfg BaseNodeConfig) RPCAddr() string {
|
||||||
return fmt.Sprintf(listenerFormat, cfg.RPCPort)
|
return fmt.Sprintf(ListenerFormat, cfg.RPCPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg NodeConfig) RESTAddr() string {
|
func (cfg BaseNodeConfig) RESTAddr() string {
|
||||||
return fmt.Sprintf(listenerFormat, cfg.RESTPort)
|
return fmt.Sprintf(ListenerFormat, cfg.RESTPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBDir returns the holding directory path of the graph database.
|
// 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)
|
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")
|
return filepath.Join(cfg.DBDir(), "channel.db")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg NodeConfig) ChanBackupPath() string {
|
func (cfg BaseNodeConfig) ChanBackupPath() string {
|
||||||
return filepath.Join(
|
return filepath.Join(
|
||||||
cfg.DataDir, "chain", "bitcoin",
|
cfg.DataDir, "chain", "bitcoin",
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
@@ -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.
|
// config struct.
|
||||||
func (cfg NodeConfig) genArgs() []string {
|
func (cfg *BaseNodeConfig) GenArgs() []string {
|
||||||
var args []string
|
var args []string
|
||||||
|
|
||||||
switch cfg.NetParams {
|
switch cfg.NetParams {
|
||||||
@@ -283,7 +302,7 @@ type policyUpdateMap map[string]map[string][]*lnrpc.RoutingPolicy
|
|||||||
// harness. Each HarnessNode instance also fully embeds an RPC client in
|
// harness. Each HarnessNode instance also fully embeds an RPC client in
|
||||||
// order to pragmatically drive the node.
|
// order to pragmatically drive the node.
|
||||||
type HarnessNode struct {
|
type HarnessNode struct {
|
||||||
Cfg *NodeConfig
|
Cfg *BaseNodeConfig
|
||||||
|
|
||||||
// NodeID is a unique identifier for the node within a NetworkHarness.
|
// NodeID is a unique identifier for the node within a NetworkHarness.
|
||||||
NodeID int
|
NodeID int
|
||||||
@@ -377,7 +396,7 @@ func nextNodeID() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newNode creates a new test lightning node instance from the passed config.
|
// 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 == "" {
|
if cfg.BaseDir == "" {
|
||||||
var err error
|
var err error
|
||||||
cfg.BaseDir, err = ioutil.TempDir("", "lndtest-node")
|
cfg.BaseDir, err = ioutil.TempDir("", "lndtest-node")
|
||||||
@@ -397,7 +416,7 @@ func newNode(cfg NodeConfig) (*HarnessNode, error) {
|
|||||||
cfg.ReadMacPath = filepath.Join(networkDir, "readonly.macaroon")
|
cfg.ReadMacPath = filepath.Join(networkDir, "readonly.macaroon")
|
||||||
cfg.InvoiceMacPath = filepath.Join(networkDir, "invoice.macaroon")
|
cfg.InvoiceMacPath = filepath.Join(networkDir, "invoice.macaroon")
|
||||||
|
|
||||||
generateListeningPorts(&cfg)
|
cfg.GenerateListeningPorts()
|
||||||
|
|
||||||
// Run all tests with accept keysend. The keysend code is very isolated
|
// Run all tests with accept keysend. The keysend code is very isolated
|
||||||
// and it is highly unlikely that it would affect regular itests when
|
// and it is highly unlikely that it would affect regular itests when
|
||||||
@@ -416,7 +435,7 @@ func newNode(cfg NodeConfig) (*HarnessNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &HarnessNode{
|
return &HarnessNode{
|
||||||
Cfg: &cfg,
|
Cfg: cfg,
|
||||||
NodeID: nextNodeID(),
|
NodeID: nextNodeID(),
|
||||||
chanWatchRequests: make(chan *chanWatchRequest),
|
chanWatchRequests: make(chan *chanWatchRequest),
|
||||||
openChans: make(map[wire.OutPoint]int),
|
openChans: make(map[wire.OutPoint]int),
|
||||||
@@ -511,12 +530,12 @@ func (hn *HarnessNode) String() string {
|
|||||||
nodeState.ClosedChans[outpoint.String()] = count
|
nodeState.ClosedChans[outpoint.String()] = count
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := json.MarshalIndent(nodeState, "", "\t")
|
stateBytes, err := json.MarshalIndent(nodeState, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Sprintf("\n encode node state with err: %v", err)
|
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.
|
// DBPath returns the filepath to the channeldb database file for this node.
|
||||||
@@ -569,7 +588,7 @@ func (hn *HarnessNode) InvoiceMacPath() string {
|
|||||||
// startLnd handles the startup of lnd, creating log files, and possibly kills
|
// startLnd handles the startup of lnd, creating log files, and possibly kills
|
||||||
// the process when needed.
|
// the process when needed.
|
||||||
func (hn *HarnessNode) startLnd(lndBinary string, lndError chan<- error) error {
|
func (hn *HarnessNode) startLnd(lndBinary string, lndError chan<- error) error {
|
||||||
args := hn.Cfg.genArgs()
|
args := hn.Cfg.GenArgs()
|
||||||
hn.cmd = exec.Command(lndBinary, args...)
|
hn.cmd = exec.Command(lndBinary, args...)
|
||||||
|
|
||||||
// Redirect stderr output to buffer
|
// Redirect stderr output to buffer
|
||||||
|
|||||||
@@ -1372,7 +1372,7 @@ func chanRestoreViaRPC(net *lntest.NetworkHarness, password []byte,
|
|||||||
// copyPorts returns a node option function that copies the ports of an existing
|
// copyPorts returns a node option function that copies the ports of an existing
|
||||||
// node over to the newly created one.
|
// node over to the newly created one.
|
||||||
func copyPorts(oldNode *lntest.HarnessNode) lntest.NodeOption {
|
func copyPorts(oldNode *lntest.HarnessNode) lntest.NodeOption {
|
||||||
return func(cfg *lntest.NodeConfig) {
|
return func(cfg *lntest.BaseNodeConfig) {
|
||||||
cfg.P2PPort = oldNode.Cfg.P2PPort
|
cfg.P2PPort = oldNode.Cfg.P2PPort
|
||||||
cfg.RPCPort = oldNode.Cfg.RPCPort
|
cfg.RPCPort = oldNode.Cfg.RPCPort
|
||||||
cfg.RESTPort = oldNode.Cfg.RESTPort
|
cfg.RESTPort = oldNode.Cfg.RESTPort
|
||||||
|
|||||||
@@ -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
|
// withP2PPort is a helper closure used to set the P2P port that a node
|
||||||
// should use.
|
// should use.
|
||||||
var withP2PPort = func(port int) lntest.NodeOption {
|
var withP2PPort = func(port int) lntest.NodeOption {
|
||||||
return func(cfg *lntest.NodeConfig) {
|
return func(cfg *lntest.BaseNodeConfig) {
|
||||||
cfg.P2PPort = port
|
cfg.P2PPort = port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ const (
|
|||||||
// number and are determined by the results of nextAvailablePort().
|
// number and are determined by the results of nextAvailablePort().
|
||||||
defaultNodePort = 5555
|
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.
|
// listener addresses.
|
||||||
listenerFormat = "127.0.0.1:%d"
|
ListenerFormat = "127.0.0.1:%d"
|
||||||
|
|
||||||
// NeutrinoBackendName is the name of the neutrino backend.
|
// NeutrinoBackendName is the name of the neutrino backend.
|
||||||
NeutrinoBackendName = "neutrino"
|
NeutrinoBackendName = "neutrino"
|
||||||
@@ -73,7 +73,7 @@ func NextAvailablePort() int {
|
|||||||
// the harness node, in practice in CI servers this seems much
|
// the harness node, in practice in CI servers this seems much
|
||||||
// less likely than simply some other process already being
|
// less likely than simply some other process already being
|
||||||
// bound at the start of the tests.
|
// bound at the start of the tests.
|
||||||
addr := fmt.Sprintf(listenerFormat, port)
|
addr := fmt.Sprintf(ListenerFormat, port)
|
||||||
l, err := net.Listen("tcp4", addr)
|
l, err := net.Listen("tcp4", addr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err := l.Close()
|
err := l.Close()
|
||||||
@@ -117,8 +117,8 @@ func GetBtcdBinary() string {
|
|||||||
// addresses with unique ports and should be used to overwrite rpctest's
|
// addresses with unique ports and should be used to overwrite rpctest's
|
||||||
// default generator which is prone to use colliding ports.
|
// default generator which is prone to use colliding ports.
|
||||||
func GenerateBtcdListenerAddresses() (string, string) {
|
func GenerateBtcdListenerAddresses() (string, string) {
|
||||||
return fmt.Sprintf(listenerFormat, NextAvailablePort()),
|
return fmt.Sprintf(ListenerFormat, NextAvailablePort()),
|
||||||
fmt.Sprintf(listenerFormat, NextAvailablePort())
|
fmt.Sprintf(ListenerFormat, NextAvailablePort())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeOutpoint returns the outpoint of the channel's funding transaction.
|
// MakeOutpoint returns the outpoint of the channel's funding transaction.
|
||||||
|
|||||||
Reference in new issue
Block a user