diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 77e0975..122e4f5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,8 +10,9 @@ test: stage: test script: - pip3 install -r requirements.txt - - sudo -u matemat python3 -m coverage run --branch -m unittest discover matemat - - sudo -u matemat python3 -m coverage report -m --include 'matemat/*' --omit '*/test_*.py' --omit 'matemat/webserver/test/abstract_httpd_test.py' + - sudo -u matemat python3 -m coverage run --rcfile=setup.cfg -m unittest discover matemat + - sudo -u matemat python3 -m coverage combine + - sudo -u matemat python3 -m coverage report --rcfile=setup.cfg codestyle: stage: test diff --git a/matemat/webserver/httpd.py b/matemat/webserver/httpd.py index 24916be..c0a351d 100644 --- a/matemat/webserver/httpd.py +++ b/matemat/webserver/httpd.py @@ -1,8 +1,7 @@ -from typing import Any, Callable, Dict, List, Tuple, Type, Union +from typing import Any, Callable, Dict, Set, Tuple, Type, Union import logging -import sys import os import socket import mimetypes @@ -40,7 +39,7 @@ _PAGELET_PATHS: Dict[str, Callable[[str, # HTTP method (GET, POST, ...) PageletResponse, # A generic response ]]] = dict() # The pagelet initialization functions, to be executed upon startup -_PAGELET_INIT_FUNCTIONS: List[Callable[[Dict[str, str], logging.Logger], None]] = [] +_PAGELET_INIT_FUNCTIONS: Set[Callable[[Dict[str, str], logging.Logger], None]] = set() # Inactivity timeout for client sessions _SESSION_TIMEOUT: int = 3600 @@ -116,7 +115,7 @@ def pagelet_init(fun: Callable[[Dict[str, str], logging.Logger], None]): :param fun: The function to annotate """ - _PAGELET_INIT_FUNCTIONS.append(fun) + _PAGELET_INIT_FUNCTIONS.add(fun) class MatematHTTPServer(HTTPServer): @@ -221,7 +220,7 @@ class MatematWebserver(object): # If an error occurs, log it and terminate self._httpd.logger.exception(e) self._httpd.logger.critical('An initialization pagelet raised an error. Stopping.') - sys.exit(1) + raise e # If pagelet initialization went fine, start the HTTP server self._httpd.serve_forever() diff --git a/matemat/webserver/test/test_pagelet_init.py b/matemat/webserver/test/test_pagelet_init.py new file mode 100644 index 0000000..21c30e4 --- /dev/null +++ b/matemat/webserver/test/test_pagelet_init.py @@ -0,0 +1,63 @@ +from typing import Any, Dict + +import unittest +import http.client + +import logging +import threading + +from matemat.webserver import MatematWebserver, RequestArguments, pagelet_init, pagelet + + +@pagelet('/just/testing/init') +def init_test_pagelet(method: str, + path: str, + args: RequestArguments, + session_vars: Dict[str, Any], + headers: Dict[str, str], + pagelet_variables: Dict[str, str]): + return pagelet_variables['Unit-Test'] + + +_INIT_FAIL = False + + +@pagelet_init +def init(config: Dict[str, str], + logger: logging.Logger): + if _INIT_FAIL: + raise ValueError('This error should be raised!') + config['Unit-Test'] = 'Pagelet Init Test' + + +class TestPageletInitialization(unittest.TestCase): + + def tearDown(self): + global _INIT_FAIL + _INIT_FAIL = False + + def test_pagelet_init_ok(self): + """ + Test successful pagelet initialization + """ + srv = MatematWebserver('::1', 0, '/nonexistent', '/nonexistent', {}, {}, logging.NOTSET, logging.NullHandler()) + port = int(srv._httpd.socket.getsockname()[1]) + thread = threading.Thread(target=srv.start) + thread.start() + con = http.client.HTTPConnection(f'[::1]:{port}') + con.request('GET', '/just/testing/init') + response = con.getresponse().read() + srv._httpd.shutdown() + srv._httpd.socket.close() + self.assertEqual(b'Pagelet Init Test', response) + + def test_pagelet_init_fail(self): + """ + Test unsuccessful pagelet initialization + """ + global _INIT_FAIL + _INIT_FAIL = True + srv = MatematWebserver('::1', 0, '/nonexistent', '/nonexistent', {}, {}, logging.NOTSET, logging.NullHandler()) + with self.assertRaises(ValueError): + srv.start() + srv._httpd.socket.close() diff --git a/setup.cfg b/setup.cfg index 62acd3a..2dcea66 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,22 @@ + +# +# PyCodestyle +# + [pycodestyle] max-line-length = 120 statistics = True + +# +# Coverage +# + +[run] +branch = True +parallel = True +source = matemat/ + +[report] +show_missing = True +include = matemat/* +omit = */test/*.py