2020-05-08 20:10:06 +00:00
|
|
|
{.used.}
|
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
import unittest
|
2019-12-04 04:44:54 +00:00
|
|
|
import chronos
|
2020-05-23 19:26:25 +00:00
|
|
|
import stew/byteutils
|
2020-03-26 06:06:47 +00:00
|
|
|
import nimcrypto/sysrand
|
2020-04-21 01:24:42 +00:00
|
|
|
import ../libp2p/[errors,
|
|
|
|
switch,
|
2019-09-30 15:48:40 +00:00
|
|
|
multistream,
|
2020-05-23 19:26:25 +00:00
|
|
|
standard_setup,
|
2020-04-21 01:24:42 +00:00
|
|
|
stream/bufferstream,
|
2020-06-19 17:29:43 +00:00
|
|
|
stream/connection,
|
2019-10-29 18:51:48 +00:00
|
|
|
multiaddress,
|
2019-09-30 15:48:40 +00:00
|
|
|
peerinfo,
|
2019-10-29 18:51:48 +00:00
|
|
|
crypto/crypto,
|
|
|
|
protocols/protocol,
|
2019-09-30 15:48:40 +00:00
|
|
|
muxers/muxer,
|
2019-10-29 18:51:48 +00:00
|
|
|
muxers/mplex/mplex,
|
2020-03-27 14:25:52 +00:00
|
|
|
stream/lpstream]
|
2020-05-08 20:10:06 +00:00
|
|
|
import ./helpers
|
2019-10-29 18:51:48 +00:00
|
|
|
|
2020-04-21 01:24:42 +00:00
|
|
|
const
|
|
|
|
TestCodec = "/test/proto/1.0.0"
|
2019-08-31 17:58:49 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TestProto = ref object of LPProtocol
|
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
suite "Switch":
|
2020-04-21 01:24:42 +00:00
|
|
|
teardown:
|
2020-05-08 20:10:06 +00:00
|
|
|
for tracker in testTrackers():
|
2020-05-18 13:49:49 +00:00
|
|
|
# echo tracker.dump()
|
2020-05-08 20:10:06 +00:00
|
|
|
check tracker.isLeaked() == false
|
2020-04-21 01:24:42 +00:00
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
test "e2e use switch dial proto string":
|
2020-05-25 14:40:39 +00:00
|
|
|
proc testSwitch() {.async, gcsafe.} =
|
|
|
|
let done = newFuture[void]()
|
|
|
|
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
|
|
|
try:
|
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
|
|
|
check "Hello!" == msg
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
finally:
|
|
|
|
await conn.close()
|
|
|
|
done.complete()
|
|
|
|
|
|
|
|
let testProto = new TestProto
|
|
|
|
testProto.codec = TestCodec
|
|
|
|
testProto.handler = handle
|
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Noise])
|
2020-05-25 14:40:39 +00:00
|
|
|
switch1.mount(testProto)
|
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Noise])
|
2020-05-25 14:40:39 +00:00
|
|
|
var awaiters: seq[Future[void]]
|
|
|
|
awaiters.add(await switch1.start())
|
|
|
|
awaiters.add(await switch2.start())
|
|
|
|
|
|
|
|
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
2020-07-17 15:36:48 +00:00
|
|
|
|
|
|
|
check switch1.isConnected(switch2.peerInfo)
|
|
|
|
check switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-25 14:40:39 +00:00
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
|
|
|
check "Hello!" == msg
|
|
|
|
await conn.close()
|
|
|
|
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(
|
|
|
|
done.wait(5.seconds),
|
2020-05-25 14:40:39 +00:00
|
|
|
switch1.stop(),
|
2020-06-02 23:53:38 +00:00
|
|
|
switch2.stop())
|
2020-05-25 14:40:39 +00:00
|
|
|
|
|
|
|
# this needs to go at end
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(awaiters)
|
2020-05-25 14:40:39 +00:00
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
check not switch1.isConnected(switch2.peerInfo)
|
|
|
|
check not switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-25 14:40:39 +00:00
|
|
|
waitFor(testSwitch())
|
|
|
|
|
|
|
|
test "e2e should not leak bufferstreams and connections on channel close":
|
2020-05-20 00:14:15 +00:00
|
|
|
proc testSwitch() {.async, gcsafe.} =
|
2020-04-21 01:24:42 +00:00
|
|
|
let done = newFuture[void]()
|
2020-03-27 14:25:52 +00:00
|
|
|
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
2020-05-23 19:26:25 +00:00
|
|
|
try:
|
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
|
|
|
check "Hello!" == msg
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
finally:
|
|
|
|
await conn.close()
|
|
|
|
done.complete()
|
2020-03-27 14:25:52 +00:00
|
|
|
|
2019-09-04 22:00:39 +00:00
|
|
|
let testProto = new TestProto
|
|
|
|
testProto.codec = TestCodec
|
2020-03-27 14:25:52 +00:00
|
|
|
testProto.handler = handle
|
2020-05-23 19:26:25 +00:00
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
2019-08-31 17:58:49 +00:00
|
|
|
switch1.mount(testProto)
|
2020-03-27 14:25:52 +00:00
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
2020-05-23 19:26:25 +00:00
|
|
|
var awaiters: seq[Future[void]]
|
2020-02-12 14:43:42 +00:00
|
|
|
awaiters.add(await switch1.start())
|
2020-01-07 08:06:27 +00:00
|
|
|
awaiters.add(await switch2.start())
|
2020-03-27 14:25:52 +00:00
|
|
|
|
2019-09-30 15:48:40 +00:00
|
|
|
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
2020-07-17 15:36:48 +00:00
|
|
|
|
|
|
|
check switch1.isConnected(switch2.peerInfo)
|
|
|
|
check switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-20 00:14:15 +00:00
|
|
|
await conn.writeLp("Hello!")
|
2020-05-23 19:26:25 +00:00
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
2020-05-20 00:14:15 +00:00
|
|
|
check "Hello!" == msg
|
2020-05-23 19:26:25 +00:00
|
|
|
await conn.close()
|
|
|
|
|
|
|
|
await sleepAsync(2.seconds) # wait a little for cleanup to happen
|
|
|
|
var bufferTracker = getTracker(BufferStreamTrackerName)
|
2020-07-17 18:44:41 +00:00
|
|
|
# echo bufferTracker.dump()
|
2020-05-23 19:26:25 +00:00
|
|
|
|
|
|
|
# plus 4 for the pubsub streams
|
|
|
|
check (BufferStreamTracker(bufferTracker).opened ==
|
2020-08-12 00:05:49 +00:00
|
|
|
(BufferStreamTracker(bufferTracker).closed))
|
2020-05-23 19:26:25 +00:00
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
var connTracker = getTracker(ConnectionTrackerName)
|
2020-07-17 18:44:41 +00:00
|
|
|
# echo connTracker.dump()
|
2020-05-23 19:26:25 +00:00
|
|
|
|
|
|
|
# plus 8 is for the secured connection and the socket
|
|
|
|
# and the pubsub streams that won't clean up until
|
|
|
|
# `disconnect()` or `stop()`
|
2020-07-17 15:36:48 +00:00
|
|
|
check (ConnectionTracker(connTracker).opened ==
|
2020-08-12 00:05:49 +00:00
|
|
|
(ConnectionTracker(connTracker).closed + 4.uint64))
|
2019-08-31 17:58:49 +00:00
|
|
|
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(
|
|
|
|
done.wait(5.seconds),
|
2020-04-21 01:24:42 +00:00
|
|
|
switch1.stop(),
|
|
|
|
switch2.stop(),
|
|
|
|
)
|
|
|
|
|
|
|
|
# this needs to go at end
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(awaiters)
|
2019-08-31 17:58:49 +00:00
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
check not switch1.isConnected(switch2.peerInfo)
|
|
|
|
check not switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-20 00:14:15 +00:00
|
|
|
waitFor(testSwitch())
|
2019-12-23 18:44:51 +00:00
|
|
|
|
2020-05-23 19:26:25 +00:00
|
|
|
test "e2e use connect then dial":
|
2020-05-14 15:19:03 +00:00
|
|
|
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
|
|
|
var awaiters: seq[Future[void]]
|
|
|
|
|
|
|
|
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
2020-05-23 19:26:25 +00:00
|
|
|
try:
|
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
|
|
|
check "Hello!" == msg
|
|
|
|
finally:
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
await conn.close()
|
2020-05-14 15:19:03 +00:00
|
|
|
|
|
|
|
let testProto = new TestProto
|
|
|
|
testProto.codec = TestCodec
|
|
|
|
testProto.handler = handle
|
2020-05-23 19:26:25 +00:00
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Noise])
|
2020-05-14 15:19:03 +00:00
|
|
|
switch1.mount(testProto)
|
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Noise])
|
2020-05-14 15:19:03 +00:00
|
|
|
awaiters.add(await switch1.start())
|
|
|
|
awaiters.add(await switch2.start())
|
2020-05-23 19:26:25 +00:00
|
|
|
|
2020-05-14 15:19:03 +00:00
|
|
|
await switch2.connect(switch1.peerInfo)
|
|
|
|
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
check switch1.isConnected(switch2.peerInfo)
|
|
|
|
check switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-14 15:19:03 +00:00
|
|
|
try:
|
|
|
|
await conn.writeLp("Hello!")
|
2020-05-23 19:26:25 +00:00
|
|
|
let msg = string.fromBytes(await conn.readLp(1024))
|
2020-05-14 15:19:03 +00:00
|
|
|
check "Hello!" == msg
|
|
|
|
result = true
|
|
|
|
except LPStreamError:
|
|
|
|
result = false
|
|
|
|
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(
|
2020-05-14 15:19:03 +00:00
|
|
|
conn.close(),
|
|
|
|
switch1.stop(),
|
|
|
|
switch2.stop()
|
|
|
|
)
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(awaiters)
|
2020-05-14 15:19:03 +00:00
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
check not switch1.isConnected(switch2.peerInfo)
|
|
|
|
check not switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-14 15:19:03 +00:00
|
|
|
check:
|
|
|
|
waitFor(testSwitch()) == true
|
2020-03-26 06:06:47 +00:00
|
|
|
|
2020-05-23 19:26:25 +00:00
|
|
|
test "e2e should not leak on peer disconnect":
|
|
|
|
proc testSwitch() {.async, gcsafe.} =
|
|
|
|
var awaiters: seq[Future[void]]
|
|
|
|
|
2020-06-20 10:56:55 +00:00
|
|
|
let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
|
|
|
let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
2020-05-23 19:26:25 +00:00
|
|
|
awaiters.add(await switch1.start())
|
|
|
|
awaiters.add(await switch2.start())
|
2020-06-19 17:29:43 +00:00
|
|
|
|
2020-05-23 19:26:25 +00:00
|
|
|
await switch2.connect(switch1.peerInfo)
|
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
check switch1.isConnected(switch2.peerInfo)
|
|
|
|
check switch2.isConnected(switch1.peerInfo)
|
2020-06-02 17:32:42 +00:00
|
|
|
|
2020-05-23 19:26:25 +00:00
|
|
|
await sleepAsync(100.millis)
|
|
|
|
await switch2.disconnect(switch1.peerInfo)
|
|
|
|
await sleepAsync(2.seconds)
|
2020-07-17 15:36:48 +00:00
|
|
|
|
|
|
|
check not switch1.isConnected(switch2.peerInfo)
|
|
|
|
check not switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
2020-05-23 19:26:25 +00:00
|
|
|
var bufferTracker = getTracker(BufferStreamTrackerName)
|
|
|
|
# echo bufferTracker.dump()
|
|
|
|
check bufferTracker.isLeaked() == false
|
|
|
|
|
2020-07-17 15:36:48 +00:00
|
|
|
var connTracker = getTracker(ConnectionTrackerName)
|
2020-05-23 19:26:25 +00:00
|
|
|
# echo connTracker.dump()
|
2020-07-17 15:36:48 +00:00
|
|
|
check connTracker.isLeaked() == false
|
2020-06-02 17:32:42 +00:00
|
|
|
|
2020-06-02 23:53:38 +00:00
|
|
|
await allFuturesThrowing(
|
2020-05-23 19:26:25 +00:00
|
|
|
switch1.stop(),
|
2020-06-02 23:53:38 +00:00
|
|
|
switch2.stop())
|
|
|
|
await allFuturesThrowing(awaiters)
|
2020-05-23 19:26:25 +00:00
|
|
|
|
|
|
|
waitFor(testSwitch())
|
2020-07-24 19:24:31 +00:00
|
|
|
|
|
|
|
test "e2e should trigger hooks":
|
|
|
|
proc testSwitch() {.async, gcsafe.} =
|
|
|
|
var awaiters: seq[Future[void]]
|
|
|
|
|
|
|
|
let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
|
|
|
let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Secio])
|
|
|
|
|
|
|
|
var step = 0
|
2020-08-08 06:52:20 +00:00
|
|
|
var kinds: set[ConnEventKind]
|
|
|
|
proc hook(peerId: PeerID, event: ConnEvent) {.async, gcsafe.} =
|
|
|
|
kinds = kinds + {event.kind}
|
2020-07-24 19:24:31 +00:00
|
|
|
case step:
|
|
|
|
of 0:
|
|
|
|
check:
|
2020-08-08 06:52:20 +00:00
|
|
|
event.kind == ConnEventKind.Connected
|
|
|
|
peerId == switch2.peerInfo.peerId
|
|
|
|
of 1:
|
2020-07-24 19:24:31 +00:00
|
|
|
check:
|
2020-08-08 06:52:20 +00:00
|
|
|
event.kind == ConnEventKind.Disconnected
|
2020-07-24 19:24:31 +00:00
|
|
|
|
2020-08-08 06:52:20 +00:00
|
|
|
check peerId == switch2.peerInfo.peerId
|
2020-07-24 19:24:31 +00:00
|
|
|
else:
|
|
|
|
check false
|
|
|
|
|
|
|
|
step.inc()
|
|
|
|
|
2020-08-08 06:52:20 +00:00
|
|
|
switch1.addConnEventHandler(hook, ConnEventKind.Connected)
|
|
|
|
switch1.addConnEventHandler(hook, ConnEventKind.Disconnected)
|
2020-07-24 19:24:31 +00:00
|
|
|
|
|
|
|
awaiters.add(await switch1.start())
|
|
|
|
awaiters.add(await switch2.start())
|
|
|
|
|
|
|
|
await switch2.connect(switch1.peerInfo)
|
|
|
|
|
|
|
|
check switch1.isConnected(switch2.peerInfo)
|
|
|
|
check switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
|
|
|
await sleepAsync(100.millis)
|
|
|
|
await switch2.disconnect(switch1.peerInfo)
|
|
|
|
await sleepAsync(2.seconds)
|
|
|
|
|
|
|
|
check not switch1.isConnected(switch2.peerInfo)
|
|
|
|
check not switch2.isConnected(switch1.peerInfo)
|
|
|
|
|
|
|
|
var bufferTracker = getTracker(BufferStreamTrackerName)
|
|
|
|
# echo bufferTracker.dump()
|
|
|
|
check bufferTracker.isLeaked() == false
|
|
|
|
|
|
|
|
var connTracker = getTracker(ConnectionTrackerName)
|
|
|
|
# echo connTracker.dump()
|
|
|
|
check connTracker.isLeaked() == false
|
|
|
|
|
|
|
|
check:
|
2020-08-08 06:52:20 +00:00
|
|
|
kinds == {
|
|
|
|
ConnEventKind.Connected,
|
|
|
|
ConnEventKind.Disconnected
|
2020-07-24 19:24:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
await allFuturesThrowing(
|
|
|
|
switch1.stop(),
|
|
|
|
switch2.stop())
|
|
|
|
await allFuturesThrowing(awaiters)
|
|
|
|
|
|
|
|
waitFor(testSwitch())
|