From 7cf9ec81909f69c267f4cb130bc1bbe04ff488b0 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 20 Sep 2016 16:09:48 -0500 Subject: [PATCH] rpctest: Use ports based on the process id. This modifies the ports that are selected for use for the p2p and rpc ports to start with a port that is based on the process id instead of a hard-coded value. The chosen ports are incremented for each running instance similar to the previous code except the p2p and rpc ports and now split into ranges instead of being 2 apart. This is being done because the previous code only worked for a single process which means it prevented the ability to run tests in parallel. The new approach will work with multiple processes, however it must be stated that there is still a very small probability that the stars could align resulting in the same ports being selected. Finally, this also reverts the recent change to run tests serially since this fixes the underlying cause for that change. --- goclean.sh | 2 +- rpctest/rpc_harness.go | 47 ++++++++++++++++++++----------------- rpctest/rpc_harness_test.go | 6 +---- rpctest/utils.go | 9 +------ 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/goclean.sh b/goclean.sh index 1c77bceb..8a4e8379 100755 --- a/goclean.sh +++ b/goclean.sh @@ -12,7 +12,7 @@ set -ex test -z "$(go fmt $(glide novendor) | tee /dev/stderr)" test -z "$(for package in $(glide novendor); do golint $package; done | grep -v 'ALL_CAPS\|OP_\|NewFieldVal' | tee /dev/stderr)" test -z "$(go vet $(glide novendor) 2>&1 | tee /dev/stderr)" -env GORACE="halt_on_error=1" go test -p 1 -v -race $(glide novendor) +env GORACE="halt_on_error=1" go test -v -race $(glide novendor) # Run test coverage on each subdirectories and merge the coverage profile. diff --git a/rpctest/rpc_harness.go b/rpctest/rpc_harness.go index 0c5270fa..24fcd631 100644 --- a/rpctest/rpc_harness.go +++ b/rpctest/rpc_harness.go @@ -22,23 +22,29 @@ import ( "github.com/btcsuite/btcutil" ) +const ( + // These constants define the minimum and maximum p2p and rpc port + // numbers used by a test harness. The min port is inclusive while the + // max port is exclusive. + minPeerPort = 10000 + maxPeerPort = 35000 + minRPCPort = maxPeerPort + maxRPCPort = 60000 +) + var ( // current number of active test nodes. numTestInstances = 0 - // defaultP2pPort is the initial p2p port which will be used by the - // first created rpc harnesses to listen on for incoming p2p - // connections. Subsequent allocated ports for future rpc harness - // instances will be monotonically increasing odd numbers calculated as - // such: defaultP2pPort + (2 * harness.nodeNum). - defaultP2pPort = 18555 - - // defaultRPCPort is the initial rpc port which will be used by the - // first created rpc harnesses to listen on for incoming rpc - // connections. Subsequent allocated ports for future rpc harness - // instances will be monotonically increasing even numbers calculated - // as such: defaultP2pPort + (2 * harness.nodeNum). - defaultRPCPort = 18556 + // processID is the process ID of the current running process. It is + // used to calculate ports based upon it when launching an rpc + // harnesses. The intent is to allow multiple process to run in + // parallel without port collisions. + // + // It should be noted however that there is still some small probability + // that there will be port collisions either due to other processes + // running or simply due to the stars aligning on the process IDs. + processID = os.Getppid() // testInstances is a private package-level slice used to keep track of // all active test harnesses. This global can be used to perform @@ -392,18 +398,15 @@ func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32, // support multiple test nodes running at once, the p2p and rpc port are // incremented after each initialization. func generateListeningAddresses() (string, string) { - var p2p, rpc string localhost := "127.0.0.1" - if numTestInstances == 0 { - p2p = net.JoinHostPort(localhost, strconv.Itoa(defaultP2pPort)) - rpc = net.JoinHostPort(localhost, strconv.Itoa(defaultRPCPort)) - } else { - p2p = net.JoinHostPort(localhost, - strconv.Itoa(defaultP2pPort+(2*numTestInstances))) - rpc = net.JoinHostPort(localhost, - strconv.Itoa(defaultRPCPort+(2*numTestInstances))) + portString := func(minPort, maxPort int) string { + port := minPort + numTestInstances + ((20 * processID) % + (maxPort - minPort)) + return strconv.Itoa(port) } + p2p := net.JoinHostPort(localhost, portString(minPeerPort, maxPeerPort)) + rpc := net.JoinHostPort(localhost, portString(minRPCPort, maxRPCPort)) return p2p, rpc } diff --git a/rpctest/rpc_harness_test.go b/rpctest/rpc_harness_test.go index 042744a1..9cefaaa4 100644 --- a/rpctest/rpc_harness_test.go +++ b/rpctest/rpc_harness_test.go @@ -5,9 +5,7 @@ package rpctest import ( "fmt" - "net" "os" - "strconv" "testing" "time" @@ -82,14 +80,12 @@ func testSendOutputs(r *Harness, t *testing.T) { } func assertConnectedTo(t *testing.T, nodeA *Harness, nodeB *Harness) { - nodePort := defaultP2pPort + (2 * nodeB.nodeNum) - nodeAddr := net.JoinHostPort("127.0.0.1", strconv.Itoa(nodePort)) - nodeAPeers, err := nodeA.Node.GetPeerInfo() if err != nil { t.Fatalf("unable to get nodeA's peer info") } + nodeAddr := nodeB.node.config.listen addrFound := false for _, peerInfo := range nodeAPeers { if peerInfo.Addr == nodeAddr { diff --git a/rpctest/utils.go b/rpctest/utils.go index f3309088..b10f462f 100644 --- a/rpctest/utils.go +++ b/rpctest/utils.go @@ -5,9 +5,7 @@ package rpctest import ( - "net" "reflect" - "strconv" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -110,18 +108,13 @@ retry: // therefore in the case of disconnects, "from" will attempt to reestablish a // connection to the "to" harness. func ConnectNode(from *Harness, to *Harness) error { - // Calculate the target p2p addr+port for the node to be connected to. - // p2p ports uses within the package are always even, so we multiply - // the node number by two before offsetting from the defaultP2pPort. - targetPort := defaultP2pPort + (2 * to.nodeNum) - targetAddr := net.JoinHostPort("127.0.0.1", strconv.Itoa(targetPort)) - peerInfo, err := from.Node.GetPeerInfo() if err != nil { return err } numPeers := len(peerInfo) + targetAddr := to.node.config.listen if err := from.Node.AddNode(targetAddr, btcrpcclient.ANAdd); err != nil { return err }