From 99825de025fe47372ce8fc09f1461a7f0576f4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 24 Nov 2015 23:08:38 +0100 Subject: [PATCH 01/40] Implemented dummy socket server interface and added one test --- dummyserver/__init__.py | 0 dummyserver/server.py | 38 ++++++++++++++++++++++++++++++++++++++ test_requests.py | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 dummyserver/__init__.py create mode 100644 dummyserver/server.py diff --git a/dummyserver/__init__.py b/dummyserver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/dummyserver/server.py b/dummyserver/server.py new file mode 100644 index 00000000..e8a90bc4 --- /dev/null +++ b/dummyserver/server.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +import threading, socket + + + +""" +Dummy server using for unit testing +""" + +class Server(threading.Thread): + def __init__(self, handler, host='localhost', port=8021): + threading.Thread.__init__(self) + self.handler = handler + self.host = host + self.port = port + self.ready_event = threading.Event() + self.stop_event = threading.Event() + + def run(self): + sock = socket.socket() + sock.bind((self.host, self.port)) + sock.listen(0) + self.ready_event.set() + self.handler(sock) + self.stop_event.set() + sock.close() + + def __enter__(self): + self.start() + self.ready_event.wait() + return self.host, self.port + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + self.stop_event.wait() + return False # allow exceptions to propagate + diff --git a/test_requests.py b/test_requests.py index e83cbc44..5bf1e402 100755 --- a/test_requests.py +++ b/test_requests.py @@ -29,6 +29,8 @@ from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks +from dummyserver.server import Server +import socket try: import StringIO @@ -1736,6 +1738,23 @@ def test_vendor_aliases(): with pytest.raises(ImportError): from requests.packages import webbrowser +class TestDummyServer(unittest.TestCase): + def test_basic(self): + question = "sucess?" + answer = "yeah, success" + def handler(server_sock): + sock, _ = server_sock.accept() + text = sock.recv(1000) + assert text == question + sock.send(answer) + + with Server(handler) as (host, port): + sock = socket.socket() + sock.connect((host, port)) + sock.send(question) + text = sock.recv(1000) + assert text == answer + sock.close() if __name__ == '__main__': unittest.main() From 9a2cc99b068b2aaa572f52b4516852b239577c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 25 Nov 2015 13:52:53 +0100 Subject: [PATCH 02/40] Put docstring inside Server class --- dummyserver/server.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dummyserver/server.py b/dummyserver/server.py index e8a90bc4..22c5d90f 100644 --- a/dummyserver/server.py +++ b/dummyserver/server.py @@ -4,11 +4,10 @@ import threading, socket -""" -Dummy server using for unit testing -""" class Server(threading.Thread): + """ Dummy server using for unit testing """ + def __init__(self, handler, host='localhost', port=8021): threading.Thread.__init__(self) self.handler = handler From b806ce15ba5d726f94f58aa247fe40b6e2972fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 25 Nov 2015 13:53:54 +0100 Subject: [PATCH 03/40] Make strings in DummyServer test bytestrings --- test_requests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_requests.py b/test_requests.py index 5bf1e402..89d9c75b 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1740,8 +1740,8 @@ def test_vendor_aliases(): class TestDummyServer(unittest.TestCase): def test_basic(self): - question = "sucess?" - answer = "yeah, success" + question = b"sucess?" + answer = b"yeah, success" def handler(server_sock): sock, _ = server_sock.accept() text = sock.recv(1000) From 47e96c4e57964dd2db4806b2c24e02a89f3ae8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 25 Nov 2015 14:05:21 +0100 Subject: [PATCH 04/40] Renamed dummyserver to testserver --- test_requests.py | 4 ++-- testserver/.server.py.swo | Bin 0 -> 12288 bytes {dummyserver => testserver}/__init__.py | 0 {dummyserver => testserver}/server.py | 5 +---- 4 files changed, 3 insertions(+), 6 deletions(-) create mode 100644 testserver/.server.py.swo rename {dummyserver => testserver}/__init__.py (100%) rename {dummyserver => testserver}/server.py (94%) diff --git a/test_requests.py b/test_requests.py index 89d9c75b..926abe2e 100755 --- a/test_requests.py +++ b/test_requests.py @@ -29,7 +29,7 @@ from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks -from dummyserver.server import Server +from testserver.server import Server import socket try: @@ -1738,7 +1738,7 @@ def test_vendor_aliases(): with pytest.raises(ImportError): from requests.packages import webbrowser -class TestDummyServer(unittest.TestCase): +class TestTestServer(unittest.TestCase): def test_basic(self): question = b"sucess?" answer = b"yeah, success" diff --git a/testserver/.server.py.swo b/testserver/.server.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..eb2d89d951ba5e633d389c0c2bc56934ae95a5e2 GIT binary patch literal 12288 zcmeI2y=xRf9EK-?VAQB6Ho;SH{&_+RQ6tohwQG91V?k=a8A_xY41JBK7=j)wkZUZ4(DbG$_ z;b)A~4CM%8jYl)HD~0<#Uq>0MgjVD_zHa$zxp@BaU)!_Bo9Tq5nq@D@QYe;$SJzb} zq>?42KSfvS(a zVL2*aV7f^cXHHLJs%9X#Bl%U|6Jty_RK*-OO|k4K)6DBhimi^xRo!wUQRFJLY*E2W zkcDJiJ9L^k4p8%@DkfP1KUDDwSR`%>g;j0-F^a>poryW)7&d@RlA+IV4W zPd*-p7Ru0Tx02~?hLIP~uw{c=&l00mP1|$4dE3?OfAwLc=s2uk}?*BqWE~al4pJgA1%RKIHngn|NFR literal 0 HcmV?d00001 diff --git a/dummyserver/__init__.py b/testserver/__init__.py similarity index 100% rename from dummyserver/__init__.py rename to testserver/__init__.py diff --git a/dummyserver/server.py b/testserver/server.py similarity index 94% rename from dummyserver/server.py rename to testserver/server.py index 22c5d90f..14349fb9 100644 --- a/dummyserver/server.py +++ b/testserver/server.py @@ -2,11 +2,8 @@ import threading, socket - - - class Server(threading.Thread): - """ Dummy server using for unit testing """ + """ Basic socket server used for unit testing """ def __init__(self, handler, host='localhost', port=8021): threading.Thread.__init__(self) From ab0f063d85d01a707516c84881c0a698edc526cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 25 Nov 2015 14:15:51 +0100 Subject: [PATCH 05/40] Made TestServer.Server listen on an arbitrary open port by default --- testserver/.server.py.swo | Bin 12288 -> 0 bytes testserver/server.py | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) delete mode 100644 testserver/.server.py.swo diff --git a/testserver/.server.py.swo b/testserver/.server.py.swo deleted file mode 100644 index eb2d89d951ba5e633d389c0c2bc56934ae95a5e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2y=xRf9EK-?VAQB6Ho;SH{&_+RQ6tohwQG91V?k=a8A_xY41JBK7=j)wkZUZ4(DbG$_ z;b)A~4CM%8jYl)HD~0<#Uq>0MgjVD_zHa$zxp@BaU)!_Bo9Tq5nq@D@QYe;$SJzb} zq>?42KSfvS(a zVL2*aV7f^cXHHLJs%9X#Bl%U|6Jty_RK*-OO|k4K)6DBhimi^xRo!wUQRFJLY*E2W zkcDJiJ9L^k4p8%@DkfP1KUDDwSR`%>g;j0-F^a>poryW)7&d@RlA+IV4W zPd*-p7Ru0Tx02~?hLIP~uw{c=&l00mP1|$4dE3?OfAwLc=s2uk}?*BqWE~al4pJgA1%RKIHngn|NFR diff --git a/testserver/server.py b/testserver/server.py index 14349fb9..689aaaf8 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -3,9 +3,9 @@ import threading, socket class Server(threading.Thread): - """ Basic socket server used for unit testing """ + """ Dummy server using for unit testing """ - def __init__(self, handler, host='localhost', port=8021): + def __init__(self, handler, host='localhost', port=0): threading.Thread.__init__(self) self.handler = handler self.host = host @@ -16,6 +16,9 @@ class Server(threading.Thread): def run(self): sock = socket.socket() sock.bind((self.host, self.port)) + + # update port in case self.port = 0 + self.port = sock.getsockname()[1] sock.listen(0) self.ready_event.set() self.handler(sock) From 2ad3f079821769062ad6b8e91c927b1b345895d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 25 Nov 2015 14:41:03 +0100 Subject: [PATCH 06/40] Make exceptions in the testserver.Server thread not block the main thread --- testserver/server.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/testserver/server.py b/testserver/server.py index 689aaaf8..6fa6464e 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -14,16 +14,23 @@ class Server(threading.Thread): self.stop_event = threading.Event() def run(self): + try: + sock = self._create_socket_and_bind() + # in case self.port = 0 + self.port = sock.getsockname()[1] + self.ready_event.set() + self.handler(sock) + + finally: + self.ready_event.set() # just in case of exception + self.stop_event.set() + sock.close() + + def _create_socket_and_bind(self): sock = socket.socket() sock.bind((self.host, self.port)) - - # update port in case self.port = 0 - self.port = sock.getsockname()[1] sock.listen(0) - self.ready_event.set() - self.handler(sock) - self.stop_event.set() - sock.close() + return sock def __enter__(self): self.start() From 11ad502b80a10d3c4fe5631509f893a7bd20c2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 26 Nov 2015 00:29:53 +0100 Subject: [PATCH 07/40] Added basic_response_server classmethod and tested it --- test_requests.py | 7 +++++++ testserver/server.py | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/test_requests.py b/test_requests.py index 926abe2e..75253eb3 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1756,5 +1756,12 @@ class TestTestServer(unittest.TestCase): assert text == answer sock.close() + def test_basic_response(self): + with Server.basic_response_server() as (host, port): + r = requests.get('http://{}:{}'.format(host, port)) + assert r.status_code == 200 + assert r.text == '' + assert r.headers['Content-Length'] == '0' + if __name__ == '__main__': unittest.main() diff --git a/testserver/server.py b/testserver/server.py index 6fa6464e..f19cc3c7 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -13,6 +13,19 @@ class Server(threading.Thread): self.ready_event = threading.Event() self.stop_event = threading.Event() + @classmethod + def basic_response_server(cls, host='localhost', port=0): + def basic_response_handler(server_sock): + sock, _ = server_sock.accept() + sock.send( + b'HTTP/1.1 200 OK\r\n' + b'Content-Length: 0\r\n' + b'\r\n' + ) + + server = Server(basic_response_handler, host=host, port=port) + return server + def run(self): try: sock = self._create_socket_and_bind() From f7917c305a4f05a86a3ae058036e2205dc0f47e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 26 Nov 2015 01:04:27 +0100 Subject: [PATCH 08/40] Make server set stop_event right after closing its socket --- testserver/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testserver/server.py b/testserver/server.py index f19cc3c7..e329a9fc 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -36,8 +36,8 @@ class Server(threading.Thread): finally: self.ready_event.set() # just in case of exception - self.stop_event.set() sock.close() + self.stop_event.set() def _create_socket_and_bind(self): sock = socket.socket() From b4b4661f461a132c6815daa3719a3200553464a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 26 Nov 2015 01:05:16 +0100 Subject: [PATCH 09/40] Implemented test to verify that the context manager exits after the server is closed --- test_requests.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test_requests.py b/test_requests.py index 75253eb3..2d433f95 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1756,6 +1756,16 @@ class TestTestServer(unittest.TestCase): assert text == answer sock.close() + def test_server_closes(self): + with Server.basic_response_server() as (host, port): + sock = socket.socket() + sock.connect((host, port)) + + with pytest.raises(socket.error): + new_sock = socket.socket() + new_sock.connect((host, port)) + sock.close() + def test_basic_response(self): with Server.basic_response_server() as (host, port): r = requests.get('http://{}:{}'.format(host, port)) From 6adabacd81d8e453c3915f8a98692c9891df022b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 26 Nov 2015 01:11:18 +0100 Subject: [PATCH 10/40] Close socket properly in test_server_closes --- test_requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_requests.py b/test_requests.py index 2d433f95..e54e6f01 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1760,11 +1760,11 @@ class TestTestServer(unittest.TestCase): with Server.basic_response_server() as (host, port): sock = socket.socket() sock.connect((host, port)) + sock.close() with pytest.raises(socket.error): new_sock = socket.socket() new_sock.connect((host, port)) - sock.close() def test_basic_response(self): with Server.basic_response_server() as (host, port): From 6551c290fdbf0b29e4534abef1b04f7485a88aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 2 Dec 2015 01:52:32 +0100 Subject: [PATCH 11/40] Allow main thread to block testserver before closing --- testserver/server.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/testserver/server.py b/testserver/server.py index e329a9fc..5c5d8069 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -1,39 +1,47 @@ #!/usr/bin/python -import threading, socket +import threading +import socket + +def consume_socket(sock, chunks=65536): + while not sock.recv(chunks).endswith(b'\r\n\r\n'): + pass + class Server(threading.Thread): """ Dummy server using for unit testing """ - def __init__(self, handler, host='localhost', port=0): + def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): threading.Thread.__init__(self) self.handler = handler self.host = host self.port = port + self.requests_to_handle = requests_to_handle + + self.wait_to_close_event = wait_to_close_event self.ready_event = threading.Event() self.stop_event = threading.Event() @classmethod - def basic_response_server(cls, host='localhost', port=0): - def basic_response_handler(server_sock): - sock, _ = server_sock.accept() + def basic_response_server(cls, **kwargs): + def basic_response_handler(sock): sock.send( b'HTTP/1.1 200 OK\r\n' b'Content-Length: 0\r\n' b'\r\n' ) - server = Server(basic_response_handler, host=host, port=port) + server = Server(basic_response_handler, **kwargs) return server + def run(self): try: sock = self._create_socket_and_bind() # in case self.port = 0 self.port = sock.getsockname()[1] self.ready_event.set() - self.handler(sock) - + self._handle_requests_and_close_server(sock) finally: self.ready_event.set() # just in case of exception sock.close() @@ -45,6 +53,14 @@ class Server(threading.Thread): sock.listen(0) return sock + def _handle_requests_and_close_server(self, server_sock): + for _ in range(self.requests_to_handle): + sock = server_sock.accept()[0] + self.handler(sock) + + if self.wait_to_close_event: + self.wait_to_close_event.wait() + def __enter__(self): self.start() self.ready_event.wait() From aac32ac56e60ac220a15c33d207306806c193d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 2 Dec 2015 01:53:39 +0100 Subject: [PATCH 12/40] Updated tests relying on the old testserver and added basic test for chunked uploads --- test_requests.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/test_requests.py b/test_requests.py index e54e6f01..5c91c20a 100755 --- a/test_requests.py +++ b/test_requests.py @@ -31,6 +31,8 @@ from requests.models import urlencode from requests.hooks import default_hooks from testserver.server import Server import socket +import threading +import time try: import StringIO @@ -1179,6 +1181,24 @@ class TestContentEncodingDetection(unittest.TestCase): encodings = requests.utils.get_encodings_from_content(content) assert encodings == ['HTML5', 'HTML4', 'XML'] + def test_chunked_upload(self): + """ can safely send generators """ + block_server = threading.Event() + server = Server.basic_response_server(wait_to_close_event=block_server) + data = (i for i in [b'a', b'b', b'c']) + + with server as (host, port): + url = 'http://{}:{}/'.format(host, port) + r = requests.post(url, data=data, stream=True) + block_server.set() # release server block + + assert r.status_code == 200 + assert r.request.headers['Transfer-Encoding'] == 'chunked' + + + + + class TestCaseInsensitiveDict(unittest.TestCase): @@ -1742,8 +1762,7 @@ class TestTestServer(unittest.TestCase): def test_basic(self): question = b"sucess?" answer = b"yeah, success" - def handler(server_sock): - sock, _ = server_sock.accept() + def handler(sock): text = sock.recv(1000) assert text == question sock.send(answer) @@ -1773,5 +1792,16 @@ class TestTestServer(unittest.TestCase): assert r.text == '' assert r.headers['Content-Length'] == '0' + def test_basic_waiting_server(self): + block_server = threading.Event() + + with Server.basic_response_server(wait_to_close_event=block_server) as (host, port): + sock = socket.socket() + sock.connect((host, port)) + sock.send(b'send something') + time.sleep(2.5) + sock.send(b'still alive') + block_server.set() # release server block + if __name__ == '__main__': unittest.main() From 5ecf789a6f2c50a69854e2663083aeea1a0ff683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Wed, 2 Dec 2015 02:02:09 +0100 Subject: [PATCH 13/40] Avoid server from blocking if an exception is found in the main thread --- testserver/server.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testserver/server.py b/testserver/server.py index 5c5d8069..fd6bca40 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -69,5 +69,10 @@ class Server(threading.Thread): def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: self.stop_event.wait() + else: + if self.wait_to_close_event: + # avoid server from blocking if an exception is found + # in the main thread + self.wait_to_close_event.set() return False # allow exceptions to propagate From 3b2a489e13a2dc3c9d1ef919ad35e14cc5189f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 8 Dec 2015 16:12:40 +0100 Subject: [PATCH 14/40] Added text_response_server classmethod to TestServer and updated basic_response_server to use it --- testserver/server.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/testserver/server.py b/testserver/server.py index fd6bca40..8361b58f 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -23,17 +23,22 @@ class Server(threading.Thread): self.stop_event = threading.Event() @classmethod - def basic_response_server(cls, **kwargs): - def basic_response_handler(sock): - sock.send( - b'HTTP/1.1 200 OK\r\n' - b'Content-Length: 0\r\n' - b'\r\n' - ) + def text_response_server(cls, text, **kwargs): + def text_response_handler(sock): + sock.send(text.encode()) + + server = Server(text_response_handler, **kwargs) - server = Server(basic_response_handler, **kwargs) return server + @classmethod + def basic_response_server(cls, **kwargs): + server = cls.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 0\r\n\r\n", **kwargs + ) + + return server def run(self): try: From 4a41c591f88c3be7bb1319c8e6b8eba631fea8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 8 Dec 2015 16:23:02 +0100 Subject: [PATCH 15/40] Tested text_response_server --- test_requests.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test_requests.py b/test_requests.py index 5c91c20a..29773bda 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1784,6 +1784,20 @@ class TestTestServer(unittest.TestCase): with pytest.raises(socket.error): new_sock = socket.socket() new_sock.connect((host, port)) + + def test_text_response(self): + server = Server.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 6\r\n" + + "\r\nroflol" + ) + + with server as (host, port): + r = requests.get('http://{}:{}'.format(host, port)) + + assert r.status_code == 200 + assert r.text == 'roflol' + assert r.headers['Content-Length'] == '6' def test_basic_response(self): with Server.basic_response_server() as (host, port): From 578b03255594d446b4fc8c6e00ec67dd3c8b440f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 8 Dec 2015 16:37:03 +0100 Subject: [PATCH 16/40] Tested TestServer multiple request handling --- test_requests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test_requests.py b/test_requests.py index 29773bda..aa591ef5 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1817,5 +1817,22 @@ class TestTestServer(unittest.TestCase): sock.send(b'still alive') block_server.set() # release server block + def test_multiple_requests(self): + requests_to_handle = 5 + + server = Server.basic_response_server(requests_to_handle=requests_to_handle) + + with server as (host, port): + server_url = 'http://{}:{}'.format(host, port) + for _ in range(requests_to_handle): + r = requests.get(server_url) + assert r.status_code == 200 + + # the (n+1)th request fails + with pytest.raises(requests.exceptions.ConnectionError): + r = requests.get(server_url) + + + if __name__ == '__main__': unittest.main() From 3eeea3771b274e1089317faa302730e74203b37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 8 Dec 2015 20:40:58 +0100 Subject: [PATCH 17/40] Added a way for TestServer request handlers to store data for later retrieval by the main thread (actual requests, for example) --- test_requests.py | 22 +++++++++++++++++++++- testserver/server.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/test_requests.py b/test_requests.py index aa591ef5..4e97bd66 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1779,6 +1779,7 @@ class TestTestServer(unittest.TestCase): with Server.basic_response_server() as (host, port): sock = socket.socket() sock.connect((host, port)) + sock.close() with pytest.raises(socket.error): @@ -1797,7 +1798,7 @@ class TestTestServer(unittest.TestCase): assert r.status_code == 200 assert r.text == 'roflol' - assert r.headers['Content-Length'] == '6' + assert r.headers['Content-Length'] == '6' def test_basic_response(self): with Server.basic_response_server() as (host, port): @@ -1832,6 +1833,25 @@ class TestTestServer(unittest.TestCase): with pytest.raises(requests.exceptions.ConnectionError): r = requests.get(server_url) + def test_request_recovery(self): + server = Server.basic_response_server(requests_to_handle=2) + first_request = "put your hands up in the air" + second_request = "put your hand down in the floor" + + with server as address: + sock1 = socket.socket() + sock2 = socket.socket() + + sock1.connect(address) + sock1.send(first_request.encode()) + sock1.close() + + sock2.connect(address) + sock2.send(second_request.encode()) + sock2.close() + + assert server.handler_results[0] == first_request + assert server.handler_results[1] == second_request if __name__ == '__main__': diff --git a/testserver/server.py b/testserver/server.py index 8361b58f..c5a7ad5b 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -2,18 +2,35 @@ import threading import socket +import select -def consume_socket(sock, chunks=65536): - while not sock.recv(chunks).endswith(b'\r\n\r\n'): - pass +def consume_socket_content(sock, chunks=65536, timeout=0.5): + content = "" + more_to_read = select.select([sock], [], [], timeout)[0] + + while more_to_read: + new_content = sock.recv(chunks).decode("utf-8") + + if len(new_content) == 0: + more_to_read = False # empty recv means the socket disconnected + + else: + content += new_content + # stop reading if no new data is received for a while + more_to_read = select.select([sock], [], [], timeout)[0] + + return content class Server(threading.Thread): """ Dummy server using for unit testing """ def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): threading.Thread.__init__(self) + self.handler = handler + self.handler_results = [] + self.host = host self.port = port self.requests_to_handle = requests_to_handle @@ -23,10 +40,14 @@ class Server(threading.Thread): self.stop_event = threading.Event() @classmethod - def text_response_server(cls, text, **kwargs): + def text_response_server(cls, text, request_timeout=0.5, **kwargs): def text_response_handler(sock): + request_content = consume_socket_content(sock, timeout=request_timeout) sock.send(text.encode()) + return request_content + + server = Server(text_response_handler, **kwargs) return server @@ -61,7 +82,9 @@ class Server(threading.Thread): def _handle_requests_and_close_server(self, server_sock): for _ in range(self.requests_to_handle): sock = server_sock.accept()[0] - self.handler(sock) + handler_result = self.handler(sock) + + self.handler_results.append(handler_result) if self.wait_to_close_event: self.wait_to_close_event.wait() From 534ee814fcb9d7b563413ea77ce6838090ead25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Tue, 8 Dec 2015 20:54:12 +0100 Subject: [PATCH 18/40] Tested timeouts in text_response_server requests retrieval --- test_requests.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test_requests.py b/test_requests.py index 4e97bd66..f24c775c 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1853,6 +1853,31 @@ class TestTestServer(unittest.TestCase): assert server.handler_results[0] == first_request assert server.handler_results[1] == second_request + def test_requests_after_timeout_are_not_received(self): + server = Server.basic_response_server(request_timeout=1) + + with server as address: + sock = socket.socket() + sock.connect(address) + time.sleep(1.5) + sock.send(b"hehehe, not received") + sock.close() + + assert server.handler_results[0] == "" + + + def test_request_recovery_with_bigger_timeout(self): + server = Server.basic_response_server(request_timeout=3) + data = "bananadine" + + with server as address: + sock = socket.socket() + sock.connect(address) + time.sleep(1.5) + sock.send(data.encode()) + sock.close() + + assert server.handler_results[0] == data if __name__ == '__main__': unittest.main() From fa91b0ab7ce45389357a4fc9f33785514b265b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 20:07:42 +0100 Subject: [PATCH 19/40] Fixed style --- test_requests.py | 11 ++--------- testserver/server.py | 16 +++++++--------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/test_requests.py b/test_requests.py index f24c775c..ea57daae 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1186,19 +1186,12 @@ class TestContentEncodingDetection(unittest.TestCase): block_server = threading.Event() server = Server.basic_response_server(wait_to_close_event=block_server) data = (i for i in [b'a', b'b', b'c']) - with server as (host, port): url = 'http://{}:{}/'.format(host, port) r = requests.post(url, data=data, stream=True) block_server.set() # release server block - - assert r.status_code == 200 - assert r.request.headers['Transfer-Encoding'] == 'chunked' - - - - - + assert r.status_code == 200 + assert r.request.headers['Transfer-Encoding'] == 'chunked' class TestCaseInsensitiveDict(unittest.TestCase): diff --git a/testserver/server.py b/testserver/server.py index c5a7ad5b..a1a3fd0f 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -5,20 +5,20 @@ import socket import select -def consume_socket_content(sock, chunks=65536, timeout=0.5): +def consume_socket_content(sock, timeout=0.5): + chunks = 65536 content = "" more_to_read = select.select([sock], [], [], timeout)[0] while more_to_read: new_content = sock.recv(chunks).decode("utf-8") - if len(new_content) == 0: - more_to_read = False # empty recv means the socket disconnected + if not new_content: + break - else: - content += new_content - # stop reading if no new data is received for a while - more_to_read = select.select([sock], [], [], timeout)[0] + content += new_content + # stop reading if no new data is received for a while + more_to_read = select.select([sock], [], [], timeout)[0] return content @@ -49,7 +49,6 @@ class Server(threading.Thread): server = Server(text_response_handler, **kwargs) - return server @classmethod @@ -58,7 +57,6 @@ class Server(threading.Thread): "HTTP/1.1 200 OK\r\n" + "Content-Length: 0\r\n\r\n", **kwargs ) - return server def run(self): From 241656355bbc03f24d04578e3e523bee9ca70269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 20:09:13 +0100 Subject: [PATCH 20/40] Changed whitespace in docstring --- test_requests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test_requests.py b/test_requests.py index ea57daae..6c7b295b 100755 --- a/test_requests.py +++ b/test_requests.py @@ -1182,14 +1182,16 @@ class TestContentEncodingDetection(unittest.TestCase): assert encodings == ['HTML5', 'HTML4', 'XML'] def test_chunked_upload(self): - """ can safely send generators """ + """can safely send generators""" block_server = threading.Event() server = Server.basic_response_server(wait_to_close_event=block_server) data = (i for i in [b'a', b'b', b'c']) + with server as (host, port): url = 'http://{}:{}/'.format(host, port) r = requests.post(url, data=data, stream=True) block_server.set() # release server block + assert r.status_code == 200 assert r.request.headers['Transfer-Encoding'] == 'chunked' From 9ac5a6e4aea4ba76c515291be3682aac262e34d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 21:11:17 +0100 Subject: [PATCH 21/40] Fixed encoding issues, added timeouts to event waits and refactored Server --- testserver/server.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/testserver/server.py b/testserver/server.py index a1a3fd0f..153775bd 100644 --- a/testserver/server.py +++ b/testserver/server.py @@ -11,7 +11,7 @@ def consume_socket_content(sock, timeout=0.5): more_to_read = select.select([sock], [], [], timeout)[0] while more_to_read: - new_content = sock.recv(chunks).decode("utf-8") + new_content = sock.recv(chunks) if not new_content: break @@ -22,8 +22,11 @@ def consume_socket_content(sock, timeout=0.5): return content + + class Server(threading.Thread): """ Dummy server using for unit testing """ + WAIT_EVENT_TIMEOUT = 5 def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): threading.Thread.__init__(self) @@ -43,7 +46,7 @@ class Server(threading.Thread): def text_response_server(cls, text, request_timeout=0.5, **kwargs): def text_response_handler(sock): request_content = consume_socket_content(sock, timeout=request_timeout) - sock.send(text.encode()) + sock.send(text.encode('utf-8')) return request_content @@ -65,7 +68,10 @@ class Server(threading.Thread): # in case self.port = 0 self.port = sock.getsockname()[1] self.ready_event.set() - self._handle_requests_and_close_server(sock) + self._handle_requests(sock) + + if self.wait_to_close_event: + self.wait_to_close_event.wait(self.WAIT_EVENT_TIMEOUT) finally: self.ready_event.set() # just in case of exception sock.close() @@ -77,28 +83,25 @@ class Server(threading.Thread): sock.listen(0) return sock - def _handle_requests_and_close_server(self, server_sock): + def _handle_requests(self, server_sock): for _ in range(self.requests_to_handle): sock = server_sock.accept()[0] handler_result = self.handler(sock) self.handler_results.append(handler_result) - if self.wait_to_close_event: - self.wait_to_close_event.wait() - def __enter__(self): self.start() - self.ready_event.wait() + self.ready_event.wait(self.WAIT_EVENT_TIMEOUT) return self.host, self.port def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: - self.stop_event.wait() + self.stop_event.wait(self.WAIT_EVENT_TIMEOUT) else: if self.wait_to_close_event: - # avoid server from blocking if an exception is found - # in the main thread + # avoid server from waiting for event timeouts + # if an exception is found in the main thread self.wait_to_close_event.set() return False # allow exceptions to propagate From ca35c847a203b264edb57a2d6d3a2700ac69dcde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 21:52:59 +0100 Subject: [PATCH 22/40] Moved testserver to tests/ --- tests/testserver/.server.py.swo | Bin 0 -> 12288 bytes tests/testserver/__init__.py | 0 tests/testserver/server.py | 107 ++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 tests/testserver/.server.py.swo create mode 100644 tests/testserver/__init__.py create mode 100644 tests/testserver/server.py diff --git a/tests/testserver/.server.py.swo b/tests/testserver/.server.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..940c6b1d913a7e002873b66969af9f95bc6379ef GIT binary patch literal 12288 zcmeHNO^6&t6s}bvMvaPIMJuz&&cbZ>Yz#!AtA=Qd8vk&UgIQ^6dTMq$>FI8}syCU7 zf_f7#ddo>c5D)R7HxD@p!GpQzSudg@=t({My{i7(*&jCqgg_O1U9xHNyz+DT zrc5@dE2PrO*YuS6hRl82dD*m@>UyVuQ{YAvDD-IQ(F3O+IkeoTW#&5v`Th5uzL6E( zT&I9jz$xGqa0)mDoB~b(r+`!7CR0FXbL?$!zNO@SyzJ*@`tncLIR%^oP64NYQ@|<{1v;CtXJ;9cMy;91}y zfC0bW&Db^I6QBSz5CRVae;r`#Ti{FJeP94Q4?GS$2K;>&V?O~u0^b4e0j~o-&;f1( zZUw%%ld&&=%fKbz1K=!h1lSM!atC8qfvub06YX6Pk?tG}qPk#+FMloNmjml$M*}3*((XzIL-k5ZBsiAic({<;?FZP|Jw`_?SBdCj~< z+oiJ+CF?<{MUPWitk~M1=vL^l*c2QEPjj{{UNX)cMa0zOfeDLvn4(tmPhOX9P4cQO2McTYTCz}6XvUAHIPr;IIwg~JJwD3&J2{?QU46x0_Lljf zexJYm!d5qPz?8(f-?R-4?=dsmhrDZoYJJ)nGNpCBSuw|>L)zPUf!!>Coe%&tXi z_ULpv{OMvcnc|9|qrnRW5%?&@C+x%N-FO;+A2S7Bo$*;>bW21N6MAjJHx&v(YW&JQ R=oc#Yai#m&6elEM{{pZ=xYGat literal 0 HcmV?d00001 diff --git a/tests/testserver/__init__.py b/tests/testserver/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/testserver/server.py b/tests/testserver/server.py new file mode 100644 index 00000000..153775bd --- /dev/null +++ b/tests/testserver/server.py @@ -0,0 +1,107 @@ +#!/usr/bin/python + +import threading +import socket +import select + + +def consume_socket_content(sock, timeout=0.5): + chunks = 65536 + content = "" + more_to_read = select.select([sock], [], [], timeout)[0] + + while more_to_read: + new_content = sock.recv(chunks) + + if not new_content: + break + + content += new_content + # stop reading if no new data is received for a while + more_to_read = select.select([sock], [], [], timeout)[0] + + return content + + + +class Server(threading.Thread): + """ Dummy server using for unit testing """ + WAIT_EVENT_TIMEOUT = 5 + + def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): + threading.Thread.__init__(self) + + self.handler = handler + self.handler_results = [] + + self.host = host + self.port = port + self.requests_to_handle = requests_to_handle + + self.wait_to_close_event = wait_to_close_event + self.ready_event = threading.Event() + self.stop_event = threading.Event() + + @classmethod + def text_response_server(cls, text, request_timeout=0.5, **kwargs): + def text_response_handler(sock): + request_content = consume_socket_content(sock, timeout=request_timeout) + sock.send(text.encode('utf-8')) + + return request_content + + + server = Server(text_response_handler, **kwargs) + return server + + @classmethod + def basic_response_server(cls, **kwargs): + server = cls.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 0\r\n\r\n", **kwargs + ) + return server + + def run(self): + try: + sock = self._create_socket_and_bind() + # in case self.port = 0 + self.port = sock.getsockname()[1] + self.ready_event.set() + self._handle_requests(sock) + + if self.wait_to_close_event: + self.wait_to_close_event.wait(self.WAIT_EVENT_TIMEOUT) + finally: + self.ready_event.set() # just in case of exception + sock.close() + self.stop_event.set() + + def _create_socket_and_bind(self): + sock = socket.socket() + sock.bind((self.host, self.port)) + sock.listen(0) + return sock + + def _handle_requests(self, server_sock): + for _ in range(self.requests_to_handle): + sock = server_sock.accept()[0] + handler_result = self.handler(sock) + + self.handler_results.append(handler_result) + + def __enter__(self): + self.start() + self.ready_event.wait(self.WAIT_EVENT_TIMEOUT) + return self.host, self.port + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + self.stop_event.wait(self.WAIT_EVENT_TIMEOUT) + else: + if self.wait_to_close_event: + # avoid server from waiting for event timeouts + # if an exception is found in the main thread + self.wait_to_close_event.set() + return False # allow exceptions to propagate + From 75a9a981b58dc4866acaa2b95b08a8c2ffa914d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 22:00:08 +0100 Subject: [PATCH 23/40] Removed unnecessary files --- tests/testserver/.server.py.swo | Bin 12288 -> 0 bytes testserver/__init__.py | 0 testserver/server.py | 107 -------------------------------- 3 files changed, 107 deletions(-) delete mode 100644 tests/testserver/.server.py.swo delete mode 100644 testserver/__init__.py delete mode 100644 testserver/server.py diff --git a/tests/testserver/.server.py.swo b/tests/testserver/.server.py.swo deleted file mode 100644 index 940c6b1d913a7e002873b66969af9f95bc6379ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHNO^6&t6s}bvMvaPIMJuz&&cbZ>Yz#!AtA=Qd8vk&UgIQ^6dTMq$>FI8}syCU7 zf_f7#ddo>c5D)R7HxD@p!GpQzSudg@=t({My{i7(*&jCqgg_O1U9xHNyz+DT zrc5@dE2PrO*YuS6hRl82dD*m@>UyVuQ{YAvDD-IQ(F3O+IkeoTW#&5v`Th5uzL6E( zT&I9jz$xGqa0)mDoB~b(r+`!7CR0FXbL?$!zNO@SyzJ*@`tncLIR%^oP64NYQ@|<{1v;CtXJ;9cMy;91}y zfC0bW&Db^I6QBSz5CRVae;r`#Ti{FJeP94Q4?GS$2K;>&V?O~u0^b4e0j~o-&;f1( zZUw%%ld&&=%fKbz1K=!h1lSM!atC8qfvub06YX6Pk?tG}qPk#+FMloNmjml$M*}3*((XzIL-k5ZBsiAic({<;?FZP|Jw`_?SBdCj~< z+oiJ+CF?<{MUPWitk~M1=vL^l*c2QEPjj{{UNX)cMa0zOfeDLvn4(tmPhOX9P4cQO2McTYTCz}6XvUAHIPr;IIwg~JJwD3&J2{?QU46x0_Lljf zexJYm!d5qPz?8(f-?R-4?=dsmhrDZoYJJ)nGNpCBSuw|>L)zPUf!!>Coe%&tXi z_ULpv{OMvcnc|9|qrnRW5%?&@C+x%N-FO;+A2S7Bo$*;>bW21N6MAjJHx&v(YW&JQ R=oc#Yai#m&6elEM{{pZ=xYGat diff --git a/testserver/__init__.py b/testserver/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/testserver/server.py b/testserver/server.py deleted file mode 100644 index 153775bd..00000000 --- a/testserver/server.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/python - -import threading -import socket -import select - - -def consume_socket_content(sock, timeout=0.5): - chunks = 65536 - content = "" - more_to_read = select.select([sock], [], [], timeout)[0] - - while more_to_read: - new_content = sock.recv(chunks) - - if not new_content: - break - - content += new_content - # stop reading if no new data is received for a while - more_to_read = select.select([sock], [], [], timeout)[0] - - return content - - - -class Server(threading.Thread): - """ Dummy server using for unit testing """ - WAIT_EVENT_TIMEOUT = 5 - - def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): - threading.Thread.__init__(self) - - self.handler = handler - self.handler_results = [] - - self.host = host - self.port = port - self.requests_to_handle = requests_to_handle - - self.wait_to_close_event = wait_to_close_event - self.ready_event = threading.Event() - self.stop_event = threading.Event() - - @classmethod - def text_response_server(cls, text, request_timeout=0.5, **kwargs): - def text_response_handler(sock): - request_content = consume_socket_content(sock, timeout=request_timeout) - sock.send(text.encode('utf-8')) - - return request_content - - - server = Server(text_response_handler, **kwargs) - return server - - @classmethod - def basic_response_server(cls, **kwargs): - server = cls.text_response_server( - "HTTP/1.1 200 OK\r\n" + - "Content-Length: 0\r\n\r\n", **kwargs - ) - return server - - def run(self): - try: - sock = self._create_socket_and_bind() - # in case self.port = 0 - self.port = sock.getsockname()[1] - self.ready_event.set() - self._handle_requests(sock) - - if self.wait_to_close_event: - self.wait_to_close_event.wait(self.WAIT_EVENT_TIMEOUT) - finally: - self.ready_event.set() # just in case of exception - sock.close() - self.stop_event.set() - - def _create_socket_and_bind(self): - sock = socket.socket() - sock.bind((self.host, self.port)) - sock.listen(0) - return sock - - def _handle_requests(self, server_sock): - for _ in range(self.requests_to_handle): - sock = server_sock.accept()[0] - handler_result = self.handler(sock) - - self.handler_results.append(handler_result) - - def __enter__(self): - self.start() - self.ready_event.wait(self.WAIT_EVENT_TIMEOUT) - return self.host, self.port - - def __exit__(self, exc_type, exc_value, traceback): - if exc_type is None: - self.stop_event.wait(self.WAIT_EVENT_TIMEOUT) - else: - if self.wait_to_close_event: - # avoid server from waiting for event timeouts - # if an exception is found in the main thread - self.wait_to_close_event.set() - return False # allow exceptions to propagate - From 567b31080e62fd52bb9b8fb778736eb05359daa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 22:00:27 +0100 Subject: [PATCH 24/40] Fixed formatting error in python2.6 --- tests/test_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 29dd4b85..bc585287 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -164,7 +164,7 @@ class TestContentEncodingDetection: data = (i for i in [b'a', b'b', b'c']) with server as (host, port): - url = 'http://{}:{}/'.format(host, port) + url = 'http://{0}:{1}/'.format(host, port) r = requests.post(url, data=data, stream=True) block_server.set() # release server block @@ -288,7 +288,7 @@ class TestTestServer: ) with server as (host, port): - r = requests.get('http://{}:{}'.format(host, port)) + r = requests.get('http://{0}:{1}'.format(host, port)) assert r.status_code == 200 assert r.text == 'roflol' @@ -296,7 +296,7 @@ class TestTestServer: def test_basic_response(self): with Server.basic_response_server() as (host, port): - r = requests.get('http://{}:{}'.format(host, port)) + r = requests.get('http://{0}:{1}'.format(host, port)) assert r.status_code == 200 assert r.text == '' assert r.headers['Content-Length'] == '0' @@ -318,7 +318,7 @@ class TestTestServer: server = Server.basic_response_server(requests_to_handle=requests_to_handle) with server as (host, port): - server_url = 'http://{}:{}'.format(host, port) + server_url = 'http://{0}:{1}'.format(host, port) for _ in range(requests_to_handle): r = requests.get(server_url) assert r.status_code == 200 From f17ef753d2c1f4db0d7f5aec51261da1db20d611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Thu, 3 Mar 2016 22:13:47 +0100 Subject: [PATCH 25/40] Moved test_chunked_upload to test_requests.py --- tests/test_utils.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index bc585287..3990780a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -157,23 +157,6 @@ class TestContentEncodingDetection: '''.strip() assert get_encodings_from_content(content) == ['HTML5', 'HTML4', 'XML'] - def test_chunked_upload(self): - """can safely send generators""" - block_server = threading.Event() - server = Server.basic_response_server(wait_to_close_event=block_server) - data = (i for i in [b'a', b'b', b'c']) - - with server as (host, port): - url = 'http://{0}:{1}/'.format(host, port) - r = requests.post(url, data=data, stream=True) - block_server.set() # release server block - - assert r.status_code == 200 - assert r.request.headers['Transfer-Encoding'] == 'chunked' - - - - USER = PASSWORD = "%!*'();:@&=+$,/?#[] " ENCODED_USER = compat.quote(USER, '') ENCODED_PASSWORD = compat.quote(PASSWORD, '') From e3ad31f3be58790b719c4798f4f3dbdc19518819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Fri, 4 Mar 2016 19:21:32 +0100 Subject: [PATCH 26/40] Added test_chunked_upload to test_requests.py --- tests/test_requests.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index efb93d3a..c70008f0 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -9,6 +9,7 @@ import os import pickle import collections import contextlib +import threading import io import requests @@ -27,6 +28,7 @@ from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks +from testserver.server import Server from .compat import StringIO, u # Requests to this URL should always fail with a connection timeout (nothing @@ -1452,6 +1454,23 @@ def test_vendor_aliases(): with pytest.raises(ImportError): from requests.packages import webbrowser +def test_chunked_upload(): + """can safely send generators""" + block_server = threading.Event() + server = Server.basic_response_server(wait_to_close_event=block_server) + data = (i for i in [b'a', b'b', b'c']) + + with server as (host, port): + url = 'http://{0}:{1}/'.format(host, port) + r = requests.post(url, data=data, stream=True) + block_server.set() # release server block + + assert r.status_code == 200 + assert r.request.headers['Transfer-Encoding'] == 'chunked' + + + + if __name__ == '__main__': From bf026e3c3109ee3d5948f674df120e97e3c3fb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Fri, 4 Mar 2016 19:24:15 +0100 Subject: [PATCH 27/40] Removed unittest execution chunk --- tests/test_requests.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index c70008f0..ab1916ce 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1467,11 +1467,3 @@ def test_chunked_upload(): assert r.status_code == 200 assert r.request.headers['Transfer-Encoding'] == 'chunked' - - - - - - -if __name__ == '__main__': - unittest.main() From 0d1a779030c1b26f9decda889b3e140d89bdeef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Fri, 4 Mar 2016 19:33:58 +0100 Subject: [PATCH 28/40] Fixed style issues --- tests/testserver/server.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/testserver/server.py b/tests/testserver/server.py index 153775bd..b9d64289 100644 --- a/tests/testserver/server.py +++ b/tests/testserver/server.py @@ -1,10 +1,7 @@ -#!/usr/bin/python - import threading import socket import select - def consume_socket_content(sock, timeout=0.5): chunks = 65536 content = "" @@ -17,19 +14,17 @@ def consume_socket_content(sock, timeout=0.5): break content += new_content - # stop reading if no new data is received for a while + # stop reading if no new data is received for a while more_to_read = select.select([sock], [], [], timeout)[0] return content - - class Server(threading.Thread): - """ Dummy server using for unit testing """ + """Dummy server using for unit testing""" WAIT_EVENT_TIMEOUT = 5 def __init__(self, handler, host='localhost', port=0, requests_to_handle=1, wait_to_close_event=None): - threading.Thread.__init__(self) + super(Server, self).__init__() self.handler = handler self.handler_results = [] @@ -51,16 +46,15 @@ class Server(threading.Thread): return request_content - server = Server(text_response_handler, **kwargs) - return server + return Server(text_response_handler, **kwargs) @classmethod def basic_response_server(cls, **kwargs): - server = cls.text_response_server( + return cls.text_response_server( "HTTP/1.1 200 OK\r\n" + - "Content-Length: 0\r\n\r\n", **kwargs + "Content-Length: 0\r\n\r\n", + **kwargs ) - return server def run(self): try: From 44161ac373199716c4231aa5cb5011a08d2d6ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Fri, 4 Mar 2016 19:35:46 +0100 Subject: [PATCH 29/40] Moved TestTestServer to its own file --- tests/test_testserver.py | 128 +++++++++++++++++++++++++++++++++++++++ tests/test_utils.py | 125 -------------------------------------- 2 files changed, 128 insertions(+), 125 deletions(-) create mode 100644 tests/test_testserver.py diff --git a/tests/test_testserver.py b/tests/test_testserver.py new file mode 100644 index 00000000..03aa590f --- /dev/null +++ b/tests/test_testserver.py @@ -0,0 +1,128 @@ +import threading +import socket +import time + +import pytest +import requests +from testserver.server import Server + +class TestTestServer: + def test_basic(self): + question = b"sucess?" + answer = b"yeah, success" + def handler(sock): + text = sock.recv(1000) + assert text == question + sock.send(answer) + + with Server(handler) as (host, port): + sock = socket.socket() + sock.connect((host, port)) + sock.send(question) + text = sock.recv(1000) + assert text == answer + sock.close() + + def test_server_closes(self): + with Server.basic_response_server() as (host, port): + sock = socket.socket() + sock.connect((host, port)) + + sock.close() + + with pytest.raises(socket.error): + new_sock = socket.socket() + new_sock.connect((host, port)) + + def test_text_response(self): + server = Server.text_response_server( + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 6\r\n" + + "\r\nroflol" + ) + + with server as (host, port): + r = requests.get('http://{0}:{1}'.format(host, port)) + + assert r.status_code == 200 + assert r.text == 'roflol' + assert r.headers['Content-Length'] == '6' + + def test_basic_response(self): + with Server.basic_response_server() as (host, port): + r = requests.get('http://{0}:{1}'.format(host, port)) + assert r.status_code == 200 + assert r.text == '' + assert r.headers['Content-Length'] == '0' + + def test_basic_waiting_server(self): + block_server = threading.Event() + + with Server.basic_response_server(wait_to_close_event=block_server) as (host, port): + sock = socket.socket() + sock.connect((host, port)) + sock.send(b'send something') + time.sleep(2.5) + sock.send(b'still alive') + block_server.set() # release server block + + def test_multiple_requests(self): + requests_to_handle = 5 + + server = Server.basic_response_server(requests_to_handle=requests_to_handle) + + with server as (host, port): + server_url = 'http://{0}:{1}'.format(host, port) + for _ in range(requests_to_handle): + r = requests.get(server_url) + assert r.status_code == 200 + + # the (n+1)th request fails + with pytest.raises(requests.exceptions.ConnectionError): + r = requests.get(server_url) + + def test_request_recovery(self): + server = Server.basic_response_server(requests_to_handle=2) + first_request = "put your hands up in the air" + second_request = "put your hand down in the floor" + + with server as address: + sock1 = socket.socket() + sock2 = socket.socket() + + sock1.connect(address) + sock1.send(first_request.encode()) + sock1.close() + + sock2.connect(address) + sock2.send(second_request.encode()) + sock2.close() + + assert server.handler_results[0] == first_request + assert server.handler_results[1] == second_request + + def test_requests_after_timeout_are_not_received(self): + server = Server.basic_response_server(request_timeout=1) + + with server as address: + sock = socket.socket() + sock.connect(address) + time.sleep(1.5) + sock.send(b"hehehe, not received") + sock.close() + + assert server.handler_results[0] == "" + + + def test_request_recovery_with_bigger_timeout(self): + server = Server.basic_response_server(request_timeout=3) + data = "bananadine" + + with server as address: + sock = socket.socket() + sock.connect(address) + time.sleep(1.5) + sock.send(data.encode()) + sock.close() + + assert server.handler_results[0] == data diff --git a/tests/test_utils.py b/tests/test_utils.py index 3990780a..5972c005 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,12 +1,8 @@ # coding: utf-8 import os -import threading -import socket -import time from io import BytesIO import pytest -import requests from requests import compat from requests.utils import ( address_in_network, dotted_netmask, @@ -234,124 +230,3 @@ def test_select_proxies(url, expected): proxies = {'http': 'http://http.proxy', 'http://some.host': 'http://some.host.proxy'} assert select_proxy(url, proxies) == expected - -class TestTestServer: - def test_basic(self): - question = b"sucess?" - answer = b"yeah, success" - def handler(sock): - text = sock.recv(1000) - assert text == question - sock.send(answer) - - with Server(handler) as (host, port): - sock = socket.socket() - sock.connect((host, port)) - sock.send(question) - text = sock.recv(1000) - assert text == answer - sock.close() - - def test_server_closes(self): - with Server.basic_response_server() as (host, port): - sock = socket.socket() - sock.connect((host, port)) - - sock.close() - - with pytest.raises(socket.error): - new_sock = socket.socket() - new_sock.connect((host, port)) - - def test_text_response(self): - server = Server.text_response_server( - "HTTP/1.1 200 OK\r\n" + - "Content-Length: 6\r\n" + - "\r\nroflol" - ) - - with server as (host, port): - r = requests.get('http://{0}:{1}'.format(host, port)) - - assert r.status_code == 200 - assert r.text == 'roflol' - assert r.headers['Content-Length'] == '6' - - def test_basic_response(self): - with Server.basic_response_server() as (host, port): - r = requests.get('http://{0}:{1}'.format(host, port)) - assert r.status_code == 200 - assert r.text == '' - assert r.headers['Content-Length'] == '0' - - def test_basic_waiting_server(self): - block_server = threading.Event() - - with Server.basic_response_server(wait_to_close_event=block_server) as (host, port): - sock = socket.socket() - sock.connect((host, port)) - sock.send(b'send something') - time.sleep(2.5) - sock.send(b'still alive') - block_server.set() # release server block - - def test_multiple_requests(self): - requests_to_handle = 5 - - server = Server.basic_response_server(requests_to_handle=requests_to_handle) - - with server as (host, port): - server_url = 'http://{0}:{1}'.format(host, port) - for _ in range(requests_to_handle): - r = requests.get(server_url) - assert r.status_code == 200 - - # the (n+1)th request fails - with pytest.raises(requests.exceptions.ConnectionError): - r = requests.get(server_url) - - def test_request_recovery(self): - server = Server.basic_response_server(requests_to_handle=2) - first_request = "put your hands up in the air" - second_request = "put your hand down in the floor" - - with server as address: - sock1 = socket.socket() - sock2 = socket.socket() - - sock1.connect(address) - sock1.send(first_request.encode()) - sock1.close() - - sock2.connect(address) - sock2.send(second_request.encode()) - sock2.close() - - assert server.handler_results[0] == first_request - assert server.handler_results[1] == second_request - - def test_requests_after_timeout_are_not_received(self): - server = Server.basic_response_server(request_timeout=1) - - with server as address: - sock = socket.socket() - sock.connect(address) - time.sleep(1.5) - sock.send(b"hehehe, not received") - sock.close() - - assert server.handler_results[0] == "" - - - def test_request_recovery_with_bigger_timeout(self): - server = Server.basic_response_server(request_timeout=3) - data = "bananadine" - - with server as address: - sock = socket.socket() - sock.connect(address) - time.sleep(1.5) - sock.send(data.encode()) - sock.close() - - assert server.handler_results[0] == data From 7088c06d8daef094eca6d154cbd3c1e6c8ea6126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 22:45:26 +0100 Subject: [PATCH 30/40] Changed tests to use socket.sendall instead of socket.send --- tests/test_testserver.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_testserver.py b/tests/test_testserver.py index 03aa590f..6d00d980 100644 --- a/tests/test_testserver.py +++ b/tests/test_testserver.py @@ -13,12 +13,12 @@ class TestTestServer: def handler(sock): text = sock.recv(1000) assert text == question - sock.send(answer) + sock.sendall(answer) with Server(handler) as (host, port): sock = socket.socket() sock.connect((host, port)) - sock.send(question) + sock.sendall(question) text = sock.recv(1000) assert text == answer sock.close() @@ -61,9 +61,9 @@ class TestTestServer: with Server.basic_response_server(wait_to_close_event=block_server) as (host, port): sock = socket.socket() sock.connect((host, port)) - sock.send(b'send something') + sock.sendall(b'send something') time.sleep(2.5) - sock.send(b'still alive') + sock.sendall(b'still alive') block_server.set() # release server block def test_multiple_requests(self): @@ -91,11 +91,11 @@ class TestTestServer: sock2 = socket.socket() sock1.connect(address) - sock1.send(first_request.encode()) + sock1.sendall(first_request.encode()) sock1.close() sock2.connect(address) - sock2.send(second_request.encode()) + sock2.sendall(second_request.encode()) sock2.close() assert server.handler_results[0] == first_request @@ -108,7 +108,7 @@ class TestTestServer: sock = socket.socket() sock.connect(address) time.sleep(1.5) - sock.send(b"hehehe, not received") + sock.sendall(b"hehehe, not received") sock.close() assert server.handler_results[0] == "" @@ -122,7 +122,7 @@ class TestTestServer: sock = socket.socket() sock.connect(address) time.sleep(1.5) - sock.send(data.encode()) + sock.sendall(data.encode()) sock.close() assert server.handler_results[0] == data From 4edf1ae55f361c7cb9b3deab88c67505fa797263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:05:36 +0100 Subject: [PATCH 31/40] Compare response bodies with unicode strings --- tests/test_testserver.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_testserver.py b/tests/test_testserver.py index 6d00d980..db4145b9 100644 --- a/tests/test_testserver.py +++ b/tests/test_testserver.py @@ -45,14 +45,14 @@ class TestTestServer: r = requests.get('http://{0}:{1}'.format(host, port)) assert r.status_code == 200 - assert r.text == 'roflol' + assert r.text == u'roflol' assert r.headers['Content-Length'] == '6' def test_basic_response(self): with Server.basic_response_server() as (host, port): r = requests.get('http://{0}:{1}'.format(host, port)) assert r.status_code == 200 - assert r.text == '' + assert r.text == u'' assert r.headers['Content-Length'] == '0' def test_basic_waiting_server(self): @@ -111,7 +111,7 @@ class TestTestServer: sock.sendall(b"hehehe, not received") sock.close() - assert server.handler_results[0] == "" + assert server.handler_results[0] == '' def test_request_recovery_with_bigger_timeout(self): From 3c3bde5381ab13dabac0d05b6bb31b4668d020c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:10:13 +0100 Subject: [PATCH 32/40] Remove unwanted changes --- tests/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 5972c005..c8c330e5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -13,7 +13,6 @@ from requests.utils import ( from .compat import StringIO, cStringIO -from testserver.server import Server class TestSuperLen: @@ -230,3 +229,4 @@ def test_select_proxies(url, expected): proxies = {'http': 'http://http.proxy', 'http://some.host': 'http://some.host.proxy'} assert select_proxy(url, proxies) == expected + From 66c52c3ce0e273250cbb5e470ef4e0daadeac715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:11:31 +0100 Subject: [PATCH 33/40] Leave two lines of separation between top level definitions --- tests/testserver/server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/testserver/server.py b/tests/testserver/server.py index b9d64289..c5f35d2b 100644 --- a/tests/testserver/server.py +++ b/tests/testserver/server.py @@ -2,6 +2,7 @@ import threading import socket import select + def consume_socket_content(sock, timeout=0.5): chunks = 65536 content = "" @@ -19,6 +20,7 @@ def consume_socket_content(sock, timeout=0.5): return content + class Server(threading.Thread): """Dummy server using for unit testing""" WAIT_EVENT_TIMEOUT = 5 From eeafdc143bee0f0356e0f5115029eaef792d4eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:21:00 +0100 Subject: [PATCH 34/40] Move test_chunked_upload to test_lowlevel.py --- tests/test_lowlevel.py | 19 +++++++++++++++++++ tests/test_requests.py | 16 ---------------- 2 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 tests/test_lowlevel.py diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py new file mode 100644 index 00000000..4e5d7826 --- /dev/null +++ b/tests/test_lowlevel.py @@ -0,0 +1,19 @@ +import threading +import requests + +from testserver.server import Server + + +def test_chunked_upload(): + """can safely send generators""" + close_server = threading.Event() + server = Server.basic_response_server(wait_to_close_event=close_server) + data = (i for i in [b'a', b'b', b'c']) + + with server as (host, port): + url = 'http://{0}:{1}/'.format(host, port) + r = requests.post(url, data=data, stream=True) + close_server.set() # release server block + + assert r.status_code == 200 + assert r.request.headers['Transfer-Encoding'] == 'chunked' diff --git a/tests/test_requests.py b/tests/test_requests.py index ab1916ce..7a20c19d 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -9,7 +9,6 @@ import os import pickle import collections import contextlib -import threading import io import requests @@ -28,7 +27,6 @@ from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks -from testserver.server import Server from .compat import StringIO, u # Requests to this URL should always fail with a connection timeout (nothing @@ -1453,17 +1451,3 @@ def test_vendor_aliases(): with pytest.raises(ImportError): from requests.packages import webbrowser - -def test_chunked_upload(): - """can safely send generators""" - block_server = threading.Event() - server = Server.basic_response_server(wait_to_close_event=block_server) - data = (i for i in [b'a', b'b', b'c']) - - with server as (host, port): - url = 'http://{0}:{1}/'.format(host, port) - r = requests.post(url, data=data, stream=True) - block_server.set() # release server block - - assert r.status_code == 200 - assert r.request.headers['Transfer-Encoding'] == 'chunked' From 94d4818fde1df23747e2208b01fd4911a97bb69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:22:52 +0100 Subject: [PATCH 35/40] Remove unwanted change in test_requests.py --- tests/test_requests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_requests.py b/tests/test_requests.py index 7a20c19d..c662c7fc 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -27,8 +27,8 @@ from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks -from .compat import StringIO, u +from .compat import StringIO, u # Requests to this URL should always fail with a connection timeout (nothing # listening on that port) TARPIT = 'http://10.255.255.1' From c4abb4c9fbce7635ea89938f52896defa5583c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:26:36 +0100 Subject: [PATCH 36/40] Remove unwanted changes in test_utils.py --- tests/test_utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index c8c330e5..5a50e366 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -14,7 +14,6 @@ from requests.utils import ( from .compat import StringIO, cStringIO - class TestSuperLen: @pytest.mark.parametrize( @@ -152,6 +151,7 @@ class TestContentEncodingDetection: '''.strip() assert get_encodings_from_content(content) == ['HTML5', 'HTML4', 'XML'] + USER = PASSWORD = "%!*'();:@&=+$,/?#[] " ENCODED_USER = compat.quote(USER, '') ENCODED_PASSWORD = compat.quote(PASSWORD, '') @@ -229,4 +229,3 @@ def test_select_proxies(url, expected): proxies = {'http': 'http://http.proxy', 'http://some.host': 'http://some.host.proxy'} assert select_proxy(url, proxies) == expected - From 0dff06a7b9eb337ce02838f1e4cb9b042c9f3f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:28:32 +0100 Subject: [PATCH 37/40] Add blank line in test_requests.py --- tests/test_requests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_requests.py b/tests/test_requests.py index c662c7fc..1ee379c9 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -29,6 +29,7 @@ from requests.models import urlencode from requests.hooks import default_hooks from .compat import StringIO, u + # Requests to this URL should always fail with a connection timeout (nothing # listening on that port) TARPIT = 'http://10.255.255.1' From 03743b15ed30a030629231da6ba0ecc23240bf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Sat, 5 Mar 2016 23:50:11 +0100 Subject: [PATCH 38/40] Added docstrings to tests in test_testserver.py --- tests/test_testserver.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_testserver.py b/tests/test_testserver.py index db4145b9..38d685b4 100644 --- a/tests/test_testserver.py +++ b/tests/test_testserver.py @@ -8,6 +8,7 @@ from testserver.server import Server class TestTestServer: def test_basic(self): + """messages are sent and received properly""" question = b"sucess?" answer = b"yeah, success" def handler(sock): @@ -24,6 +25,7 @@ class TestTestServer: sock.close() def test_server_closes(self): + """the server closes when leaving the context manager""" with Server.basic_response_server() as (host, port): sock = socket.socket() sock.connect((host, port)) @@ -35,6 +37,7 @@ class TestTestServer: new_sock.connect((host, port)) def test_text_response(self): + """the text_response_server sends the given text""" server = Server.text_response_server( "HTTP/1.1 200 OK\r\n" + "Content-Length: 6\r\n" + @@ -49,6 +52,7 @@ class TestTestServer: assert r.headers['Content-Length'] == '6' def test_basic_response(self): + """the basic response server returns an empty http response""" with Server.basic_response_server() as (host, port): r = requests.get('http://{0}:{1}'.format(host, port)) assert r.status_code == 200 @@ -56,6 +60,7 @@ class TestTestServer: assert r.headers['Content-Length'] == '0' def test_basic_waiting_server(self): + """the server waits for the block_server event to be set before closing""" block_server = threading.Event() with Server.basic_response_server(wait_to_close_event=block_server) as (host, port): @@ -67,6 +72,7 @@ class TestTestServer: block_server.set() # release server block def test_multiple_requests(self): + """multiple requests can be served""" requests_to_handle = 5 server = Server.basic_response_server(requests_to_handle=requests_to_handle) @@ -82,6 +88,7 @@ class TestTestServer: r = requests.get(server_url) def test_request_recovery(self): + """can check the requests content""" server = Server.basic_response_server(requests_to_handle=2) first_request = "put your hands up in the air" second_request = "put your hand down in the floor" @@ -102,6 +109,7 @@ class TestTestServer: assert server.handler_results[1] == second_request def test_requests_after_timeout_are_not_received(self): + """the basic response handler times out when receiving requests""" server = Server.basic_response_server(request_timeout=1) with server as address: @@ -115,6 +123,7 @@ class TestTestServer: def test_request_recovery_with_bigger_timeout(self): + """a biggest timeout can be specified""" server = Server.basic_response_server(request_timeout=3) data = "bananadine" From b473440cc1038ae9e745141ea4084291c7f8ea6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Mon, 7 Mar 2016 18:33:06 +0100 Subject: [PATCH 39/40] Fix tests in python 3 --- tests/test_lowlevel.py | 2 +- tests/test_testserver.py | 18 +++++++++--------- tests/testserver/server.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/test_lowlevel.py b/tests/test_lowlevel.py index 4e5d7826..eb6d6273 100644 --- a/tests/test_lowlevel.py +++ b/tests/test_lowlevel.py @@ -1,7 +1,7 @@ import threading import requests -from testserver.server import Server +from tests.testserver.server import Server def test_chunked_upload(): diff --git a/tests/test_testserver.py b/tests/test_testserver.py index 38d685b4..027f8e50 100644 --- a/tests/test_testserver.py +++ b/tests/test_testserver.py @@ -4,7 +4,7 @@ import time import pytest import requests -from testserver.server import Server +from tests.testserver.server import Server class TestTestServer: def test_basic(self): @@ -90,19 +90,19 @@ class TestTestServer: def test_request_recovery(self): """can check the requests content""" server = Server.basic_response_server(requests_to_handle=2) - first_request = "put your hands up in the air" - second_request = "put your hand down in the floor" + first_request = b'put your hands up in the air' + second_request = b'put your hand down in the floor' with server as address: sock1 = socket.socket() sock2 = socket.socket() sock1.connect(address) - sock1.sendall(first_request.encode()) + sock1.sendall(first_request) sock1.close() sock2.connect(address) - sock2.sendall(second_request.encode()) + sock2.sendall(second_request) sock2.close() assert server.handler_results[0] == first_request @@ -116,22 +116,22 @@ class TestTestServer: sock = socket.socket() sock.connect(address) time.sleep(1.5) - sock.sendall(b"hehehe, not received") + sock.sendall(b'hehehe, not received') sock.close() - assert server.handler_results[0] == '' + assert server.handler_results[0] == b'' def test_request_recovery_with_bigger_timeout(self): """a biggest timeout can be specified""" server = Server.basic_response_server(request_timeout=3) - data = "bananadine" + data = b'bananadine' with server as address: sock = socket.socket() sock.connect(address) time.sleep(1.5) - sock.sendall(data.encode()) + sock.sendall(data) sock.close() assert server.handler_results[0] == data diff --git a/tests/testserver/server.py b/tests/testserver/server.py index c5f35d2b..bcffd14c 100644 --- a/tests/testserver/server.py +++ b/tests/testserver/server.py @@ -5,7 +5,7 @@ import select def consume_socket_content(sock, timeout=0.5): chunks = 65536 - content = "" + content = b'' more_to_read = select.select([sock], [], [], timeout)[0] while more_to_read: From 634b2beb39644a1aa1ef3f1f7c4f26fe0a6a9bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Valdivielso=20Mart=C3=ADnez?= Date: Mon, 11 Apr 2016 20:03:23 +0200 Subject: [PATCH 40/40] Fixed indenting issues --- tests/testserver/server.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/testserver/server.py b/tests/testserver/server.py index bcffd14c..8b9643c3 100644 --- a/tests/testserver/server.py +++ b/tests/testserver/server.py @@ -1,4 +1,4 @@ -import threading +import threading import socket import select @@ -14,9 +14,9 @@ def consume_socket_content(sock, timeout=0.5): if not new_content: break - content += new_content + content += new_content # stop reading if no new data is received for a while - more_to_read = select.select([sock], [], [], timeout)[0] + more_to_read = select.select([sock], [], [], timeout)[0] return content @@ -34,7 +34,7 @@ class Server(threading.Thread): self.host = host self.port = port self.requests_to_handle = requests_to_handle - + self.wait_to_close_event = wait_to_close_event self.ready_event = threading.Event() self.stop_event = threading.Event() @@ -54,7 +54,7 @@ class Server(threading.Thread): def basic_response_server(cls, **kwargs): return cls.text_response_server( "HTTP/1.1 200 OK\r\n" + - "Content-Length: 0\r\n\r\n", + "Content-Length: 0\r\n\r\n", **kwargs ) @@ -85,19 +85,18 @@ class Server(threading.Thread): handler_result = self.handler(sock) self.handler_results.append(handler_result) - + def __enter__(self): - self.start() - self.ready_event.wait(self.WAIT_EVENT_TIMEOUT) - return self.host, self.port - + self.start() + self.ready_event.wait(self.WAIT_EVENT_TIMEOUT) + return self.host, self.port + def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: self.stop_event.wait(self.WAIT_EVENT_TIMEOUT) else: if self.wait_to_close_event: - # avoid server from waiting for event timeouts - # if an exception is found in the main thread - self.wait_to_close_event.set() - return False # allow exceptions to propagate - + # avoid server from waiting for event timeouts + # if an exception is found in the main thread + self.wait_to_close_event.set() + return False # allow exceptions to propagate