New test case class hierarchy:

- TestProcessProto has common setUpClass and tearDownClass methods
  - TestProcess is for testing the PyBitmessage process (using psutil)
This commit is contained in:
Dmitri Bogomolov 2018-04-12 17:29:22 +03:00
parent c28d463261
commit c49c131929
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13
3 changed files with 99 additions and 10 deletions

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
python_prctl
psutil

View File

@ -1,26 +1,25 @@
import unittest
import subprocess
import xmlrpclib import xmlrpclib
import base64 import base64
import json import json
import os
import tempfile
from time import sleep from time import sleep
from test_process import TestProcessProto
class TestAPI(TestProcessProto):
_process_cmd = ['pybitmessage', '-t']
class TestAPI(unittest.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
subprocess.call(['pybitmessage', '-t']) super(TestAPI, cls).setUpClass()
cls.addresses = [] cls.addresses = []
cls.api = xmlrpclib.ServerProxy( cls.api = xmlrpclib.ServerProxy(
"http://username:password@127.0.0.1:8442/") "http://username:password@127.0.0.1:8442/")
for tick in range(0, 10): for tick in range(0, 5):
sleep(1) if cls._get_readline('.api_started'):
if os.path.isfile(os.path.join(
tempfile.gettempdir(), '.api_started')):
print('API start detected!') print('API start detected!')
return return
sleep(1)
def _add_random_address(self, label): def _add_random_address(self, label):
return self.api.createRandomAddress(base64.encodestring(label)) return self.api.createRandomAddress(base64.encodestring(label))

88
src/tests/test_process.py Normal file
View File

@ -0,0 +1,88 @@
import unittest
import subprocess
import os
import signal
import tempfile
from time import sleep
import psutil
class TestProcessProto(unittest.TestCase):
_process_cmd = ['pybitmessage', '-d']
_threads_count = 14
_files = ('keys.dat', 'debug.log', 'messages.dat', 'knownnodes.dat')
@classmethod
def setUpClass(cls):
cls.home = os.environ['BITMESSAGE_HOME'] = tempfile.gettempdir()
subprocess.call(cls._process_cmd)
sleep(5)
cls.pid = int(cls._get_readline('singleton.lock'))
cls.process = psutil.Process(cls.pid)
@classmethod
def _get_readline(cls, pfile):
pfile = os.path.join(cls.home, pfile)
try:
return open(pfile, 'rb').readline().strip()
except (OSError, IOError):
pass
@classmethod
def _cleanup_files(cls):
for pfile in cls._files:
try:
os.remove(os.path.join(cls.home, pfile))
except OSError:
pass
@classmethod
def tearDownClass(cls):
cls.process.send_signal(signal.SIGTERM)
try:
cls.process.wait(5)
except psutil.TimeoutExpired:
print(open(os.path.join(cls.home, 'debug.log'), 'rb').read())
cls.process.kill()
finally:
cls._cleanup_files()
def _test_threads(self):
# only count for now
# because of https://github.com/giampaolo/psutil/issues/613
# PyBitmessage
# - addressGenerator
# - singleWorker
# - SQL
# - objectProcessor
# - singleCleaner
# - singleAPI
# - Asyncore
# - ReceiveQueue_0
# - ReceiveQueue_1
# - ReceiveQueue_2
# - Announcer
# - InvBroadcaster
# - AddrBroadcaster
# - Downloader
self.assertEqual(
len(self.process.threads()), self._threads_count)
class TestProcess(TestProcessProto):
def test_process_name(self):
"""Check PyBitmessage process name"""
self.assertEqual(self.process.name(), 'PyBitmessage')
def test_files(self):
"""Check existence of PyBitmessage files"""
for pfile in self._files:
self.assertIsNot(
self._get_readline(pfile), None,
'Failed to read file %s' % pfile
)
def test_threads(self):
"""Testing PyBitmessage threads"""
self._test_threads()