from contextlib import contextmanager import logging import random import threading from wsgiref.simple_server import ( ServerHandler, WSGIRequestHandler, WSGIServer, make_server, ) import pytest log = logging.getLogger(__name__) ServerHandler.handle_error = lambda: None class QuietHandler(WSGIRequestHandler): def log_request(self, *args): pass class QuietServer(WSGIServer): def handle_error(self, req, addr): pass def _make_test_server(app): maxport = (1 << 16) - 1 # we'll make 3 attempts to find a free port for i in range(3, 0, -1): try: port = random.randint(maxport // 2, maxport) server = make_server( "localhost", port, app, server_class=QuietServer, handler_class=QuietHandler, ) server.timeout = 5 return server except BaseException: if i == 1: raise @pytest.fixture def serve(): @contextmanager def _serve(app): server = _make_test_server(app) try: worker = threading.Thread(target=server.serve_forever) worker.daemon = True worker.start() server.url = "http://localhost:%d" % server.server_port log.debug("server started on %s", server.url) yield server finally: log.debug("shutting server down") server.shutdown() worker.join(1) if worker.is_alive(): log.warning("worker is hanged") else: log.debug("server stopped") return _serve