Browse Source

test_irc_messaging.py: redo code to simplify testing

add-joinmarket
zebra-lucky 1 year ago
parent
commit
48192bd11a
  1. 279
      electrum/plugins/joinmarket/tests/jmdaemon/test_irc_messaging.py

279
electrum/plugins/joinmarket/tests/jmdaemon/test_irc_messaging.py

@ -2,162 +2,183 @@
'''Tests of joinmarket bots end-to-end (including IRC and bitcoin) ''' '''Tests of joinmarket bots end-to-end (including IRC and bitcoin) '''
import asyncio
import io import io
import time
from electrum.plugins.joinmarket.jmbase import commands from electrum.plugins.joinmarket.jmbase import commands
from electrum.plugins.joinmarket.jmdaemon import ( from electrum.plugins.joinmarket.jmdaemon import (
IRCMessageChannel, MessageChannelCollection) IRCMessageChannel, MessageChannelCollection)
from electrum.plugins.joinmarket.jmdaemon.irc import wlog, TxIRCFactory
from electrum.plugins.joinmarket.jmdaemon.irc_support import IRCClientService
from electrum.plugins.joinmarket.tests import JMTestCase from electrum.plugins.joinmarket.tests import JMTestCase
si = 1 class DummyTransport(asyncio.Transport):
def __init__(self):
super().__init__()
self._t = io.BytesIO(b'')
class DummyDaemon(object): def write(self, data):
self._t.write(data)
def request_signature_verify(self, a, b, c, d, e, f, g, h): def close(self):
return True self._t.close()
class DummyIRCClientService(IRCClientService):
async def _dummy_create_conn(self, sslc):
self.logger.debug(f'_dummy_create_conn: {self.factory.buildProtocol}, '
f'{self.host}:{self.port}, {sslc}')
transport = DummyTransport()
protocol = self.factory.buildProtocol()
protocol.connection_made(transport)
return transport, protocol
async def _create_conn(self, sslc):
self.logger.debug(f'_create_conn: {sslc}')
self.transport, self.protocol = await self._dummy_create_conn(sslc)
async def _proxy_create_conn(self, sslc):
self.logger.debug(f'_proxy_create_conn: {sslc}')
self.transport, self.protocol = await self._create_conn(sslc)
class DummyMC(IRCMessageChannel): class DummyMC(IRCMessageChannel):
def __init__(self, jmman, configdata, nick): def __init__(self, jmman, configdata, nick):
super().__init__(jmman, configdata) super().__init__(jmman, configdata)
self.jmman = jmman
self.set_nick(nick) self.set_nick(nick)
async def shutdown(self): async def build_irc(self):
self.tx_irc_client.transport = io.BytesIO(b'') wlog(self.logger, 'building irc')
self.tx_irc_client._queue = [] if self.tx_irc_client:
self.tx_irc_client.quit() raise Exception('irc already built')
self.give_up = True try:
if self.client_service: self.irc_factory = TxIRCFactory(self)
self.client_service.stopService() wlog(
self.logger,
f'build_irc: host={self.host}, port={self.port}, '
def on_connect(x): f'channel={self.channel}, usessl={self.usessl}, '
print('simulated on-connect') f'socks5={self.socks5}, socks5_host={self.socks5_host}, '
f'socks5_port={self.socks5_port}')
self.client_service = DummyIRCClientService(
def on_welcome(mc): self.irc_factory, host=self.host, port=self.port,
print('simulated on-welcome') loop=self.loop, usessl=self.usessl, socks5=self.socks5,
mc.tx_irc_client.lineRate = 0.2 socks5_host=self.socks5_host, socks5_port=self.socks5_port)
if mc.nick == "irc_publisher": self.client_service.startService()
d = commands.deferLater(3.0, junk_pubmsgs, mc) await self.client_service.srv_task
d.addCallback(junk_longmsgs) except Exception as e:
d.addCallback(junk_announce) wlog(self.logger, 'error in buildirc: ' + repr(e))
d.addCallback(junk_fill)
class IRCMessageChannelTestCase(JMTestCase):
def on_disconnect(x):
print('simulated on-disconnect') def on_connect(self, x):
print('simulated on-connect')
def on_order_seen(dummy, counterparty, oid, ordertype, minsize, def on_welcome(self, mc):
maxsize, txfee, cjfee): print('simulated on-welcome')
global yg_name mc.tx_irc_client.lineRate = 0.2
yg_name = counterparty if mc.nick == "irc_publisher":
d = commands.deferLater(3.0, self.junk_pubmsgs, mc)
d.addCallback(self.junk_longmsgs)
def on_pubkey(pubkey): d.addCallback(self.junk_announce)
print("received pubkey: " + pubkey) d.addCallback(self.junk_fill)
def on_disconnect(self, x):
async def junk_pubmsgs(mc): print('simulated on-disconnect')
# start a raw IRCMessageChannel instance in a thread;
# then call send_* on it with various errant messages def on_order_seen(self, dummy, counterparty, oid, ordertype, minsize,
time.sleep(si) maxsize, txfee, cjfee):
await mc.request_orderbook() self.yg_name = counterparty
time.sleep(si)
# now try directly def on_pubkey(self, pubkey):
await mc.pubmsg("!orderbook") print("received pubkey: " + pubkey)
time.sleep(si)
# should be ignored; can we check? async def junk_pubmsgs(self, mc):
await mc.pubmsg("!orderbook!orderbook") # start a raw IRCMessageChannel instance in a thread;
return mc # then call send_* on it with various errant messages
await asyncio.sleep(1)
await mc.request_orderbook()
async def junk_longmsgs(mc): await asyncio.sleep(1)
# assuming MAX_PRIVMSG_LEN is not something crazy # now try directly
# big like 550, this should fail await mc.pubmsg("!orderbook")
# with pytest.raises(AssertionError) as e_info: await asyncio.sleep(1)
await mc.pubmsg("junk and crap"*40) # should be ignored; can we check?
time.sleep(si) await mc.pubmsg("!orderbook!orderbook")
# assuming MAX_PRIVMSG_LEN is not something crazy return mc
# small like 180, this should succeed
await mc.pubmsg("junk and crap"*15) async def junk_longmsgs(self, mc):
time.sleep(si) # assuming MAX_PRIVMSG_LEN is not something crazy
return mc # big like 550, this should fail
# with pytest.raises(AssertionError) as e_info:
await mc.pubmsg("junk and crap"*40)
async def junk_announce(mc): await asyncio.sleep(1)
# try a long order announcement in public # assuming MAX_PRIVMSG_LEN is not something crazy
# because we don't want to build a real orderbook, # small like 180, this should succeed
# call the underlying IRC announce function. await mc.pubmsg("junk and crap"*15)
# TODO: how to test that the sent format was correct? await asyncio.sleep(1)
print('got here') return mc
await mc._announce_orders(["!abc def gh 0001"]*30)
time.sleep(si) async def junk_announce(self, mc):
return mc # try a long order announcement in public
# because we don't want to build a real orderbook,
# call the underlying IRC announce function.
async def junk_fill(mc): # TODO: how to test that the sent format was correct?
cpname = "irc_receiver" print('got here')
# send a fill with an invalid pubkey to the existing yg; await mc._announce_orders(["!abc def gh 0001"]*30)
# this should trigger a NaclError but should NOT kill it. await asyncio.sleep(1)
await mc._privmsg(cpname, "fill", "0 10000000 abcdef") return mc
# Try with ob flag
await mc._pubmsg("!reloffer stuff") async def junk_fill(self, mc):
time.sleep(si) cpname = "irc_receiver"
# Trigger throttling with large messages # send a fill with an invalid pubkey to the existing yg;
await mc._privmsg(cpname, "tx", "aa"*5000) # this should trigger a NaclError but should NOT kill it.
time.sleep(si) await mc._privmsg(cpname, "fill", "0 10000000 abcdef")
# with pytest.raises(CJPeerError) as e_info: # Try with ob flag
await mc.send_error(cpname, "fly you fools!") await mc._pubmsg("!reloffer stuff")
time.sleep(si) await asyncio.sleep(1)
return mc # Trigger throttling with large messages
await mc._privmsg(cpname, "tx", "aa"*5000)
await asyncio.sleep(1)
def getmc(jmman, nick): # with pytest.raises(CJPeerError) as e_info:
jmconf = jmman.jmconf await mc.send_error(cpname, "fly you fools!")
mchannels = list(jmconf.get_msg_channels().values()) await asyncio.sleep(1)
mc = DummyMC(jmman, mchannels[0], nick) return mc
mc.register_orderbookwatch_callbacks(on_order_seen=on_order_seen)
mc.register_taker_callbacks(on_pubkey=on_pubkey) def getmc(self, nick):
mc.on_connect = on_connect jmman = self.jmman
mc.on_disconnect = on_disconnect jmconf = jmman.jmconf
mc.on_welcome = on_welcome mchannels = list(jmconf.get_msg_channels().values())
mcc = MessageChannelCollection([mc], jmman) mc = DummyMC(jmman, mchannels[0], nick)
return mc, mcc mc.register_orderbookwatch_callbacks(on_order_seen=self.on_order_seen)
mc.register_taker_callbacks(on_pubkey=self.on_pubkey)
mc.on_connect = self.on_connect
class TrialIRC(JMTestCase): mc.on_disconnect = self.on_disconnect
mc.on_welcome = self.on_welcome
mcc = MessageChannelCollection([mc], jmman)
return mc, mcc
async def asyncSetUp(self): async def asyncSetUp(self):
await super().asyncSetUp() await super().asyncSetUp()
self.jmman.jmconf.maker_timeout_sec = 1 self.jmman.jmconf.maker_timeout_sec = 1
mc, mcc = getmc(self.jmman, "irc_publisher") self.mc, self.mcc = self.getmc("irc_publisher")
mc2, mcc2 = getmc(self.jmman, "irc_receiver") self.mc2, self.mcc2 = self.getmc("irc_receiver")
await mcc.run() await self.mcc.run()
mc.irc_factory.buildProtocol() #self.mc.irc_factory.buildProtocol()
await mcc2.run() await self.mcc2.run()
mc2.irc_factory.buildProtocol() #self.mc2.irc_factory.buildProtocol()
async def cb(m): async def cb(m):
# don't try to reconnect # don't try to reconnect
m.give_up = True m.give_up = True
await mc.shutdown() await m.shutdown()
self.addCleanup(cb, mc)
self.addCleanup(cb, mc2)
# test_junk_messages()
print("Got here")
async def test_waiter(self): self.addCleanup(cb, self.mc)
# commands.callLater(1.0, junk_messages, self.mcc) self.addCleanup(cb, self.mc2)
return commands.deferLater(30, self._called_by_deffered)
async def _called_by_deffered(self): async def test_setup(self):
pass assert 0

Loading…
Cancel
Save