def test_blocking(self): p = Pipe(timeout=1, bsize=10) self.assertTrue(p.readblocking()) self.assertTrue(p.writeblocking()) try: # should block for 1 second and then timeout rresult = p.read(1) self.fail("blocked read returned %s" % repr(rresult)) except IOError as e: self.assertTrue(io_timedout(e)) p.write(b"123") # should not block! rresult = p.read(5) self.assertTrue(rresult == b"123") # should not block, just! p.write(bytearray(b"1234567890")) try: # should block for 1 second wresult = p.write(b"extra") self.fail("blocked write returned %s" % repr(wresult)) except IOError as e: self.assertTrue(io_timedout(e)) try: # should block for 1 second logging.debug("flush waiting for 1s timeout...") p.flush() self.fail("blocked flush returned") except IOError as e: logging.debug("flush caught 1s timeout; %s", str(e))
def test_nochunked(self): """RFC2616: A server MUST NOT send transfer-codings to an HTTP/1.0 client""" s = UnboundServer(port=self.port, app=self.multidata_app) sock = MockSocket() t = threading.Thread(target=self.run_request, args=(s, sock)) t.start() # write of str will not block on an empty pipe sock.recv_wbuffer.write(b"GET /a HTTP/1.0\r\n\r\n") # force the data into the pipe (won't flush the Pipe itself) sock.recv_wbuffer.flush() response = sock.send_pipe.readmatch(b"xyz") self.assertTrue(response is not None, "response still blocked") logging.debug("test_nochunked: response\r\n%s", response) self.assertTrue(response.startswith(b"HTTP/1.1 200 ")) self.assertFalse(b"chunked" in response.lower(), "No chunked") # it should close the connection... try: sock.recv_wbuffer.write(b"GET /b HTTP/1.0\r\n\r\n") sock.recv_wbuffer.flush() sock.send_pipe.read_wait(5) except IOError as e: # this must not be a timeout! self.assertFalse(io_timedout(e)) except ValueError: # raised by BufferedWriter when it has been closed pass # now join our handler as it must exit sock.close() logging.debug("test_nochunked: waiting for handler...") t.join() logging.debug("test_nochunked: end of test") s.server_close()
def test_transfer_encoding(self): """RFC2616: A server which receives an entity-body with a transfer-coding it does not understand SHOULD return 501 (Unimplemented), and close the connection""" s = UnboundServer(port=self.port) sock = MockSocket() t = threading.Thread(target=self.run_request, args=(s, sock)) t.start() # write of str will not block on an empty pipe sock.recv_wbuffer.write(b"POST / HTTP/1.1\r\n" b"Transfer-Encoding: unknown, chunked\r\n\r\n") # force the data into the pipe (won't flush the Pipe itself) sock.recv_wbuffer.flush() sock.send_pipe.read_wait(5) response = sock.send_rbuffer.read() self.assertTrue(response is not None, "response still blocked") logging.debug("test_transfer_encoding: response\r\n%s", response) self.assertTrue(response.startswith(b"HTTP/1.1 501 ")) # let's try and send another request, should fail try: sock.recv_wbuffer.write(b"GET / HTTP/1.1\r\n\r\n") sock.recv_wbuffer.flush() sock.send_pipe.read_wait(5) except IOError as e: # this must not be a timeout! self.assertFalse(io_timedout(e)) except ValueError: # raised by BufferedWriter when it has been closed pass # now join our handler as it must exit sock.close() t.join() s.server_close()
def test_breadmatch(self): p = Pipe(timeout=1, bsize=10, rblocking=True) p.write(b"12") p.write(b"3\r\n") self.assertTrue(p.readmatch() == b"123\r\n") # now check behaviour when no line is present p.write(b"1") p.write(b"2") p.write(b"3") try: p.readmatch() self.fail("blocking readmatch") except IOError as e: self.assertTrue(io_timedout(e)) p.write(b"\r") p.write(b"\nabc") self.assertTrue(p.readmatch() == b"123\r\n") # now check for buffer size exceeded p.write(b"\r3\n4\r56\n") try: p.readmatch() self.fail("blocking full buffer") except IOError as e: self.assertTrue(e.errno == errno.ENOBUFS) # now add an EOF and it should change the result p.write_eof() self.assertTrue(p.readmatch() == b'')
def test_wnblocking(self): p = Pipe(timeout=1, bsize=10, wblocking=False) self.assertTrue(p.readblocking()) self.assertFalse(p.writeblocking()) p.write(b"1234567890") data = b"extra" try: # should not block wresult = p.write(data) self.assertTrue(wresult is None, repr(wresult)) except IOError as e: self.fail("Timeout on non-blocking write; %s" % str(e)) # read all the data to empty the buffer self.assertTrue(len(p.read(10)) == 10, "in our case, True!") try: # should block for 1 second and then timeout rresult = p.read(1) self.fail("blocked read returned %s" % repr(rresult)) except IOError as e: self.assertTrue(io_timedout(e)) p.write(b"1234567890") try: # should not block! p.flush() self.fail("non-blocking flush returned with data") except io.BlockingIOError: pass except IOError as e: self.fail("non-blocking flush timed out; %s" % str(e))
def test_readall(self): p = Pipe(timeout=1, bsize=10, rblocking=False) p.write(b"123") # readall should block and timeout try: data = p.readall() self.fail("blocked readall returned: %s" % data) except IOError as e: self.assertTrue(io_timedout(e))
def recv_request(self): request = messages.Request() request.start_receiving() check_continue = False try: while True: if check_continue and request.get_expect_continue(): # push an expect response self.send_continue() check_continue = False mode = request.recv_mode() if mode == messages.Message.RECV_LINE: line = self.send_pipe.readmatch() if line == b'': if request.method is None: # EOF, no more requests return None else: # EOF, unexpected raise messages.HTTPException( "Unexpected EOF in mock socket") request.recv(line) elif mode == messages.Message.RECV_HEADERS: lines = [] last_line = b'' while last_line != b'\r\n': last_line = self.send_pipe.readmatch() lines.append(last_line) request.recv(lines) check_continue = True elif mode is None: break elif mode > 0: data = self.send_pipe.read(mode) if data == b'': # EOF, unexpected raise messages.HTTPException( "Unexpected EOF in mock socket") else: request.recv(data) elif mode == messages.Message.RECV_ALL: data = self.send_pipe.read() if data == b'': # EOF, expected break else: request.recv(data) else: raise ValueError("unexpected recv_mode!") except IOError as e: if io_timedout(e): logging.debug("mock socket timed out while reading request") request = None else: raise return request
def test_rwait(self): p = Pipe(timeout=1, bsize=10, rblocking=False) rresult = p.read(1) self.assertTrue(rresult is None, "read blocked") try: p.read_wait(timeout=1) self.fail("wait should time out") except IOError as e: self.assertTrue(io_timedout(e)) t = threading.Thread(target=self.rwait_runner, args=(p, )) t.start() time.sleep(0) try: p.read_wait(timeout=5) pass except IOError as e: self.fail("read_wait error on multi-threaded write; %s" % str(e))
def test_rwait(self): p = Pipe(timeout=1, bsize=10, rblocking=False) rresult = p.read(1) self.assertTrue(rresult is None, "read blocked") try: p.read_wait(timeout=1) self.fail("wait should time out") except IOError as e: self.assertTrue(io_timedout(e)) t = threading.Thread(target=self.rwait_runner, args=(p,)) t.start() time.sleep(0) try: p.read_wait(timeout=5) pass except IOError as e: self.fail("read_wait error on multi-threaded write; %s" % str(e))
def test_rnblocking(self): p = Pipe(timeout=1, bsize=10, rblocking=False) self.assertFalse(p.readblocking()) self.assertTrue(p.writeblocking()) try: # should not block rresult = p.read(1) self.assertTrue(rresult is None) except IOError as e: self.fail("Timeout on non-blocking read; %s" % str(e)) # write should still block p.write(b"1234567890") try: # should block for 1 second wresult = p.write(b"extra") self.fail("blocked write returned %s" % repr(wresult)) except IOError as e: self.assertTrue(io_timedout(e))
def test_wwait(self): p = Pipe(timeout=1, bsize=10, wblocking=False) p.write(b"1234567890") data = b"extra" wresult = p.write(data) self.assertTrue(wresult is None, "write blocked") try: p.write_wait(timeout=1) self.fail("wait should time out") except IOError as e: self.assertTrue(io_timedout(e)) t = threading.Thread(target=self.wwait_runner, args=(p,)) t.start() time.sleep(0) try: p.write_wait(timeout=5) pass except IOError: self.fail("write_wait error on multi-threaded read; %s" % str(e))
def test_wwait(self): p = Pipe(timeout=1, bsize=10, wblocking=False) p.write(b"1234567890") data = b"extra" wresult = p.write(data) self.assertTrue(wresult is None, "write blocked") try: p.write_wait(timeout=1) self.fail("wait should time out") except IOError as e: self.assertTrue(io_timedout(e)) t = threading.Thread(target=self.wwait_runner, args=(p, )) t.start() time.sleep(0) try: p.write_wait(timeout=5) pass except IOError: self.fail("write_wait error on multi-threaded read; %s" % str(e))
def recv_request(self): while True: responded = False request = messages.Request() request.start_receiving() check_continue = False try: while True: if check_continue and request.get_expect_continue(): # push an expect response if self.allow_continue: logging.debug("Sending 100 Continue") self.send_continue() else: logging.debug("Sending 417 Expectation Failed") self.send_expectation_failed() if self.close_on_417: # we're not sending any more data, hangup self.mock_shutdown(socket.SHUT_RDWR) return None else: # wait for the next request responded = True check_continue = False mode = request.recv_mode() if mode == messages.Message.RECV_LINE: line = self.send_pipe.readmatch() if line == b'': if request.method is None: # EOF, no more requests return None else: # EOF, unexpected raise messages.HTTPException( "Unexpected EOF in mock socket") request.recv(line) elif mode == messages.Message.RECV_HEADERS: lines = [] last_line = b'' while last_line != b'\r\n': last_line = self.send_pipe.readmatch() lines.append(last_line) request.recv(lines) check_continue = True elif mode is None: break elif mode > 0: data = self.send_pipe.read(mode) if data == b'': # EOF, unexpected raise messages.HTTPException( "Unexpected EOF in mock socket") else: request.recv(data) elif mode == messages.Message.RECV_ALL: data = self.send_pipe.read() if data == b'': # EOF, expected break else: request.recv(data) else: raise ValueError("unexpected recv_mode!") except IOError as e: if io_timedout(e): logging.debug( "mock socket timed out while reading request") responded = False request = None else: raise if responded: continue else: return request