def test_worker_handle_exception(): server = fake.FakeHTTPServer() thread = threading.Thread(target=web.HTTPServer.worker, args=(server, 0)) thread.start() #Wait a bit time.sleep(0.1) request = fake.FakeHTTPRequest(None, None, None) def bad_handle(self): raise Exception() request.handle = bad_handle server.request_queue.put((request, False, None)) #Wait another bit time.sleep(server.poll_interval + 0.1) assert server.request_queue.qsize() == 0 assert thread.is_alive() server.worker_shutdown = -1 thread.join(timeout=1) server.worker_shutdown = None
def test_worker_keepalive(): server = fake.FakeHTTPServer() thread = threading.Thread(target=web.HTTPServer.worker, args=(server, 0)) thread.start() #Wait a bit time.sleep(0.1) request = fake.FakeHTTPRequest(None, None, None, keepalive_number=2) server.request_queue.put((request, True, None)) #Wait for two polls time.sleep(server.poll_interval + server.poll_interval + 0.1) assert server.request_queue.qsize() == 0 assert thread.is_alive() assert request.handled == 2 assert request.initial_timeout == server.keepalive_timeout server.worker_shutdown = -1 thread.join(timeout=1) server.worker_shutdown = None
def test(request, handler=None, timeout=None, keepalive=True, initial_timeout=None, read_exception=False, close=True): if not isinstance(request, bytes): request = request.encode(web.http_encoding) if not handler: handler = fake.FakeHTTPHandler server = fake.FakeHTTPServer(routes={ '/': handler }) socket = fake.FakeSocket(request) request_obj = web.HTTPRequest(socket, ('127.0.0.1', 1337), server, timeout) request_obj.response = fake.FakeHTTPResponse(socket, ('127.0.0.1', 1337), server, request_obj) if read_exception: def bad_read(self): raise Exception() request_obj.rfile.read = bad_read request_obj.rfile.readline = bad_read request_obj.handle(keepalive, initial_timeout) if close: request_obj.close() return request_obj
def test(handler, handler_args={}, socket=None, server=None): if not socket: socket = fake.FakeSocket() if not server: server = fake.FakeHTTPServer() request_obj = fake.FakeHTTPRequest(socket, ('127.0.0.1', 1337), server, handler=handler, handler_args=handler_args, response=web.HTTPResponse) response_obj = request_obj.response response_obj.handle() value = response_obj.wfile.getvalue() response_obj.close() #Response line comes before firt '\r\n' response_line = value.split('\r\n'.encode(web.http_encoding), 1)[0] #Body should happen after '\r\n\r\n' at the end of the HTTP stuff body = value.split('\r\n\r\n'.encode(web.http_encoding), 1)[1] return response_obj, response_line, response_obj.headers, body
def test_manager_scaling(): server = fake.FakeHTTPServer() server.manager_thread = threading.Thread(target=web.HTTPServer.manager, args=(server,)) server.manager_thread.start() #Wait a bit time.sleep(0.1) for i in range(server.max_queue): server.request_queue.put(None) #Wait a bit for thread start time.sleep(server.poll_interval + 0.1) #Just make sure it is spawning some but not too many threads num_threads = len(server.worker_threads) assert num_threads > server.num_threads assert num_threads <= server.max_threads #Mark a task as done server.request_queue.get_nowait() server.request_queue.task_done() #Wait a bit for another poll time.sleep(server.poll_interval + 0.1) #Make sure the number didn't go down (and isn't over the max) last_threads = num_threads num_threads = len(server.worker_threads) assert num_threads >= last_threads assert num_threads <= server.max_threads #Mark all tasks as done try: while True: server.request_queue.get_nowait() server.request_queue.task_done() except: pass #Wait a bit for another poll time.sleep(server.poll_interval + 0.1) #Make sure the number at least went down last_threads = num_threads num_threads = len(server.worker_threads) assert num_threads < last_threads assert num_threads >= server.num_threads server.manager_shutdown = True server.manager_thread.join(timeout=1) server.manager_shutdown = False
def test_log_request(): class MyHandler(web.HTTPHandler): def respond(self): return 200, test_message server = fake.FakeHTTPServer() response, response_line, headers, body = test(MyHandler, server=server) assert response_line == 'HTTP/1.1 200 OK'.encode(web.http_encoding) assert body == test_message assert server.log.access_log.getvalue( ) == '127.0.0.1 - - [01/Jan/1970:00:00:00 -0000] "GET / HTTP/1.1" 200 15\n'
def test_manager_create_threads(): server = fake.FakeHTTPServer() server.manager_thread = threading.Thread(target=web.HTTPServer.manager, args=(server,)) server.manager_thread.start() #Wait a bit time.sleep(0.1) assert len(server.worker_threads) == server.num_threads for thread in server.worker_threads: assert thread.is_alive() server.manager_shutdown = True server.manager_thread.join(timeout=1) server.manager_shutdown = False assert server.worker_threads == None
def test_error_handler(): class ErrorHandler(web.HTTPErrorHandler): def respond(self): self.response.headers.set('Test', 'True') return 402, b'' server = fake.FakeHTTPServer(error_routes={'500': ErrorHandler}) response, response_line, headers, body = test(web.DummyHandler, {'error': TypeError()}, server=server) assert response_line == 'HTTP/1.1 402 Payment Required'.encode( web.http_encoding) assert headers.get('Test') == 'True' assert body == b''
def test_manager_thread_death(): server = fake.FakeHTTPServer() server.manager_thread = threading.Thread(target=web.HTTPServer.manager, args=(server,)) server.manager_thread.start() #Wait a bit time.sleep(0.1) server.worker_shutdown = 0 server.worker_threads[0].join(timeout=1) server.worker_shutdown = None #Wait a bit for thread restart time.sleep(server.poll_interval + 0.1) #Test that it is alive again assert server.worker_threads[0].is_alive() server.manager_shutdown = True server.manager_thread.join(timeout=1) server.manager_shutdown = False
def test_error_handler_error(): class ErrorHandler(web.HTTPErrorHandler): def respond(self): self.response.headers.set('Test', 'True') raise TypeError() server = fake.FakeHTTPServer(error_routes={'500': ErrorHandler}) response, response_line, headers, body = test(web.DummyHandler, {'error': TypeError()}, server=server) assert response_line == 'HTTP/1.1 500 Internal Server Error'.encode( web.http_encoding) assert headers.get('Test') == None assert headers.get('Content-Length') == '28' assert headers.get('Server') == web.server_version assert headers.get('Date') assert body == b'500 - Internal Server Error\n'
def test_worker_shutdown(): server = fake.FakeHTTPServer() thread = threading.Thread(target=web.HTTPServer.worker, args=(server, 0)) thread.start() #Wait a bit time.sleep(0.1) server.worker_shutdown = 0 thread.join(timeout=1) server.worker_shutdown = None #Do it again but this time setting worker_shutdown to -1 thread = threading.Thread(target=web.HTTPServer.worker, args=(server, 0)) thread.start() #Wait a bit time.sleep(0.1) server.worker_shutdown = -1 thread.join(timeout=1) server.worker_shutdown = None
def test_atomic_wait(): class MyHandler(web.HTTPHandler): nonatomic = False def respond(self): return 200, test_message class OtherHandler(web.HTTPHandler): nonatomic = True def respond(self): return 200, test_message class SpecialHandler(web.HTTPHandler): nonatomic = False stop = threading.Event() waiting = threading.Event() def respond(self): SpecialHandler.waiting.set() SpecialHandler.stop.wait() return 204, '' #Both must have the same server server = fake.FakeHTTPServer() #Both handlers should have the same fake resource '/' and should therefore block since the first one is atomic special = threading.Thread(target=test, args=(SpecialHandler, ), kwargs={'server': server}) my = threading.Thread(target=test, args=(MyHandler, ), kwargs={'server': server}) other = threading.Thread(target=test, args=(OtherHandler, ), kwargs={'server': server}) try: special.start() #Wait until the handler is blocking SpecialHandler.waiting.wait(timeout=1) #Make sure it is locked once assert '/' in server.res_lock.locks assert server.res_lock.locks_count['/'] == 1 my.start() #Wait a bit time.sleep(0.1) #Make sure that the thread is still waiting and there are two locks on the resource now assert my.is_alive() assert server.res_lock.locks_count['/'] == 2 other.start() #Wait a bit time.sleep(0.1) #Make sure that there are still two nonatomic locks on it, since this process will only be waiting on the resource assert other.is_alive() assert server.res_lock.locks_count['/'] == 2 #Make sure special has been here the whole time assert special.is_alive() finally: #Join everything SpecialHandler.stop.set() special.join(timeout=1) my.join(timeout=1) other.join(timeout=1) #Make sure we remove the lock assert '/' not in server.res_lock.locks