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.
This commit is contained in:
Dave Collins 2016-09-20 16:09:48 -05:00
parent daac24626e
commit 7cf9ec8190
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
4 changed files with 28 additions and 36 deletions

View file

@ -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.

View file

@ -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
}

View file

@ -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 {

View file

@ -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
}