#592: Fix test port allocation flakiness

This commit is contained in:
Andras Slemmer 2017-05-05 15:10:56 +01:00
parent 3a2afcdbb2
commit f744c4455e
2 changed files with 13 additions and 10 deletions

View File

@ -35,6 +35,7 @@ import java.nio.file.Path
import java.security.KeyPair
import java.security.PublicKey
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
import kotlin.reflect.KClass
/**
@ -90,6 +91,7 @@ val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Ve
fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
private val freePortCounter = AtomicInteger(30000)
/**
* Returns a free port.
*
@ -97,7 +99,7 @@ fun generateStateRef() = StateRef(SecureHash.randomSHA256(), 0)
* Use [getFreeLocalPorts] for getting multiple ports.
*/
fun freeLocalHostAndPort(): HostAndPort {
val freePort = ServerSocket(0).use { it.localPort }
val freePort = freePortCounter.getAndAccumulate(0) { prev, _ -> 30000 + (prev - 30000 + 1) % 10000 }
return HostAndPort.fromParts("localhost", freePort)
}
@ -108,12 +110,8 @@ fun freeLocalHostAndPort(): HostAndPort {
* to the Node, some other process else could allocate the returned ports.
*/
fun getFreeLocalPorts(hostName: String, numberToAlloc: Int): List<HostAndPort> {
// Create a bunch of sockets up front.
val sockets = Array(numberToAlloc) { ServerSocket(0) }
val result = sockets.map { HostAndPort.fromParts(hostName, it.localPort) }
// Close sockets only once we've grabbed all the ports we need.
sockets.forEach(ServerSocket::close)
return result
val freePort = freePortCounter.getAndAccumulate(0) { prev, _ -> 30000 + (prev - 30000 + numberToAlloc) % 10000 }
return (freePort .. freePort + numberToAlloc - 1).map { HostAndPort.fromParts(hostName, it) }
}
/**

View File

@ -10,6 +10,7 @@ import net.corda.client.rpc.internal.RPCClient
import net.corda.client.rpc.internal.RPCClientConfiguration
import net.corda.core.div
import net.corda.core.messaging.RPCOps
import net.corda.core.random63BitValue
import net.corda.core.utilities.ProcessUtilities
import net.corda.node.driver.*
import net.corda.node.services.RPCUserService
@ -101,7 +102,7 @@ interface RPCDriverExposedDSLInterface : DriverDSLExposedInterface {
* @param ops The server-side implementation of the RPC interface.
*/
fun <I : RPCOps> startRpcServer(
serverName: String = "driver-rpc-server",
serverName: String = "driver-rpc-server-${random63BitValue()}",
rpcUser: User = rpcTestUser,
nodeLegalName: X500Name = fakeNodeLegalName,
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
@ -182,11 +183,14 @@ data class RpcServerHandle(
val rpcTestUser = User("user1", "test", permissions = emptySet())
val fakeNodeLegalName = X500Name("not:a:valid:name")
// Use a global pool so that we can run RPC tests in parallel
private val globalPortAllocation = PortAllocation.Incremental(10000)
private val globalDebugPortAllocation = PortAllocation.Incremental(5005)
fun <A> rpcDriver(
isDebug: Boolean = false,
driverDirectory: Path = Paths.get("build", getTimestampAsDirectoryName()),
portAllocation: PortAllocation = PortAllocation.Incremental(10000),
debugPortAllocation: PortAllocation = PortAllocation.Incremental(5005),
portAllocation: PortAllocation = globalPortAllocation,
debugPortAllocation: PortAllocation = globalDebugPortAllocation,
systemProperties: Map<String, String> = emptyMap(),
useTestClock: Boolean = false,
automaticallyStartNetworkMap: Boolean = false,
@ -339,6 +343,7 @@ data class RPCDriverDSL(
ops: I
): ListenableFuture<RpcServerHandle> {
val hostAndPort = driverDSL.portAllocation.nextHostAndPort()
addressMustNotBeBound(driverDSL.executorService, hostAndPort)
return driverDSL.executorService.submit<RpcServerHandle> {
val artemisConfig = createRpcServerArtemisConfig(maxFileSize, maxBufferedBytesPerClient, driverDSL.driverDirectory / serverName, hostAndPort)
val server = ActiveMQServerImpl(artemisConfig, SingleUserSecurityManager(rpcUser))