mirror of https://github.com/status-im/nim-eth.git
Remove unused mock_peers and tserver files (#540)
This commit is contained in:
parent
4c821c5eae
commit
3e44299b49
|
@ -1,217 +0,0 @@
|
|||
import
|
||||
std/[macros, deques, algorithm],
|
||||
chronos,
|
||||
".."/[keys, rlp, p2p], ../common/eth_types,
|
||||
./private/p2p_types, ./rlpx
|
||||
|
||||
type
|
||||
Action = proc (p: Peer, data: Rlp): Future[void] {.gcsafe.}
|
||||
|
||||
ProtocolMessagePair = object
|
||||
protocol: ProtocolInfo
|
||||
id: int
|
||||
|
||||
ExpectedMsg = object
|
||||
msg: ProtocolMessagePair
|
||||
response: Action
|
||||
|
||||
MockConf* = ref object
|
||||
keys*: KeyPair
|
||||
address*: Address
|
||||
networkId*: uint
|
||||
chain*: AbstractChainDB
|
||||
clientId*: string
|
||||
waitForHello*: bool
|
||||
|
||||
devp2pHandshake: ExpectedMsg
|
||||
handshakes: seq[ExpectedMsg]
|
||||
protocols: seq[ProtocolInfo]
|
||||
|
||||
expectedMsgs: Deque[ExpectedMsg]
|
||||
receivedMsgsCount: int
|
||||
when useSnappy:
|
||||
useCompression*: bool
|
||||
|
||||
var
|
||||
nextUnusedMockPort = 40304
|
||||
|
||||
proc toAction(a: Action): Action = a
|
||||
|
||||
proc toAction[N](actions: array[N, Action]): Action =
|
||||
mixin await
|
||||
result = proc (peer: Peer, data: Rlp) {.async.} =
|
||||
for a in actions:
|
||||
await a(peer, data)
|
||||
|
||||
proc toAction(a: proc (): Future[void]): Action =
|
||||
result = proc (peer: Peer, data: Rlp) {.async.} =
|
||||
await a()
|
||||
|
||||
proc toAction(a: proc (peer: Peer): Future[void]): Action =
|
||||
result = proc (peer: Peer, data: Rlp) {.async.} =
|
||||
await a(peer)
|
||||
|
||||
proc delay*(duration: int): Action =
|
||||
result = proc (p: Peer, data: Rlp) {.async.} =
|
||||
await sleepAsync(duration)
|
||||
|
||||
proc reply(bytes: Bytes): Action =
|
||||
result = proc (p: Peer, data: Rlp) {.async.} =
|
||||
await p.sendMsg(bytes)
|
||||
|
||||
proc reply*[Msg](msg: Msg): Action =
|
||||
mixin await
|
||||
result = proc (p: Peer, data: Rlp) {.async.} =
|
||||
await p.send(msg)
|
||||
|
||||
proc localhostAddress*(port: int): Address =
|
||||
let port = Port(port)
|
||||
result = Address(udpPort: port, tcpPort: port, ip: parseIpAddress("127.0.0.1"))
|
||||
|
||||
proc makeProtoMsgPair(MsgType: type): ProtocolMessagePair =
|
||||
mixin msgProtocol, protocolInfo
|
||||
result.protocol = MsgType.msgProtocol.protocolInfo
|
||||
result.id = MsgType.msgId
|
||||
|
||||
proc readReqId*(rlp: Rlp): int =
|
||||
var r = rlp
|
||||
return r.read(int)
|
||||
|
||||
proc expectationViolationMsg(mock: MockConf,
|
||||
reason: string,
|
||||
receivedMsg: ptr MessageInfo): string =
|
||||
result = "[Mock expectation violated] " & reason & ": " & receivedMsg.name
|
||||
for i in 0 ..< mock.expectedMsgs.len:
|
||||
let expected = mock.expectedMsgs[i].msg
|
||||
result.add "\n " & expected.protocol.messages[expected.id].name
|
||||
if i == mock.receivedMsgsCount: result.add " <- we are here"
|
||||
result.add "\n"
|
||||
|
||||
proc addProtocol(mock: MockConf, p: ProtocolInfo): ProtocolInfo =
|
||||
result = create ProtocolInfoObj
|
||||
deepCopy(result[], p[])
|
||||
|
||||
proc incomingMsgHandler(p: Peer, receivedMsgId: int, rlp: Rlp): Future[void] {.gcsafe.} =
|
||||
let (receivedMsgProto, receivedMsgInfo) = p.getMsgMetadata(receivedMsgId)
|
||||
let expectedMsgIdx = mock.receivedMsgsCount
|
||||
|
||||
template fail(reason: string) =
|
||||
stdout.write mock.expectationViolationMsg(reason, receivedMsgInfo)
|
||||
quit 1
|
||||
|
||||
if expectedMsgIdx > mock.expectedMsgs.len:
|
||||
fail "Mock peer received more messages than expected"
|
||||
|
||||
let expectedMsg = mock.expectedMsgs[expectedMsgIdx]
|
||||
if receivedMsgInfo.id != expectedMsg.msg.id or
|
||||
receivedMsgProto.name != expectedMsg.msg.protocol.name:
|
||||
fail "Mock peer received an unexpected message"
|
||||
|
||||
inc mock.receivedMsgsCount
|
||||
if expectedMsg.response != nil:
|
||||
return expectedMsg.response(p, rlp)
|
||||
else:
|
||||
result = newFuture[void]()
|
||||
result.complete()
|
||||
|
||||
for m in mitems(result.messages):
|
||||
m.thunk = incomingMsgHandler
|
||||
|
||||
result.handshake = nil
|
||||
|
||||
# TODO This mock conf can override this
|
||||
result.disconnectHandler = nil
|
||||
|
||||
mock.protocols.add result
|
||||
|
||||
proc addHandshake*(mock: MockConf, msg: auto) =
|
||||
var msgInfo = makeProtoMsgPair(msg.type)
|
||||
msgInfo.protocol = mock.addProtocol(msgInfo.protocol)
|
||||
let expectedMsg = ExpectedMsg(msg: msgInfo, response: reply(msg))
|
||||
|
||||
when msg is DevP2P.hello:
|
||||
devp2pHandshake = expectedMsg
|
||||
else:
|
||||
mock.handshakes.add expectedMsg
|
||||
|
||||
proc addCapability*(mock: MockConf, Protocol: type) =
|
||||
mixin defaultTestingHandshake, protocolInfo
|
||||
|
||||
when compiles(defaultTestingHandshake(Protocol)):
|
||||
mock.addHandshake(defaultTestingHandshake(Protocol))
|
||||
else:
|
||||
discard mock.addProtocol(Protocol.protocolInfo)
|
||||
|
||||
proc expectImpl(mock: MockConf, msg: ProtocolMessagePair, action: Action) =
|
||||
mock.expectedMsgs.addLast ExpectedMsg(msg: msg, response: action)
|
||||
|
||||
macro expect*(mock: MockConf, MsgType: type, handler: untyped = nil): untyped =
|
||||
if handler.kind in {nnkLambda, nnkDo}:
|
||||
handler.addPragma ident("async")
|
||||
|
||||
result = newCall(
|
||||
bindSym("expectImpl"),
|
||||
mock,
|
||||
newCall(bindSym"makeProtoMsgPair", MsgType.getType),
|
||||
newCall(bindSym"toAction", handler))
|
||||
|
||||
template compression(m: MockConf): bool =
|
||||
when useSnappy:
|
||||
m.useCompression
|
||||
else:
|
||||
false
|
||||
|
||||
proc newMockPeer*(userConfigurator: proc (m: MockConf)): EthereumNode =
|
||||
var mockConf = new MockConf
|
||||
mockConf.keys = KeyPair.random()[]
|
||||
mockConf.address = localhostAddress(nextUnusedMockPort)
|
||||
inc nextUnusedMockPort
|
||||
mockConf.networkId = 1'u
|
||||
mockConf.clientId = "Mock Peer"
|
||||
mockConf.waitForHello = true
|
||||
mockConf.expectedMsgs = initDeque[ExpectedMsg]()
|
||||
|
||||
userConfigurator(mockConf)
|
||||
|
||||
var node = newEthereumNode(mockConf.keys,
|
||||
mockConf.address,
|
||||
mockConf.networkId,
|
||||
mockConf.chain,
|
||||
mockConf.clientId,
|
||||
addAllCapabilities = false,
|
||||
mockConf.compression())
|
||||
|
||||
mockConf.handshakes.sort do (lhs, rhs: ExpectedMsg) -> int:
|
||||
# this is intentially sorted in reverse order, so we
|
||||
# can add them in the correct order below.
|
||||
return -cmp(lhs.msg.protocol.index, rhs.msg.protocol.index)
|
||||
|
||||
for h in mockConf.handshakes:
|
||||
mockConf.expectedMsgs.addFirst h
|
||||
|
||||
for p in mockConf.protocols:
|
||||
node.addCapability p
|
||||
|
||||
when false:
|
||||
# TODO: This part doesn't work correctly yet.
|
||||
# rlpx{Connect,Accept} control the handshake.
|
||||
if mockConf.devp2pHandshake.response != nil:
|
||||
mockConf.expectedMsgs.addFirst mockConf.devp2pHandshake
|
||||
else:
|
||||
proc sendHello(p: Peer, data: Rlp) {.async.} =
|
||||
await p.hello(devp2pVersion,
|
||||
mockConf.clientId,
|
||||
node.capabilities,
|
||||
uint(node.address.tcpPort),
|
||||
node.keys.pubkey.getRaw())
|
||||
|
||||
mockConf.expectedMsgs.addFirst ExpectedMsg(
|
||||
msg: makeProtoMsgPair(p2p.hello),
|
||||
response: sendHello)
|
||||
|
||||
node.startListening()
|
||||
return node
|
||||
|
||||
proc rlpxConnect*(node, otherNode: EthereumNode): Future[Peer] =
|
||||
let otherAsRemote = newNode(otherNode.toENode())
|
||||
return rlpx.rlpxConnect(node, otherAsRemote)
|
|
@ -1,141 +0,0 @@
|
|||
#
|
||||
# Ethereum P2P
|
||||
# (c) Copyright 2018
|
||||
# Status Research & Development GmbH
|
||||
#
|
||||
# Licensed under either of
|
||||
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
||||
# MIT license (LICENSE-MIT)
|
||||
|
||||
import
|
||||
std/[sequtils, strformat, options],
|
||||
testutils/unittests, chronicles, chronos,
|
||||
../../eth/[rlp, keys, p2p], ../../eth/p2p/mock_peers
|
||||
|
||||
const
|
||||
clientId = "nim-eth-p2p/0.0.1"
|
||||
|
||||
type
|
||||
AbcPeer = ref object
|
||||
peerName: string
|
||||
lastResponse: string
|
||||
|
||||
XyzPeer = ref object
|
||||
messages: int
|
||||
|
||||
AbcNetwork = ref object
|
||||
peers: seq[string]
|
||||
|
||||
p2pProtocol abc(version = 1,
|
||||
peerState = AbcPeer,
|
||||
networkState = AbcNetwork,
|
||||
timeout = 100):
|
||||
|
||||
onPeerConnected do (peer: Peer):
|
||||
await peer.hi "Bob"
|
||||
let response = await peer.nextMsg(abc.hi)
|
||||
peer.networkState.peers.add response.name
|
||||
|
||||
onPeerDisconnected do (peer: Peer, reason: DisconnectionReason):
|
||||
echo "peer disconnected", peer
|
||||
|
||||
requestResponse:
|
||||
proc abcReq(p: Peer, n: int) =
|
||||
echo "got req ", n
|
||||
await response.send(&"response to #{n}")
|
||||
|
||||
proc abcRes(p: Peer, data: string) =
|
||||
echo "got response ", data
|
||||
|
||||
proc hi(p: Peer, name: string) =
|
||||
echo "got hi from ", name
|
||||
p.state.peerName = name
|
||||
let query = 123
|
||||
echo "sending req #", query
|
||||
var r = await p.abcReq(query)
|
||||
if r.isSome:
|
||||
p.state.lastResponse = r.get.data
|
||||
else:
|
||||
p.state.lastResponse = "timeout"
|
||||
|
||||
p2pProtocol xyz(version = 1,
|
||||
peerState = XyzPeer,
|
||||
useRequestIds = false,
|
||||
timeout = 100):
|
||||
|
||||
proc foo(p: Peer, s: string, a, z: int) =
|
||||
p.state.messages += 1
|
||||
if p.supports(abc):
|
||||
echo p.state(abc).peerName
|
||||
|
||||
proc bar(p: Peer, i: int, s: string)
|
||||
|
||||
requestResponse:
|
||||
proc xyzReq(p: Peer, n: int, timeout = 3.seconds) =
|
||||
echo "got req ", n
|
||||
|
||||
proc xyzRes(p: Peer, data: string) =
|
||||
echo "got response ", data
|
||||
|
||||
proc defaultTestingHandshake(_: type abc): abc.hi =
|
||||
result.name = "John Doe"
|
||||
|
||||
proc localAddress(port: int): Address =
|
||||
let port = Port(port)
|
||||
result = Address(udpPort: port, tcpPort: port, ip: parseIpAddress("127.0.0.1"))
|
||||
|
||||
template asyncTest(name, body: untyped) =
|
||||
test name:
|
||||
proc scenario {.async.} = body
|
||||
waitFor scenario()
|
||||
|
||||
template sendResponseWithId(peer: Peer, proto, msg: untyped, reqId: int, data: varargs[untyped]): auto =
|
||||
msg(ResponseWithId[proto.msg](peer: peer, id: reqId), data)
|
||||
|
||||
template sendResponse(peer: Peer, proto, msg: untyped, data: varargs[untyped]): auto =
|
||||
msg(Response[proto.msg](peer), data)
|
||||
|
||||
asyncTest "network with 3 peers using custom protocols":
|
||||
const useCompression = defined(useSnappy)
|
||||
let localKeys = KeyPair.random()[]
|
||||
let localAddress = localAddress(30303)
|
||||
var localNode = newEthereumNode(localKeys, localAddress, 1, nil, useCompression = useCompression)
|
||||
localNode.startListening()
|
||||
|
||||
var mock1 = newMockPeer do (m: MockConf):
|
||||
m.addHandshake abc.hi(name: "Alice")
|
||||
|
||||
m.expect(abc.abcReq) do (peer: Peer, data: Rlp):
|
||||
let reqId = data.readReqId()
|
||||
await sendResponseWithId(peer, abc, abcRes, reqId, "mock response")
|
||||
await sleepAsync(100)
|
||||
let r = await peer.abcReq(1)
|
||||
doAssert r.get.data == "response to #1"
|
||||
|
||||
m.expect(abc.abcRes)
|
||||
|
||||
var mock2 = newMockPeer do (m: MockConf):
|
||||
m.addCapability xyz
|
||||
m.addCapability abc
|
||||
|
||||
m.expect(abc.abcReq) # we'll let this one time out
|
||||
|
||||
m.expect(xyz.xyzReq) do (peer: Peer):
|
||||
echo "got xyz req"
|
||||
await sendResponse(peer, xyz, xyzRes, "mock peer data")
|
||||
|
||||
when useCompression:
|
||||
m.useCompression = useCompression
|
||||
|
||||
discard await mock1.rlpxConnect(localNode)
|
||||
let mock2Connection = await localNode.rlpxConnect(mock2)
|
||||
|
||||
let r = await mock2Connection.xyzReq(10)
|
||||
check r.get.data == "mock peer data"
|
||||
|
||||
let abcNetState = localNode.protocolState(abc)
|
||||
|
||||
check:
|
||||
abcNetState.peers.len == 2
|
||||
"Alice" in abcNetState.peers
|
||||
"John Doe" in abcNetState.peers
|
Loading…
Reference in New Issue