mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-29 00:32:35 +08:00
HTTPTransport test: Deal with limited-size pipe buffers
HTTPTransport.Upload33k failed on Windows due to WinHTTP timing out. The test server, http_transport_test_server.py, writes the entire request to a stdout pipe, to be received by crashpad_util_test. crashpad_util_test is also the HTTP client, and it does not attempt to read from this pipe until the HTTP transaction is complete. http_transport_test_server.py must not write to stdout until the transaction is complete, otherwise, there is a risk of deadlock if the pipe buffer fills up. The new Upload33k test sends a large request, which was filling up the pipe buffer on Windows. This also adds an Upload33k_LengthUnknown test variant to exercise a large POST when the length is not known ahead of time. This more closely matches how Crashpad crash uploads are done on OS X. TEST=crashpad_util_test HTTPTransport.* R=rsesek@chromium.org Review URL: https://codereview.chromium.org/1286173007 .
This commit is contained in:
parent
397e437e51
commit
14a2241274
@ -278,7 +278,7 @@ TEST(HTTPTransport, UnchunkedPlainText) {
|
||||
test.Run();
|
||||
}
|
||||
|
||||
TEST(HTTPTransport, Upload33k) {
|
||||
void RunUpload33k(bool has_content_length) {
|
||||
// On OS X, NSMutableURLRequest winds up calling into a CFReadStream’s Read()
|
||||
// callback with a 32kB buffer. Make sure that it’s able to get everything
|
||||
// when enough is available to fill this buffer, requiring more than one
|
||||
@ -290,8 +290,10 @@ TEST(HTTPTransport, Upload33k) {
|
||||
|
||||
HTTPHeaders headers;
|
||||
headers[kContentType] = "application/octet-stream";
|
||||
headers[kContentLength] =
|
||||
base::StringPrintf("%" PRIuS, request_string.size());
|
||||
if (has_content_length) {
|
||||
headers[kContentLength] =
|
||||
base::StringPrintf("%" PRIuS, request_string.size());
|
||||
}
|
||||
HTTPTransportTestFixture test(headers, body_stream.Pass(), 200,
|
||||
[](HTTPTransportTestFixture* fixture, const std::string& request) {
|
||||
size_t body_start = request.rfind("\r\n");
|
||||
@ -300,6 +302,15 @@ TEST(HTTPTransport, Upload33k) {
|
||||
test.Run();
|
||||
}
|
||||
|
||||
TEST(HTTPTransport, Upload33k) {
|
||||
RunUpload33k(true);
|
||||
}
|
||||
|
||||
TEST(HTTPTransport, Upload33k_LengthUnknown) {
|
||||
// The same as Upload33k, but without declaring Content-Length ahead of time.
|
||||
RunUpload33k(false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
|
@ -59,6 +59,14 @@ class BufferedReadFile(object):
|
||||
|
||||
|
||||
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
# Everything to be written to stdout is collected into this string. It can’t
|
||||
# be written to stdout until after the HTTP transaction is complete, because
|
||||
# stdout is a pipe being read by a test program that’s also the HTTP client.
|
||||
# The test program expects to complete the entire HTTP transaction before it
|
||||
# even starts reading this script’s stdout. If the stdout pipe buffer fills up
|
||||
# during an HTTP transaction, deadlock would result.
|
||||
raw_request = ''
|
||||
|
||||
response_code = 500
|
||||
response_body = ''
|
||||
|
||||
@ -69,9 +77,7 @@ class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
BaseHTTPServer.BaseHTTPRequestHandler.handle_one_request(self)
|
||||
|
||||
def do_POST(self):
|
||||
writer = sys.stdout
|
||||
|
||||
writer.write(self.rfile.buffer)
|
||||
RequestHandler.raw_request = self.rfile.buffer
|
||||
self.rfile.buffer = ''
|
||||
|
||||
if self.headers.get('Transfer-Encoding', '') == 'Chunked':
|
||||
@ -80,15 +86,14 @@ class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
length = int(self.headers.get('Content-Length', -1))
|
||||
body = self.rfile.read(length)
|
||||
|
||||
RequestHandler.raw_request += body
|
||||
|
||||
self.send_response(self.response_code)
|
||||
self.end_headers()
|
||||
if self.response_code == 200:
|
||||
self.wfile.write(self.response_body)
|
||||
self.wfile.write('\r\n')
|
||||
|
||||
writer.write(body)
|
||||
writer.flush()
|
||||
|
||||
def handle_chunked_encoding(self):
|
||||
"""This parses a "Transfer-Encoding: Chunked" body in accordance with
|
||||
RFC 7230 §4.1. This returns the result as a string.
|
||||
@ -146,5 +151,9 @@ def Main():
|
||||
# Handle the request.
|
||||
server.handle_request()
|
||||
|
||||
# Share the entire request with the test program, which will validate it.
|
||||
sys.stdout.write(RequestHandler.raw_request)
|
||||
sys.stdout.flush()
|
||||
|
||||
if __name__ == '__main__':
|
||||
Main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user