2020-01-07 08:06:27 +00:00
|
|
|
import unittest, tables
|
2019-12-04 04:44:54 +00:00
|
|
|
import chronos
|
2020-03-26 06:06:47 +00:00
|
|
|
import chronicles
|
|
|
|
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-04-21 01:24:42 +00:00
|
|
|
stream/bufferstream,
|
2019-10-29 18:51:48 +00:00
|
|
|
protocols/identify,
|
2019-09-30 15:48:40 +00:00
|
|
|
connection,
|
|
|
|
transports/transport,
|
|
|
|
transports/tcptransport,
|
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,
|
2019-09-30 15:48:40 +00:00
|
|
|
peer,
|
2019-10-29 18:51:48 +00:00
|
|
|
protocols/protocol,
|
2019-09-30 15:48:40 +00:00
|
|
|
muxers/muxer,
|
2019-10-29 18:51:48 +00:00
|
|
|
muxers/mplex/mplex,
|
2019-09-30 15:48:40 +00:00
|
|
|
muxers/mplex/types,
|
|
|
|
protocols/secure/secio,
|
2020-03-27 14:25:52 +00:00
|
|
|
protocols/secure/secure,
|
|
|
|
stream/lpstream]
|
2019-08-31 17:58:49 +00:00
|
|
|
|
2019-10-29 18:51:48 +00:00
|
|
|
when defined(nimHasUsed): {.used.}
|
|
|
|
|
2020-04-21 01:24:42 +00:00
|
|
|
const
|
|
|
|
TestCodec = "/test/proto/1.0.0"
|
|
|
|
StreamTransportTrackerName = "stream.transport"
|
|
|
|
StreamServerTrackerName = "stream.server"
|
2019-08-31 17:58:49 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TestProto = ref object of LPProtocol
|
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
proc createSwitch(ma: MultiAddress): (Switch, PeerInfo) =
|
|
|
|
var peerInfo: PeerInfo = PeerInfo.init(PrivateKey.random(RSA))
|
|
|
|
peerInfo.addrs.add(ma)
|
|
|
|
let identify = newIdentify(peerInfo)
|
|
|
|
|
|
|
|
proc createMplex(conn: Connection): Muxer =
|
|
|
|
result = newMplex(conn)
|
|
|
|
|
|
|
|
let mplexProvider = newMuxerProvider(createMplex, MplexCodec)
|
|
|
|
let transports = @[Transport(newTransport(TcpTransport))]
|
|
|
|
let muxers = [(MplexCodec, mplexProvider)].toTable()
|
|
|
|
let secureManagers = [(SecioCodec, Secure(newSecio(peerInfo.privateKey)))].toTable()
|
|
|
|
let switch = newSwitch(peerInfo,
|
2020-02-12 14:43:42 +00:00
|
|
|
transports,
|
|
|
|
identify,
|
|
|
|
muxers,
|
|
|
|
secureManagers)
|
2019-12-23 18:44:51 +00:00
|
|
|
result = (switch, peerInfo)
|
2019-09-04 22:00:39 +00:00
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
suite "Switch":
|
2020-04-21 01:24:42 +00:00
|
|
|
teardown:
|
|
|
|
let
|
|
|
|
trackers = [
|
|
|
|
# getTracker(ConnectionTrackerName),
|
|
|
|
getTracker(BufferStreamTrackerName),
|
|
|
|
getTracker(AsyncStreamWriterTrackerName),
|
|
|
|
getTracker(TcpTransportTrackerName),
|
|
|
|
getTracker(AsyncStreamReaderTrackerName),
|
|
|
|
getTracker(StreamTransportTrackerName),
|
|
|
|
getTracker(StreamServerTrackerName)
|
|
|
|
]
|
|
|
|
for tracker in trackers:
|
|
|
|
if not isNil(tracker):
|
|
|
|
# echo tracker.dump()
|
|
|
|
check tracker.isLeaked() == false
|
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
test "e2e use switch dial proto string":
|
2019-08-31 17:58:49 +00:00
|
|
|
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
2019-09-30 15:48:40 +00:00
|
|
|
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
|
|
|
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
2019-10-29 18:51:48 +00:00
|
|
|
|
2019-08-31 17:58:49 +00:00
|
|
|
var peerInfo1, peerInfo2: PeerInfo
|
|
|
|
var switch1, switch2: Switch
|
2020-02-12 14:43:42 +00:00
|
|
|
var awaiters: seq[Future[void]]
|
|
|
|
|
2019-08-31 17:58:49 +00:00
|
|
|
(switch1, peerInfo1) = createSwitch(ma1)
|
2019-09-05 15:19:39 +00:00
|
|
|
|
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.} =
|
|
|
|
let msg = cast[string](await conn.readLp())
|
|
|
|
check "Hello!" == msg
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
await conn.close()
|
2020-04-21 01:24:42 +00:00
|
|
|
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
|
2019-08-31 17:58:49 +00:00
|
|
|
switch1.mount(testProto)
|
2020-03-27 14:25:52 +00:00
|
|
|
|
2019-08-31 17:58:49 +00:00
|
|
|
(switch2, peerInfo2) = createSwitch(ma2)
|
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-03-27 14:25:52 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
let msg = cast[string](await conn.readLp())
|
|
|
|
check "Hello!" == msg
|
|
|
|
result = true
|
|
|
|
except LPStreamError:
|
|
|
|
result = false
|
2019-08-31 17:58:49 +00:00
|
|
|
|
2020-04-21 01:24:42 +00:00
|
|
|
await allFuturesThrowing(
|
|
|
|
done.wait(5000.millis) #[if OK won't happen!!]#,
|
|
|
|
conn.close(),
|
|
|
|
switch1.stop(),
|
|
|
|
switch2.stop(),
|
|
|
|
)
|
|
|
|
|
|
|
|
# this needs to go at end
|
|
|
|
await allFuturesThrowing(awaiters)
|
2019-08-31 17:58:49 +00:00
|
|
|
|
|
|
|
check:
|
|
|
|
waitFor(testSwitch()) == true
|
2019-12-23 18:44:51 +00:00
|
|
|
|
|
|
|
test "e2e use switch no proto string":
|
|
|
|
proc testSwitch(): Future[bool] {.async, gcsafe.} =
|
|
|
|
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
|
|
|
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
|
|
|
|
|
|
|
var peerInfo1, peerInfo2: PeerInfo
|
|
|
|
var switch1, switch2: Switch
|
2020-01-07 08:06:27 +00:00
|
|
|
var awaiters: seq[Future[void]]
|
2019-12-23 18:44:51 +00:00
|
|
|
|
2020-02-25 22:13:05 +00:00
|
|
|
(switch1, peerInfo1) = createSwitch(ma1)
|
|
|
|
|
2020-03-27 14:25:52 +00:00
|
|
|
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
|
|
|
|
let msg = cast[string](await conn.readLp())
|
|
|
|
check "Hello!" == msg
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
await conn.close()
|
|
|
|
|
2020-02-25 22:13:05 +00:00
|
|
|
let testProto = new TestProto
|
|
|
|
testProto.codec = TestCodec
|
2020-03-27 14:25:52 +00:00
|
|
|
testProto.handler = handle
|
2020-02-25 22:13:05 +00:00
|
|
|
switch1.mount(testProto)
|
2020-03-27 14:25:52 +00:00
|
|
|
|
2019-12-23 18:44:51 +00:00
|
|
|
(switch2, peerInfo2) = createSwitch(ma2)
|
2020-02-25 22:13:05 +00:00
|
|
|
awaiters.add(await switch1.start())
|
2020-01-07 08:06:27 +00:00
|
|
|
awaiters.add(await switch2.start())
|
2020-02-25 22:13:05 +00:00
|
|
|
await switch2.connect(switch1.peerInfo)
|
|
|
|
let conn = await switch2.dial(switch1.peerInfo, TestCodec)
|
2020-03-27 14:25:52 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
await conn.writeLp("Hello!")
|
|
|
|
let msg = cast[string](await conn.readLp())
|
|
|
|
check "Hello!" == msg
|
|
|
|
result = true
|
|
|
|
except LPStreamError:
|
|
|
|
result = false
|
2019-12-23 18:44:51 +00:00
|
|
|
|
2020-04-21 01:24:42 +00:00
|
|
|
await allFuturesThrowing(
|
|
|
|
conn.close(),
|
|
|
|
switch1.stop(),
|
|
|
|
switch2.stop()
|
|
|
|
)
|
|
|
|
await allFuturesThrowing(awaiters)
|
2019-12-23 18:44:51 +00:00
|
|
|
|
|
|
|
check:
|
2020-03-26 06:06:47 +00:00
|
|
|
waitFor(testSwitch()) == true
|
|
|
|
|
2020-03-27 01:47:30 +00:00
|
|
|
# test "e2e: handle read + secio fragmented":
|
|
|
|
# proc testListenerDialer(): Future[bool] {.async.} =
|
|
|
|
# let
|
|
|
|
# server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
|
|
|
|
# serverInfo = PeerInfo.init(PrivateKey.random(RSA), [server])
|
|
|
|
# serverNoise = newSecio(serverInfo.privateKey)
|
|
|
|
# readTask = newFuture[void]()
|
|
|
|
|
|
|
|
# var hugePayload = newSeq[byte](0x1200000)
|
|
|
|
# check randomBytes(hugePayload) == hugePayload.len
|
|
|
|
# trace "Sending huge payload", size = hugePayload.len
|
|
|
|
|
|
|
|
# proc connHandler(conn: Connection) {.async, gcsafe.} =
|
|
|
|
# let sconn = await serverNoise.secure(conn)
|
|
|
|
# defer:
|
|
|
|
# await sconn.close()
|
|
|
|
# let msg = await sconn.read(0x1200000)
|
|
|
|
# check msg == hugePayload
|
|
|
|
# readTask.complete()
|
|
|
|
|
|
|
|
# let
|
|
|
|
# transport1: TcpTransport = newTransport(TcpTransport)
|
|
|
|
# asyncCheck await transport1.listen(server, connHandler)
|
|
|
|
|
|
|
|
# let
|
|
|
|
# transport2: TcpTransport = newTransport(TcpTransport)
|
|
|
|
# clientInfo = PeerInfo.init(PrivateKey.random(RSA), [transport1.ma])
|
|
|
|
# clientNoise = newSecio(clientInfo.privateKey)
|
|
|
|
# conn = await transport2.dial(transport1.ma)
|
|
|
|
# sconn = await clientNoise.secure(conn)
|
|
|
|
|
|
|
|
# await sconn.write(hugePayload)
|
|
|
|
# await readTask
|
2020-04-21 01:24:42 +00:00
|
|
|
|
2020-03-27 01:47:30 +00:00
|
|
|
# await sconn.close()
|
2020-04-21 01:24:42 +00:00
|
|
|
# await conn.close()
|
|
|
|
# await transport2.close()
|
2020-03-27 01:47:30 +00:00
|
|
|
# await transport1.close()
|
|
|
|
|
|
|
|
# result = true
|
|
|
|
|
|
|
|
# check:
|
|
|
|
# waitFor(testListenerDialer()) == true
|