py-libp2p/tests/factories.py

204 lines
6.5 KiB
Python
Raw Normal View History

2019-09-09 15:45:35 +08:00
import asyncio
from typing import Dict, Tuple
import factory
from libp2p import generate_new_rsa_identity, initialize_default_swarm
from libp2p.crypto.keys import KeyPair
from libp2p.host.basic_host import BasicHost
2019-09-17 23:38:11 +08:00
from libp2p.network.connection.swarm_connection import SwarmConn
2019-09-09 15:45:35 +08:00
from libp2p.network.stream.net_stream_interface import INetStream
2019-09-14 23:37:01 +08:00
from libp2p.network.swarm import Swarm
from libp2p.pubsub.floodsub import FloodSub
from libp2p.pubsub.gossipsub import GossipSub
from libp2p.pubsub.pubsub import Pubsub
from libp2p.security.base_transport import BaseSecureTransport
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureTransport
import libp2p.security.secio.transport as secio
from libp2p.stream_muxer.mplex.mplex import MPLEX_PROTOCOL_ID, Mplex
2019-09-18 21:51:09 +08:00
from libp2p.stream_muxer.mplex.mplex_stream import MplexStream
from libp2p.transport.typing import TMuxerOptions
from libp2p.typing import TProtocol
2019-09-09 15:45:35 +08:00
from tests.configs import LISTEN_MADDR
from tests.pubsub.configs import (
2019-08-03 09:36:58 +08:00
FLOODSUB_PROTOCOL_ID,
GOSSIPSUB_PARAMS,
GOSSIPSUB_PROTOCOL_ID,
)
2019-09-14 23:37:01 +08:00
from tests.utils import connect, connect_swarm
def security_transport_factory(
is_secure: bool, key_pair: KeyPair
) -> Dict[TProtocol, BaseSecureTransport]:
if not is_secure:
return {PLAINTEXT_PROTOCOL_ID: InsecureTransport(key_pair)}
else:
return {secio.ID: secio.Transport(key_pair)}
2019-10-28 19:38:50 +08:00
def SwarmFactory(
is_secure: bool, key_pair: KeyPair, muxer_opt: TMuxerOptions = None
) -> Swarm:
sec_opt = security_transport_factory(is_secure, key_pair)
return initialize_default_swarm(key_pair, sec_opt=sec_opt, muxer_opt=muxer_opt)
class ListeningSwarmFactory(factory.Factory):
2019-09-14 23:37:01 +08:00
class Meta:
model = Swarm
@classmethod
async def create_and_listen(
cls, is_secure: bool, muxer_opt: TMuxerOptions = None
2019-10-28 19:38:50 +08:00
) -> Tuple[Swarm, KeyPair]:
key_pair = generate_new_rsa_identity()
swarm = SwarmFactory(is_secure, key_pair, muxer_opt=muxer_opt)
2019-09-14 23:37:01 +08:00
await swarm.listen(LISTEN_MADDR)
2019-10-28 19:38:50 +08:00
return swarm, key_pair
2019-09-14 23:37:01 +08:00
@classmethod
async def create_batch_and_listen(
cls, is_secure: bool, number: int, muxer_opt: TMuxerOptions = None
2019-10-28 19:38:50 +08:00
) -> Tuple[Tuple[Swarm, KeyPair], ...]:
2019-09-14 23:37:01 +08:00
return await asyncio.gather(
*[
cls.create_and_listen(is_secure, muxer_opt=muxer_opt)
for _ in range(number)
]
2019-09-14 23:37:01 +08:00
)
class HostFactory(factory.Factory):
class Meta:
model = BasicHost
class Params:
is_secure = False
2019-10-28 19:38:50 +08:00
network = factory.LazyAttribute(lambda o: SwarmFactory(o.is_secure, o.key_pair))
2019-09-09 15:45:35 +08:00
@classmethod
async def create_and_listen(cls, is_secure: bool) -> BasicHost:
2019-10-28 19:38:50 +08:00
swarms_and_keys = await ListeningSwarmFactory.create_batch_and_listen(
is_secure, 1
)
swarm, key_pair = swarms_and_keys[0]
return BasicHost(key_pair.public_key, swarm)
@classmethod
async def create_batch_and_listen(
cls, is_secure: bool, number: int
) -> Tuple[BasicHost, ...]:
2019-10-28 19:38:50 +08:00
swarms_and_keys = await ListeningSwarmFactory.create_batch_and_listen(
is_secure, number
)
return tuple(
BasicHost(key_pair.public_key, swarm) for swarm, key_pair in swarms_and_keys
)
2019-09-09 15:45:35 +08:00
class FloodsubFactory(factory.Factory):
class Meta:
model = FloodSub
protocols = (FLOODSUB_PROTOCOL_ID,)
class GossipsubFactory(factory.Factory):
class Meta:
model = GossipSub
protocols = (GOSSIPSUB_PROTOCOL_ID,)
degree = GOSSIPSUB_PARAMS.degree
degree_low = GOSSIPSUB_PARAMS.degree_low
degree_high = GOSSIPSUB_PARAMS.degree_high
time_to_live = GOSSIPSUB_PARAMS.time_to_live
gossip_window = GOSSIPSUB_PARAMS.gossip_window
gossip_history = GOSSIPSUB_PARAMS.gossip_history
heartbeat_interval = GOSSIPSUB_PARAMS.heartbeat_interval
class PubsubFactory(factory.Factory):
class Meta:
model = Pubsub
host = factory.SubFactory(HostFactory)
router = None
my_id = factory.LazyAttribute(lambda obj: obj.host.get_id())
cache_size = None
2019-09-09 15:45:35 +08:00
async def swarm_pair_factory(
is_secure: bool, muxer_opt: TMuxerOptions = None
) -> Tuple[Swarm, Swarm]:
2019-10-28 19:38:50 +08:00
swarms_and_keys = await ListeningSwarmFactory.create_batch_and_listen(
is_secure, 2, muxer_opt=muxer_opt
)
2019-10-28 19:38:50 +08:00
swarms = tuple(swarm for swarm, _key_pair in swarms_and_keys)
2019-09-14 23:37:01 +08:00
await connect_swarm(swarms[0], swarms[1])
return swarms[0], swarms[1]
async def host_pair_factory(is_secure) -> Tuple[BasicHost, BasicHost]:
2019-09-09 15:45:35 +08:00
hosts = await asyncio.gather(
2019-09-14 23:37:01 +08:00
*[
HostFactory.create_and_listen(is_secure),
HostFactory.create_and_listen(is_secure),
]
2019-09-09 15:45:35 +08:00
)
await connect(hosts[0], hosts[1])
return hosts[0], hosts[1]
2019-09-17 23:38:11 +08:00
async def swarm_conn_pair_factory(
is_secure: bool, muxer_opt: TMuxerOptions = None
2019-09-17 23:38:11 +08:00
) -> Tuple[SwarmConn, Swarm, SwarmConn, Swarm]:
swarms = await swarm_pair_factory(is_secure)
conn_0 = swarms[0].connections[swarms[1].get_peer_id()]
conn_1 = swarms[1].connections[swarms[0].get_peer_id()]
return conn_0, swarms[0], conn_1, swarms[1]
2019-09-09 15:45:35 +08:00
2019-09-18 21:51:09 +08:00
async def mplex_conn_pair_factory(is_secure: bool) -> Tuple[Mplex, Swarm, Mplex, Swarm]:
muxer_opt = {MPLEX_PROTOCOL_ID: Mplex}
conn_0, swarm_0, conn_1, swarm_1 = await swarm_conn_pair_factory(
is_secure, muxer_opt=muxer_opt
)
return conn_0.muxed_conn, swarm_0, conn_1.muxed_conn, swarm_1
2019-09-18 21:51:09 +08:00
async def mplex_stream_pair_factory(
is_secure: bool
) -> Tuple[MplexStream, Swarm, MplexStream, Swarm]:
mplex_conn_0, swarm_0, mplex_conn_1, swarm_1 = await mplex_conn_pair_factory(
is_secure
)
stream_0 = await mplex_conn_0.open_stream()
await asyncio.sleep(0.01)
stream_1: MplexStream
async with mplex_conn_1.streams_lock:
if len(mplex_conn_1.streams) != 1:
raise Exception("Mplex should not have any stream upon connection")
stream_1 = tuple(mplex_conn_1.streams.values())[0]
return stream_0, swarm_0, stream_1, swarm_1
2019-09-14 23:37:01 +08:00
async def net_stream_pair_factory(
is_secure: bool
) -> Tuple[INetStream, BasicHost, INetStream, BasicHost]:
2019-09-09 15:45:35 +08:00
protocol_id = "/example/id/1"
stream_1: INetStream
# Just a proxy, we only care about the stream
def handler(stream: INetStream) -> None:
nonlocal stream_1
stream_1 = stream
2019-09-14 23:37:01 +08:00
host_0, host_1 = await host_pair_factory(is_secure)
2019-09-09 15:45:35 +08:00
host_1.set_stream_handler(protocol_id, handler)
stream_0 = await host_0.new_stream(host_1.get_id(), [protocol_id])
return stream_0, host_0, stream_1, host_1