Connection limits tests (#509)

* connection limit tests

* remove use of secio

* check that upgraded fut is not nil

* rebuild
This commit is contained in:
Dmitriy Ryajov 2021-01-27 21:27:33 -06:00 committed by GitHub
parent 1d77d37f17
commit fb493d1a4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 342 additions and 7 deletions

View File

@ -83,7 +83,7 @@ proc init*(C: type ConnManager,
maxIn = -1,
maxOut = -1): ConnManager =
var inSema, outSema: AsyncSemaphore
if maxIn > 0 and maxOut > 0:
if maxIn > 0 or maxOut > 0:
inSema = newAsyncSemaphore(maxIn)
outSema = newAsyncSemaphore(maxOut)
elif maxConnections > 0:

View File

@ -20,8 +20,6 @@ type
proc newStandardSwitch*(privKey = none(PrivateKey),
address = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),
secureManagers: openarray[SecureProtocol] = [
# array cos order matters
SecureProtocol.Secio,
SecureProtocol.Noise,
],
transportFlags: set[ServerFlags] = {},

View File

@ -41,6 +41,7 @@ proc isUpgraded*(s: Connection): bool =
return s.upgraded.finished
proc upgrade*(s: Connection, failed: ref Exception = nil) =
if not isNil(s.upgraded):
if not isNil(failed):
s.upgraded.fail(failed)
return

View File

@ -239,3 +239,227 @@ suite "Connection Manager":
check isNil(connMngr.selectConn(peer.peerId, Direction.Out))
await connMngr.close()
asyncTest "track total incoming connection limits":
let connMngr = ConnManager.init(maxConnections = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check await conn.withTimeout(10.millis)
conns.add(await conn)
# should timeout adding a connection over the limit
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check not(await conn.withTimeout(10.millis))
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track total outgoing connection limits":
let connMngr = ConnManager.init(maxConnections = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
conns.add(conn)
# should throw adding a connection over the limit
expect TooManyConnectionsError:
discard await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track both incoming and outgoing total connections limits - fail on incoming":
let connMngr = ConnManager.init(maxConnections = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
conns.add(conn)
# should timeout adding a connection over the limit
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check not(await conn.withTimeout(10.millis))
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track both incoming and outgoing total connections limits - fail on outgoing":
let connMngr = ConnManager.init(maxConnections = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check await conn.withTimeout(10.millis)
conns.add(await conn)
# should throw adding a connection over the limit
expect TooManyConnectionsError:
discard await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track max incoming connection limits":
let connMngr = ConnManager.init(maxIn = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check await conn.withTimeout(10.millis)
conns.add(await conn)
# should timeout adding a connection over the limit
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check not(await conn.withTimeout(10.millis))
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track max outgoing connection limits":
let connMngr = ConnManager.init(maxOut = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
conns.add(conn)
# should throw adding a connection over the limit
expect TooManyConnectionsError:
discard await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track incoming max connections limits - fail on incoming":
let connMngr = ConnManager.init(maxOut = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
conns.add(conn)
# should timeout adding a connection over the limit
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check not(await conn.withTimeout(10.millis))
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))
asyncTest "track incoming max connections limits - fail on outgoing":
let connMngr = ConnManager.init(maxIn = 3)
var conns: seq[Connection]
for i in 0..<3:
let conn = connMngr.trackIncomingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
check await conn.withTimeout(10.millis)
conns.add(await conn)
# should throw adding a connection over the limit
expect TooManyConnectionsError:
discard await connMngr.trackOutgoingConn(
proc(): Future[Connection] {.async.} =
return Connection.init(
PeerInfo.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()),
Direction.In)
)
await connMngr.close()
await allFuturesThrowing(
allFutures(conns.mapIt( it.close() )))

View File

@ -741,3 +741,115 @@ suite "Switch":
expect(DialFailedError):
let conn = await switch2.dial(somePeer, TestCodec)
await switch2.stop()
asyncTest "e2e total connection limits on incoming connections":
var awaiters: seq[Future[void]]
var switches: seq[Switch]
let destSwitch = newStandardSwitch(maxConnections = 3)
switches.add(destSwitch)
awaiters.add(await destSwitch.start())
let destPeerInfo = destSwitch.peerInfo
for i in 0..<3:
let switch = newStandardSwitch()
switches.add(switch)
awaiters.add(await switch.start())
check await switch.connect(destPeerInfo)
.withTimeout(100.millis)
let switchFail = newStandardSwitch()
switches.add(switchFail)
awaiters.add(await switchFail.start())
check not(await switchFail.connect(destPeerInfo)
.withTimeout(100.millis))
await allFuturesThrowing(
allFutures(switches.mapIt( it.stop() )))
await allFuturesThrowing(awaiters)
asyncTest "e2e total connection limits on incoming connections":
var awaiters: seq[Future[void]]
var switches: seq[Switch]
for i in 0..<3:
switches.add(newStandardSwitch())
awaiters.add(await switches[i].start())
let srcSwitch = newStandardSwitch(maxConnections = 3)
awaiters.add(await srcSwitch.start())
let dstSwitch = newStandardSwitch()
awaiters.add(await dstSwitch.start())
for s in switches:
check await srcSwitch.connect(s.peerInfo)
.withTimeout(100.millis)
expect TooManyConnectionsError:
await srcSwitch.connect(dstSwitch.peerInfo)
switches.add(srcSwitch)
switches.add(dstSwitch)
await allFuturesThrowing(
allFutures(switches.mapIt( it.stop() )))
await allFuturesThrowing(awaiters)
asyncTest "e2e max incoming connection limits":
var awaiters: seq[Future[void]]
var switches: seq[Switch]
let destSwitch = newStandardSwitch(maxIn = 3)
switches.add(destSwitch)
awaiters.add(await destSwitch.start())
let destPeerInfo = destSwitch.peerInfo
for i in 0..<3:
let switch = newStandardSwitch()
switches.add(switch)
awaiters.add(await switch.start())
check await switch.connect(destPeerInfo)
.withTimeout(100.millis)
let switchFail = newStandardSwitch()
switches.add(switchFail)
awaiters.add(await switchFail.start())
check not(await switchFail.connect(destPeerInfo)
.withTimeout(100.millis))
await allFuturesThrowing(
allFutures(switches.mapIt( it.stop() )))
await allFuturesThrowing(awaiters)
asyncTest "e2e max outgoing connection limits":
var awaiters: seq[Future[void]]
var switches: seq[Switch]
for i in 0..<3:
switches.add(newStandardSwitch())
awaiters.add(await switches[i].start())
let srcSwitch = newStandardSwitch(maxOut = 3)
awaiters.add(await srcSwitch.start())
let dstSwitch = newStandardSwitch()
awaiters.add(await dstSwitch.start())
for s in switches:
check await srcSwitch.connect(s.peerInfo)
.withTimeout(100.millis)
expect TooManyConnectionsError:
await srcSwitch.connect(dstSwitch.peerInfo)
switches.add(srcSwitch)
switches.add(dstSwitch)
await allFuturesThrowing(
allFutures(switches.mapIt( it.stop() )))
await allFuturesThrowing(awaiters)