Chromium Code Reviews| Index: net/http/http_stream_parser_unittest.cc |
| diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc |
| index 76f998a0e97a78d3c9db169712bbdc6a197961e1..bc54f6246d3a5bdd423a53477fa7f7e11a9fe51b 100644 |
| --- a/net/http/http_stream_parser_unittest.cc |
| +++ b/net/http/http_stream_parser_unittest.cc |
| @@ -4,6 +4,8 @@ |
| #include "net/http/http_stream_parser.h" |
| +#include <stdint.h> |
| + |
| #include <algorithm> |
| #include <string> |
| #include <vector> |
| @@ -59,6 +61,15 @@ scoped_ptr<ClientSocketHandle> CreateConnectedSocketHandle( |
| return socket_handle.Pass(); |
| } |
| +// Helper method to get the total data size of the MockWrites in |writes|. |
| +int64_t WritesSize(const MockWrite writes[], size_t length) { |
|
mmenke
2015/08/31 22:23:13
Suggest calling this CountWriteBytes.
WriteBytes
mmenke
2015/08/31 22:23:13
Maybe make this part of SequencedSocketData instea
sclittle
2015/09/01 01:21:48
OK, I've created CountReadBytes and CountWriteByte
mmenke
2015/09/01 17:39:43
I actually disagree here - seems like a utility fu
sclittle
2015/09/01 20:03:00
Often the length is necessary - a single SocketDat
|
| + int64_t total = 0; |
| + for (const MockWrite* write = writes; write != writes + length; ++write) { |
| + total += write->data_len; |
| + } |
| + return total; |
| +} |
| + |
| // The empty payload is how the last chunk is encoded. |
| TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { |
| char output[kOutputSize]; |
| @@ -1005,6 +1016,261 @@ TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) { |
| EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| } |
| +TEST(HttpStreamParser, SentBytesNoHeaders) { |
| + MockWrite writes[] = { |
| + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + HttpRequestInfo request; |
| + request.method = "GET"; |
| + request.url = GURL("http://localhost"); |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(), |
|
mmenke
2015/08/31 22:23:13
These should probably just be EXPECTs - at least t
sclittle
2015/09/01 01:21:48
Done.
|
| + &response, callback.callback())); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesWithHeaders) { |
| + MockWrite writes[] = { |
| + MockWrite(SYNCHRONOUS, 0, |
| + "GET / HTTP/1.1\r\n" |
| + "Host: localhost\r\n" |
| + "Connection: Keep-Alive\r\n\r\n"), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + HttpRequestInfo request; |
| + request.method = "GET"; |
| + request.url = GURL("http://localhost"); |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Host", "localhost"); |
| + headers.SetHeader("Connection", "Keep-Alive"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, |
| + callback.callback())); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesWithHeadersMultiWrite) { |
| + MockWrite writes[] = { |
| + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), |
| + MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), |
| + MockWrite(SYNCHRONOUS, 2, "Connection: Keep-Alive\r\n\r\n"), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + HttpRequestInfo request; |
| + request.method = "GET"; |
| + request.url = GURL("http://localhost"); |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Host", "localhost"); |
| + headers.SetHeader("Connection", "Keep-Alive"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + |
| + int rv = parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, |
| + callback.callback()); |
| + ASSERT_EQ(OK, rv); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesWithErrorWritingHeaders) { |
| + MockWrite writes[] = { |
| + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), |
| + MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), |
| + MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 2), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + HttpRequestInfo request; |
| + request.method = "GET"; |
| + request.url = GURL("http://localhost"); |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Host", "localhost"); |
| + headers.SetHeader("Connection", "Keep-Alive"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(ERR_CONNECTION_RESET, |
| + parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, |
| + callback.callback())); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesPost) { |
| + MockWrite writes[] = { |
| + MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"), |
| + MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"), |
| + MockWrite(SYNCHRONOUS, 2, "hello world!"), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + ScopedVector<UploadElementReader> element_readers; |
| + element_readers.push_back(new UploadBytesElementReader("hello world!", 12)); |
| + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); |
| + ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); |
| + |
| + HttpRequestInfo request; |
| + request.method = "POST"; |
| + request.url = GURL("http://localhost"); |
| + request.upload_data_stream = &upload_data_stream; |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Content-Length", "12"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(OK, parser.SendRequest("POST / HTTP/1.1\r\n", headers, &response, |
| + callback.callback())); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesChunkedPost) { |
|
mmenke
2015/08/31 22:23:13
Rather than duplicate some of these larger tests,
sclittle
2015/09/01 01:21:47
Done.
|
| + static const char kChunk1[] = "Chunk 1"; |
| + static const char kChunk2[] = "Chunky 2"; |
| + static const char kChunk3[] = "Test 3"; |
| + |
| + MockWrite writes[] = { |
| + MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"), |
| + MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"), |
| + MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"), |
| + MockWrite(ASYNC, 3, "8\r\nChunky 2\r\n"), |
| + MockWrite(ASYNC, 4, "6\r\nTest 3\r\n"), |
| + MockWrite(ASYNC, 5, "0\r\n\r\n"), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + ChunkedUploadDataStream upload_data_stream(0); |
| + ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); |
| + |
| + HttpRequestInfo request; |
| + request.method = "POST"; |
| + request.url = GURL("http://localhost"); |
| + request.upload_data_stream = &upload_data_stream; |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Transfer-Encoding", "chunked"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers, |
| + &response, callback.callback())); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + upload_data_stream.AppendData(kChunk1, arraysize(kChunk1) - 1, false); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + upload_data_stream.AppendData(kChunk2, arraysize(kChunk2) - 1, false); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + upload_data_stream.AppendData(kChunk3, arraysize(kChunk3) - 1, true); |
| + |
| + ASSERT_EQ(OK, callback.WaitForResult()); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| +TEST(HttpStreamParser, SentBytesChunkedPostError) { |
| + static const char kChunk[] = "Chunk 1"; |
| + |
| + MockWrite writes[] = { |
| + MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"), |
| + MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"), |
| + MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"), |
| + MockWrite(SYNCHRONOUS, ERR_FAILED, 3), |
| + }; |
| + |
| + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); |
| + scoped_ptr<ClientSocketHandle> socket_handle = |
| + CreateConnectedSocketHandle(&data); |
| + |
| + ChunkedUploadDataStream upload_data_stream(0); |
| + ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); |
| + |
| + HttpRequestInfo request; |
| + request.method = "POST"; |
| + request.url = GURL("http://localhost"); |
| + request.upload_data_stream = &upload_data_stream; |
| + |
| + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), |
| + BoundNetLog()); |
| + |
| + HttpRequestHeaders headers; |
| + headers.SetHeader("Transfer-Encoding", "chunked"); |
| + |
| + HttpResponseInfo response; |
| + TestCompletionCallback callback; |
| + ASSERT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers, |
| + &response, callback.callback())); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); |
| + |
| + base::RunLoop().RunUntilIdle(); |
| + // This write should fail. |
| + upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); |
| + ASSERT_EQ(ERR_FAILED, callback.WaitForResult()); |
| + |
| + EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); |
| +} |
| + |
| // Test that an HttpStreamParser can be read from after it's received headers |
| // and data structures owned by its owner have been deleted. This happens |
| // when a ResponseBodyDrainer is used. |