Skip to content

Commit

Permalink
irc: test suite enhancement
Browse files Browse the repository at this point in the history
Comes with some tweaks to support tests
Daemonizes the ping and timeout threads (they should have been in the first place)
  • Loading branch information
maxpowa committed May 24, 2016
1 parent a10cf3e commit 0ce0b17
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 1 deletion.
6 changes: 5 additions & 1 deletion sopel/irc.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def __init__(self, config):

self.stack = {}
self.ca_certs = ca_certs
self.enabled_capabilities = set()
self.hasquit = False

self.sending = threading.RLock()
Expand Down Expand Up @@ -189,7 +190,8 @@ def quit(self, message):
def handle_close(self):
self.connection_registered = False

self._shutdown()
if hasattr(self, '_shutdown'):
self._shutdown()
stderr('Closed!')

# This will eventually call asyncore dispatchers close method, which
Expand Down Expand Up @@ -231,8 +233,10 @@ def handle_connect(self):
stderr('Connected.')
self.last_ping_time = datetime.now()
timeout_check_thread = threading.Thread(target=self._timeout_check)
timeout_check_thread.daemon = True
timeout_check_thread.start()
ping_thread = threading.Thread(target=self._send_ping)
ping_thread.daemon = True
ping_thread.start()

def _timeout_check(self):
Expand Down
147 changes: 147 additions & 0 deletions test/test_irc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# coding=utf8
"""Tests for message formatting"""
from __future__ import unicode_literals

import pytest

import asynchat
import os
import shutil
import socket
import select
import tempfile
import threading
import time
import asyncore

from sopel import irc
from sopel.tools import stderr, Identifier
import sopel.config as conf


HOST = '127.0.0.1'
SERVER_QUIT = 'QUIT'


class BasicServer(asyncore.dispatcher):
def __init__(self, address, handler):
asyncore.dispatcher.__init__(self)
self.response_handler = handler
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(address)
self.address = self.socket.getsockname()
self.listen(1)
return

def handle_accept(self):
# Called when a client connects to our socket
client_info = self.accept()
BasicHandler(sock=client_info[0], handler=self.response_handler)
self.handle_close()
return

def handle_close(self):
self.close()

class BasicHandler(asynchat.async_chat):
ac_in_buffer_size = 512
ac_out_buffer_size = 512

def __init__(self, sock, handler):
self.received_data = []
asynchat.async_chat.__init__(self, sock)
self.handler_function = handler
self.set_terminator(b'\n')
return

def collect_incoming_data(self, data):
self.received_data.append(data.decode('utf-8'))

def found_terminator(self):
self._process_command()

def _process_command(self):
command = ''.join(self.received_data)
response = self.handler_function(self, command)
self.push(':fake.server {}\n'.format(response).encode())
self.received_data = []


def start_server(rpl_function=None):
def rpl_func(msg):
print(msg)
return msg

if rpl_function is None:
rpl_function = rpl_func

address = ('localhost', 0) # let the kernel give us a port
server = BasicServer(address, rpl_function)
return server


@pytest.fixture
def bot(request):
cfg_dir = tempfile.mkdtemp()
print(cfg_dir)
filename = tempfile.mkstemp(dir=cfg_dir)[1]
os.mkdir(os.path.join(cfg_dir, 'modules'))
def fin():
print('teardown config file')
shutil.rmtree(cfg_dir)
request.addfinalizer(fin)

def gen(data):
with open(filename, 'w') as fileo:
fileo.write(data)
cfg = conf.Config(filename)
irc_bot = irc.Bot(cfg)
irc_bot.config = cfg
return irc_bot

return gen


def test_bot_init(bot):
test_bot = bot(
'[core]\n'
'owner=Baz\n'
'nick=Foo\n'
'user=Bar\n'
'name=Sopel\n'
)
assert test_bot.nick == Identifier('Foo')
assert test_bot.user == 'Bar'
assert test_bot.name == 'Sopel'


def basic_irc_replies(server, msg):
if msg.startswith('NICK'):
return '001 Foo :Hello'
elif msg.startswith('USER'):
# Quit here because good enough
server.close()
elif msg.startswith('PING'):
return 'PONG{}'.format(msg.replace('PING','',1))
elif msg.startswith('CAP'):
return 'CAP * :'
elif msg.startswith('QUIT'):
server.close()
else:
return '421 {} :Unknown command'.format(msg)


def test_bot_connect(bot):
test_bot = bot(
'[core]\n'
'owner=Baz\n'
'nick=Foo\n'
'user=Bar\n'
'name=Sopel\n'
'host=127.0.0.1\n'
'timeout=10\n'
)
s = start_server(basic_irc_replies)

# Do main run
test_bot.run(HOST, s.address[1])

0 comments on commit 0ce0b17

Please sign in to comment.