Skip to content

Commit 7f189ad

Browse files
committed
Move functional harness to a separate module to avoid import errors.
1 parent ec489a3 commit 7f189ad

File tree

6 files changed

+152
-152
lines changed

6 files changed

+152
-152
lines changed

tests/functional/__init__.py

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +0,0 @@
1-
import subprocess
2-
import os
3-
import sys
4-
import time
5-
import sqlite3
6-
import datetime
7-
import urllib.parse
8-
9-
import irc.client
10-
import pytest
11-
import tempora.timing
12-
13-
import pmxbot.dictlib
14-
15-
16-
class TestingClient:
17-
"""
18-
A simple client simulating a user other than the pmxbot
19-
"""
20-
21-
def __init__(self, server, port, nickname):
22-
self.reactor = irc.client.Reactor()
23-
self.c = self.reactor.server()
24-
self.c.connect(server, port, nickname)
25-
self.reactor.process_once(0.1)
26-
self.channels = set()
27-
28-
def join(self, channel):
29-
self.c.join(channel)
30-
self.channels.add(channel)
31-
32-
def send_message(self, channel, message):
33-
if channel not in self.channels:
34-
self.join(channel)
35-
self.c.privmsg(channel, message)
36-
time.sleep(0.05)
37-
38-
39-
class PmxbotHarness:
40-
config = pmxbot.dictlib.ConfigDict(
41-
server_port=6668,
42-
bot_nickname='pmxbotTest',
43-
log_channels=['#logged'],
44-
other_channels=['#inane'],
45-
database="sqlite:tests/functional/pmxbot.sqlite",
46-
)
47-
48-
@classmethod
49-
def setup_class(cls):
50-
"""Start an IRC server, launch the bot, and ask it to do stuff"""
51-
path = os.path.dirname(os.path.abspath(__file__))
52-
cls.config_fn = os.path.join(path, 'testconf.yaml')
53-
cls.config.to_yaml(cls.config_fn)
54-
cls.dbfile = urllib.parse.urlparse(cls.config['database']).path
55-
cls.db = sqlite3.connect(cls.dbfile)
56-
env = os.environ.copy()
57-
# copy the current sys.path to PYTHONPATH so subprocesses have access
58-
# to libs pulled by tests_require
59-
env['PYTHONPATH'] = os.pathsep.join(sys.path)
60-
try:
61-
cmd = [sys.executable, '-m', 'irc.server', '-p', '6668', '-l', 'debug']
62-
cls.server = subprocess.Popen(cmd, env=env)
63-
except OSError:
64-
pytest.skip("Unable to launch irc server.")
65-
time.sleep(0.5)
66-
# add './plugins' to the path so we get some pmxbot commands specific
67-
# for testing.
68-
plugins = os.path.join(path, 'plugins')
69-
env['PYTHONPATH'] = os.pathsep.join([plugins, env['PYTHONPATH']])
70-
try:
71-
# Launch pmxbot using Python directly (rather than through
72-
# the console entry point, which can't be properly
73-
# .terminate()d on Windows.
74-
cmd = [sys.executable, '-m', 'pmxbot', cls.config_fn]
75-
cls.bot = subprocess.Popen(cmd, env=env)
76-
except OSError:
77-
pytest.skip("Unable to launch pmxbot (pmxbot must be installed)")
78-
cls.wait_for_tables()
79-
cls.wait_for_output()
80-
if cls.bot.poll() is not None:
81-
pytest.skip("Bot did not start up properly")
82-
cls.client = TestingClient('localhost', 6668, 'testingbot')
83-
84-
@classmethod
85-
def wait_for_output(cls):
86-
"""
87-
Wait for 'Running with config' in cls.bot.output
88-
"""
89-
if cls.bot.poll() is not None:
90-
return
91-
# stubbed
92-
time.sleep(5)
93-
94-
@classmethod
95-
def wait_for_tables(cls, timeout=30):
96-
watch = tempora.timing.Stopwatch()
97-
while watch.split() < datetime.timedelta(seconds=timeout):
98-
try:
99-
cls.check_logs('#check')
100-
return
101-
except Exception:
102-
# short-circuit if the bot has stopped
103-
if cls.bot.poll() is not None:
104-
return
105-
time.sleep(0.2)
106-
107-
@classmethod
108-
def check_logs(cls, channel='', nick='', message=''):
109-
if channel.startswith('#'):
110-
channel = channel[1:]
111-
time.sleep(0.2)
112-
cursor = cls.db.cursor()
113-
query = (
114-
"select * from logs where 1=1"
115-
+ " and channel = :channel" * bool(channel)
116-
+ " and nick = :nick" * bool(nick)
117-
+ " and message = :message" * bool(message)
118-
)
119-
cursor.execute(query, locals())
120-
res = cursor.fetchall()
121-
print(res)
122-
return len(res) >= 1
123-
124-
@classmethod
125-
def teardown_class(cls):
126-
os.remove(cls.config_fn)
127-
if hasattr(cls, 'bot') and not cls.bot.poll():
128-
cls.bot.terminate()
129-
cls.bot.wait()
130-
if hasattr(cls, 'server') and cls.server.poll() is None:
131-
cls.server.terminate()
132-
cls.server.wait()
133-
if hasattr(cls, 'db'):
134-
cls.db.rollback()
135-
cls.db.close()
136-
del cls.db
137-
if hasattr(cls, 'client'):
138-
del cls.client
139-
# wait up to 10 seconds for the file to be removable
140-
for x in range(100):
141-
try:
142-
if os.path.isfile(cls.dbfile):
143-
os.remove(cls.dbfile)
144-
break
145-
except OSError:
146-
time.sleep(0.1)
147-
else:
148-
raise RuntimeError('Could not remove log db', cls.dbfile)

tests/functional/harness.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import subprocess
2+
import os
3+
import sys
4+
import time
5+
import sqlite3
6+
import datetime
7+
import urllib.parse
8+
9+
import irc.client
10+
import pytest
11+
import tempora.timing
12+
13+
import pmxbot.dictlib
14+
15+
16+
class TestingClient:
17+
"""
18+
A simple client simulating a user other than the pmxbot
19+
"""
20+
21+
def __init__(self, server, port, nickname):
22+
self.reactor = irc.client.Reactor()
23+
self.c = self.reactor.server()
24+
self.c.connect(server, port, nickname)
25+
self.reactor.process_once(0.1)
26+
self.channels = set()
27+
28+
def join(self, channel):
29+
self.c.join(channel)
30+
self.channels.add(channel)
31+
32+
def send_message(self, channel, message):
33+
if channel not in self.channels:
34+
self.join(channel)
35+
self.c.privmsg(channel, message)
36+
time.sleep(0.05)
37+
38+
39+
class PmxbotHarness:
40+
config = pmxbot.dictlib.ConfigDict(
41+
server_port=6668,
42+
bot_nickname='pmxbotTest',
43+
log_channels=['#logged'],
44+
other_channels=['#inane'],
45+
database="sqlite:tests/functional/pmxbot.sqlite",
46+
)
47+
48+
@classmethod
49+
def setup_class(cls):
50+
"""Start an IRC server, launch the bot, and ask it to do stuff"""
51+
path = os.path.dirname(os.path.abspath(__file__))
52+
cls.config_fn = os.path.join(path, 'testconf.yaml')
53+
cls.config.to_yaml(cls.config_fn)
54+
cls.dbfile = urllib.parse.urlparse(cls.config['database']).path
55+
cls.db = sqlite3.connect(cls.dbfile)
56+
env = os.environ.copy()
57+
# copy the current sys.path to PYTHONPATH so subprocesses have access
58+
# to libs pulled by tests_require
59+
env['PYTHONPATH'] = os.pathsep.join(sys.path)
60+
try:
61+
cmd = [sys.executable, '-m', 'irc.server', '-p', '6668', '-l', 'debug']
62+
cls.server = subprocess.Popen(cmd, env=env)
63+
except OSError:
64+
pytest.skip("Unable to launch irc server.")
65+
time.sleep(0.5)
66+
# add './plugins' to the path so we get some pmxbot commands specific
67+
# for testing.
68+
plugins = os.path.join(path, 'plugins')
69+
env['PYTHONPATH'] = os.pathsep.join([plugins, env['PYTHONPATH']])
70+
try:
71+
# Launch pmxbot using Python directly (rather than through
72+
# the console entry point, which can't be properly
73+
# .terminate()d on Windows.
74+
cmd = [sys.executable, '-m', 'pmxbot', cls.config_fn]
75+
cls.bot = subprocess.Popen(cmd, env=env)
76+
except OSError:
77+
pytest.skip("Unable to launch pmxbot (pmxbot must be installed)")
78+
cls.wait_for_tables()
79+
cls.wait_for_output()
80+
if cls.bot.poll() is not None:
81+
pytest.skip("Bot did not start up properly")
82+
cls.client = TestingClient('localhost', 6668, 'testingbot')
83+
84+
@classmethod
85+
def wait_for_output(cls):
86+
"""
87+
Wait for 'Running with config' in cls.bot.output
88+
"""
89+
if cls.bot.poll() is not None:
90+
return
91+
# stubbed
92+
time.sleep(5)
93+
94+
@classmethod
95+
def wait_for_tables(cls, timeout=30):
96+
watch = tempora.timing.Stopwatch()
97+
while watch.split() < datetime.timedelta(seconds=timeout):
98+
try:
99+
cls.check_logs('#check')
100+
return
101+
except Exception:
102+
# short-circuit if the bot has stopped
103+
if cls.bot.poll() is not None:
104+
return
105+
time.sleep(0.2)
106+
107+
@classmethod
108+
def check_logs(cls, channel='', nick='', message=''):
109+
if channel.startswith('#'):
110+
channel = channel[1:]
111+
time.sleep(0.2)
112+
cursor = cls.db.cursor()
113+
query = (
114+
"select * from logs where 1=1"
115+
+ " and channel = :channel" * bool(channel)
116+
+ " and nick = :nick" * bool(nick)
117+
+ " and message = :message" * bool(message)
118+
)
119+
cursor.execute(query, locals())
120+
res = cursor.fetchall()
121+
print(res)
122+
return len(res) >= 1
123+
124+
@classmethod
125+
def teardown_class(cls):
126+
os.remove(cls.config_fn)
127+
if hasattr(cls, 'bot') and not cls.bot.poll():
128+
cls.bot.terminate()
129+
cls.bot.wait()
130+
if hasattr(cls, 'server') and cls.server.poll() is None:
131+
cls.server.terminate()
132+
cls.server.wait()
133+
if hasattr(cls, 'db'):
134+
cls.db.rollback()
135+
cls.db.close()
136+
del cls.db
137+
if hasattr(cls, 'client'):
138+
del cls.client
139+
# wait up to 10 seconds for the file to be removable
140+
for x in range(100):
141+
try:
142+
if os.path.isfile(cls.dbfile):
143+
os.remove(cls.dbfile)
144+
break
145+
except OSError:
146+
time.sleep(0.1)
147+
else:
148+
raise RuntimeError('Could not remove log db', cls.dbfile)

tests/functional/test_exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import time
22

3-
from . import PmxbotHarness
3+
from .harness import PmxbotHarness
44

55

66
class TestPmxbotExceptions(PmxbotHarness):

tests/functional/test_logging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import time
22
import uuid
33

4-
from . import PmxbotHarness
4+
from .harness import PmxbotHarness
55

66

77
class TestPmxbotLog(PmxbotHarness):

tests/functional/test_messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import time
22

3-
from . import PmxbotHarness
3+
from .harness import PmxbotHarness
44

55

66
class TestPmxbotMessages(PmxbotHarness):

tests/functional/test_regexps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import time
22

3-
from . import PmxbotHarness
3+
from .harness import PmxbotHarness
44

55

66
class TestPmxbotRegexp(PmxbotHarness):

0 commit comments

Comments
 (0)