| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 | 92 |
| 93 // The payload is one byte larger the output buffer size. | 93 // The payload is one byte larger the output buffer size. |
| 94 const std::string kPayload(kMaxPayloadSize + 1, '\xff'); | 94 const std::string kPayload(kMaxPayloadSize + 1, '\xff'); |
| 95 const int num_bytes_written = | 95 const int num_bytes_written = |
| 96 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); | 96 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); |
| 97 ASSERT_EQ(ERR_INVALID_ARGUMENT, num_bytes_written); | 97 ASSERT_EQ(ERR_INVALID_ARGUMENT, num_bytes_written); |
| 98 } | 98 } |
| 99 | 99 |
| 100 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) { | 100 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) { |
| 101 // Shouldn't be merged if upload data is non-existent. | 101 // Shouldn't be merged if upload data is non-existent. |
| 102 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 102 ASSERT_FALSE( |
| 103 "some header", NULL)); | 103 HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header", NULL)); |
| 104 } | 104 } |
| 105 | 105 |
| 106 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { | 106 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) { |
| 107 ScopedVector<UploadElementReader> element_readers; | 107 ScopedVector<UploadElementReader> element_readers; |
| 108 scoped_ptr<UploadDataStream> body( | 108 scoped_ptr<UploadDataStream> body( |
| 109 new UploadDataStream(element_readers.Pass(), 0)); | 109 new UploadDataStream(element_readers.Pass(), 0)); |
| 110 ASSERT_EQ(OK, body->Init(CompletionCallback())); | 110 ASSERT_EQ(OK, body->Init(CompletionCallback())); |
| 111 // Shouldn't be merged if upload data is empty. | 111 // Shouldn't be merged if upload data is empty. |
| 112 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 112 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header", |
| 113 "some header", body.get())); | 113 body.get())); |
| 114 } | 114 } |
| 115 | 115 |
| 116 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_ChunkedBody) { | 116 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_ChunkedBody) { |
| 117 const std::string payload = "123"; | 117 const std::string payload = "123"; |
| 118 scoped_ptr<UploadDataStream> body( | 118 scoped_ptr<UploadDataStream> body( |
| 119 new UploadDataStream(UploadDataStream::CHUNKED, 0)); | 119 new UploadDataStream(UploadDataStream::CHUNKED, 0)); |
| 120 body->AppendChunk(payload.data(), payload.size(), true); | 120 body->AppendChunk(payload.data(), payload.size(), true); |
| 121 ASSERT_EQ(OK, body->Init(CompletionCallback())); | 121 ASSERT_EQ(OK, body->Init(CompletionCallback())); |
| 122 // Shouldn't be merged if upload data carries chunked data. | 122 // Shouldn't be merged if upload data carries chunked data. |
| 123 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 123 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header", |
| 124 "some header", body.get())); | 124 body.get())); |
| 125 } | 125 } |
| 126 | 126 |
| 127 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) { | 127 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) { |
| 128 { | 128 { |
| 129 ScopedVector<UploadElementReader> element_readers; | 129 ScopedVector<UploadElementReader> element_readers; |
| 130 | 130 |
| 131 // Create an empty temporary file. | 131 // Create an empty temporary file. |
| 132 base::ScopedTempDir temp_dir; | 132 base::ScopedTempDir temp_dir; |
| 133 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 133 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 134 base::FilePath temp_file_path; | 134 base::FilePath temp_file_path; |
| 135 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), | 135 ASSERT_TRUE( |
| 136 &temp_file_path)); | 136 base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file_path)); |
| 137 | 137 |
| 138 element_readers.push_back( | 138 element_readers.push_back( |
| 139 new UploadFileElementReader(base::MessageLoopProxy::current().get(), | 139 new UploadFileElementReader(base::MessageLoopProxy::current().get(), |
| 140 temp_file_path, | 140 temp_file_path, |
| 141 0, | 141 0, |
| 142 0, | 142 0, |
| 143 base::Time())); | 143 base::Time())); |
| 144 | 144 |
| 145 scoped_ptr<UploadDataStream> body( | 145 scoped_ptr<UploadDataStream> body( |
| 146 new UploadDataStream(element_readers.Pass(), 0)); | 146 new UploadDataStream(element_readers.Pass(), 0)); |
| 147 TestCompletionCallback callback; | 147 TestCompletionCallback callback; |
| 148 ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback())); | 148 ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback())); |
| 149 ASSERT_EQ(OK, callback.WaitForResult()); | 149 ASSERT_EQ(OK, callback.WaitForResult()); |
| 150 // Shouldn't be merged if upload data carries a file, as it's not in-memory. | 150 // Shouldn't be merged if upload data carries a file, as it's not in-memory. |
| 151 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 151 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( |
| 152 "some header", body.get())); | 152 "some header", body.get())); |
| 153 } | 153 } |
| 154 // UploadFileElementReaders may post clean-up tasks on destruction. | 154 // UploadFileElementReaders may post clean-up tasks on destruction. |
| 155 base::RunLoop().RunUntilIdle(); | 155 base::RunLoop().RunUntilIdle(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) { | 158 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) { |
| 159 ScopedVector<UploadElementReader> element_readers; | 159 ScopedVector<UploadElementReader> element_readers; |
| 160 const std::string payload = "123"; | 160 const std::string payload = "123"; |
| 161 element_readers.push_back(new UploadBytesElementReader( | 161 element_readers.push_back( |
| 162 payload.data(), payload.size())); | 162 new UploadBytesElementReader(payload.data(), payload.size())); |
| 163 | 163 |
| 164 scoped_ptr<UploadDataStream> body( | 164 scoped_ptr<UploadDataStream> body( |
| 165 new UploadDataStream(element_readers.Pass(), 0)); | 165 new UploadDataStream(element_readers.Pass(), 0)); |
| 166 ASSERT_EQ(OK, body->Init(CompletionCallback())); | 166 ASSERT_EQ(OK, body->Init(CompletionCallback())); |
| 167 // Yes, should be merged if the in-memory body is small here. | 167 // Yes, should be merged if the in-memory body is small here. |
| 168 ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 168 ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header", |
| 169 "some header", body.get())); | 169 body.get())); |
| 170 } | 170 } |
| 171 | 171 |
| 172 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { | 172 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { |
| 173 ScopedVector<UploadElementReader> element_readers; | 173 ScopedVector<UploadElementReader> element_readers; |
| 174 const std::string payload(10000, 'a'); // 'a' x 10000. | 174 const std::string payload(10000, 'a'); // 'a' x 10000. |
| 175 element_readers.push_back(new UploadBytesElementReader( | 175 element_readers.push_back( |
| 176 payload.data(), payload.size())); | 176 new UploadBytesElementReader(payload.data(), payload.size())); |
| 177 | 177 |
| 178 scoped_ptr<UploadDataStream> body( | 178 scoped_ptr<UploadDataStream> body( |
| 179 new UploadDataStream(element_readers.Pass(), 0)); | 179 new UploadDataStream(element_readers.Pass(), 0)); |
| 180 ASSERT_EQ(OK, body->Init(CompletionCallback())); | 180 ASSERT_EQ(OK, body->Init(CompletionCallback())); |
| 181 // Shouldn't be merged if the in-memory body is large here. | 181 // Shouldn't be merged if the in-memory body is large here. |
| 182 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody( | 182 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header", |
| 183 "some header", body.get())); | 183 body.get())); |
| 184 } | 184 } |
| 185 | 185 |
| 186 // Test to ensure the HttpStreamParser state machine does not get confused | 186 // Test to ensure the HttpStreamParser state machine does not get confused |
| 187 // when sending a request with a chunked body, where chunks become available | 187 // when sending a request with a chunked body, where chunks become available |
| 188 // asynchronously, over a socket where writes may also complete | 188 // asynchronously, over a socket where writes may also complete |
| 189 // asynchronously. | 189 // asynchronously. |
| 190 // This is a regression test for http://crbug.com/132243 | 190 // This is a regression test for http://crbug.com/132243 |
| 191 TEST(HttpStreamParser, AsyncChunkAndAsyncSocket) { | 191 TEST(HttpStreamParser, AsyncChunkAndAsyncSocket) { |
| 192 // The chunks that will be written in the request, as reflected in the | 192 // The chunks that will be written in the request, as reflected in the |
| 193 // MockWrites below. | 193 // MockWrites below. |
| 194 static const char kChunk1[] = "Chunk 1"; | 194 static const char kChunk1[] = "Chunk 1"; |
| 195 static const char kChunk2[] = "Chunky 2"; | 195 static const char kChunk2[] = "Chunky 2"; |
| 196 static const char kChunk3[] = "Test 3"; | 196 static const char kChunk3[] = "Test 3"; |
| 197 | 197 |
| 198 MockWrite writes[] = { | 198 MockWrite writes[] = { |
| 199 MockWrite(ASYNC, 0, | 199 MockWrite(ASYNC, |
| 200 "GET /one.html HTTP/1.1\r\n" | 200 0, |
| 201 "Host: localhost\r\n" | 201 "GET /one.html HTTP/1.1\r\n" |
| 202 "Transfer-Encoding: chunked\r\n" | 202 "Host: localhost\r\n" |
| 203 "Connection: keep-alive\r\n\r\n"), | 203 "Transfer-Encoding: chunked\r\n" |
| 204 MockWrite(ASYNC, 1, "7\r\nChunk 1\r\n"), | 204 "Connection: keep-alive\r\n\r\n"), |
| 205 MockWrite(ASYNC, 2, "8\r\nChunky 2\r\n"), | 205 MockWrite(ASYNC, 1, "7\r\nChunk 1\r\n"), |
| 206 MockWrite(ASYNC, 3, "6\r\nTest 3\r\n"), | 206 MockWrite(ASYNC, 2, "8\r\nChunky 2\r\n"), |
| 207 MockWrite(ASYNC, 4, "0\r\n\r\n"), | 207 MockWrite(ASYNC, 3, "6\r\nTest 3\r\n"), MockWrite(ASYNC, 4, "0\r\n\r\n"), |
| 208 }; | 208 }; |
| 209 | 209 |
| 210 // The size of the response body, as reflected in the Content-Length of the | 210 // The size of the response body, as reflected in the Content-Length of the |
| 211 // MockRead below. | 211 // MockRead below. |
| 212 static const int kBodySize = 8; | 212 static const int kBodySize = 8; |
| 213 | 213 |
| 214 MockRead reads[] = { | 214 MockRead reads[] = { |
| 215 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), | 215 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"), |
| 216 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"), | 216 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"), |
| 217 MockRead(ASYNC, 7, "one.html"), | 217 MockRead(ASYNC, 7, "one.html"), MockRead(SYNCHRONOUS, 0, 8), // EOF |
| 218 MockRead(SYNCHRONOUS, 0, 8), // EOF | |
| 219 }; | 218 }; |
| 220 | 219 |
| 221 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); | 220 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); |
| 222 upload_stream.AppendChunk(kChunk1, arraysize(kChunk1) - 1, false); | 221 upload_stream.AppendChunk(kChunk1, arraysize(kChunk1) - 1, false); |
| 223 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); | 222 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); |
| 224 | 223 |
| 225 DeterministicSocketData data(reads, arraysize(reads), | 224 DeterministicSocketData data( |
| 226 writes, arraysize(writes)); | 225 reads, arraysize(reads), writes, arraysize(writes)); |
| 227 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 226 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 228 | 227 |
| 229 scoped_ptr<DeterministicMockTCPClientSocket> transport( | 228 scoped_ptr<DeterministicMockTCPClientSocket> transport( |
| 230 new DeterministicMockTCPClientSocket(NULL, &data)); | 229 new DeterministicMockTCPClientSocket(NULL, &data)); |
| 231 data.set_delegate(transport->AsWeakPtr()); | 230 data.set_delegate(transport->AsWeakPtr()); |
| 232 | 231 |
| 233 TestCompletionCallback callback; | 232 TestCompletionCallback callback; |
| 234 int rv = transport->Connect(callback.callback()); | 233 int rv = transport->Connect(callback.callback()); |
| 235 rv = callback.GetResult(rv); | 234 rv = callback.GetResult(rv); |
| 236 ASSERT_EQ(OK, rv); | 235 ASSERT_EQ(OK, rv); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 249 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 248 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 250 | 249 |
| 251 HttpRequestHeaders request_headers; | 250 HttpRequestHeaders request_headers; |
| 252 request_headers.SetHeader("Host", "localhost"); | 251 request_headers.SetHeader("Host", "localhost"); |
| 253 request_headers.SetHeader("Transfer-Encoding", "chunked"); | 252 request_headers.SetHeader("Transfer-Encoding", "chunked"); |
| 254 request_headers.SetHeader("Connection", "keep-alive"); | 253 request_headers.SetHeader("Connection", "keep-alive"); |
| 255 | 254 |
| 256 HttpResponseInfo response_info; | 255 HttpResponseInfo response_info; |
| 257 // This will attempt to Write() the initial request and headers, which will | 256 // This will attempt to Write() the initial request and headers, which will |
| 258 // complete asynchronously. | 257 // complete asynchronously. |
| 259 rv = parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers, | 258 rv = parser.SendRequest("GET /one.html HTTP/1.1\r\n", |
| 260 &response_info, callback.callback()); | 259 request_headers, |
| 260 &response_info, |
| 261 callback.callback()); |
| 261 ASSERT_EQ(ERR_IO_PENDING, rv); | 262 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 262 | 263 |
| 263 // Complete the initial request write. Additionally, this should enqueue the | 264 // Complete the initial request write. Additionally, this should enqueue the |
| 264 // first chunk. | 265 // first chunk. |
| 265 data.RunFor(1); | 266 data.RunFor(1); |
| 266 ASSERT_FALSE(callback.have_result()); | 267 ASSERT_FALSE(callback.have_result()); |
| 267 | 268 |
| 268 // Now append another chunk (while the first write is still pending), which | 269 // Now append another chunk (while the first write is still pending), which |
| 269 // should not confuse the state machine. | 270 // should not confuse the state machine. |
| 270 upload_stream.AppendChunk(kChunk2, arraysize(kChunk2) - 1, false); | 271 upload_stream.AppendChunk(kChunk2, arraysize(kChunk2) - 1, false); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 ASSERT_EQ(ERR_IO_PENDING, rv); | 318 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 318 data.RunFor(1); | 319 data.RunFor(1); |
| 319 | 320 |
| 320 ASSERT_TRUE(callback.have_result()); | 321 ASSERT_TRUE(callback.have_result()); |
| 321 rv = callback.WaitForResult(); | 322 rv = callback.WaitForResult(); |
| 322 ASSERT_EQ(kBodySize, rv); | 323 ASSERT_EQ(kBodySize, rv); |
| 323 } | 324 } |
| 324 | 325 |
| 325 TEST(HttpStreamParser, TruncatedHeaders) { | 326 TEST(HttpStreamParser, TruncatedHeaders) { |
| 326 MockRead truncated_status_reads[] = { | 327 MockRead truncated_status_reads[] = { |
| 327 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"), | 328 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"), |
| 328 MockRead(SYNCHRONOUS, 0, 2), // EOF | 329 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 329 }; | 330 }; |
| 330 | 331 |
| 331 MockRead truncated_after_status_reads[] = { | 332 MockRead truncated_after_status_reads[] = { |
| 332 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\n"), | 333 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\n"), |
| 333 MockRead(SYNCHRONOUS, 0, 2), // EOF | 334 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 334 }; | 335 }; |
| 335 | 336 |
| 336 MockRead truncated_in_header_reads[] = { | 337 MockRead truncated_in_header_reads[] = { |
| 337 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHead"), | 338 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHead"), |
| 338 MockRead(SYNCHRONOUS, 0, 2), // EOF | 339 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 339 }; | 340 }; |
| 340 | 341 |
| 341 MockRead truncated_after_header_reads[] = { | 342 MockRead truncated_after_header_reads[] = { |
| 342 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n"), | 343 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n"), |
| 343 MockRead(SYNCHRONOUS, 0, 2), // EOF | 344 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 344 }; | 345 }; |
| 345 | 346 |
| 346 MockRead truncated_after_final_newline_reads[] = { | 347 MockRead truncated_after_final_newline_reads[] = { |
| 347 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r"), | 348 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r"), |
| 348 MockRead(SYNCHRONOUS, 0, 2), // EOF | 349 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 349 }; | 350 }; |
| 350 | 351 |
| 351 MockRead not_truncated_reads[] = { | 352 MockRead not_truncated_reads[] = { |
| 352 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r\n"), | 353 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r\n"), |
| 353 MockRead(SYNCHRONOUS, 0, 2), // EOF | 354 MockRead(SYNCHRONOUS, 0, 2), // EOF |
| 354 }; | 355 }; |
| 355 | 356 |
| 356 MockRead* reads[] = { | 357 MockRead* reads[] = { |
| 357 truncated_status_reads, | 358 truncated_status_reads, truncated_after_status_reads, |
| 358 truncated_after_status_reads, | 359 truncated_in_header_reads, truncated_after_header_reads, |
| 359 truncated_in_header_reads, | 360 truncated_after_final_newline_reads, not_truncated_reads, |
| 360 truncated_after_header_reads, | |
| 361 truncated_after_final_newline_reads, | |
| 362 not_truncated_reads, | |
| 363 }; | 361 }; |
| 364 | 362 |
| 365 MockWrite writes[] = { | 363 MockWrite writes[] = { |
| 366 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), | 364 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), |
| 367 }; | 365 }; |
| 368 | 366 |
| 369 enum { | 367 enum { |
| 370 HTTP = 0, | 368 HTTP = 0, |
| 371 HTTPS, | 369 HTTPS, |
| 372 NUM_PROTOCOLS, | 370 NUM_PROTOCOLS, |
| 373 }; | 371 }; |
| 374 | 372 |
| 375 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) { | 373 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) { |
| 376 SCOPED_TRACE(protocol); | 374 SCOPED_TRACE(protocol); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 401 request_info.url = GURL("https://localhost"); | 399 request_info.url = GURL("https://localhost"); |
| 402 } | 400 } |
| 403 request_info.load_flags = LOAD_NORMAL; | 401 request_info.load_flags = LOAD_NORMAL; |
| 404 | 402 |
| 405 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 403 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 406 HttpStreamParser parser( | 404 HttpStreamParser parser( |
| 407 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 405 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 408 | 406 |
| 409 HttpRequestHeaders request_headers; | 407 HttpRequestHeaders request_headers; |
| 410 HttpResponseInfo response_info; | 408 HttpResponseInfo response_info; |
| 411 rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, | 409 rv = parser.SendRequest("GET / HTTP/1.1\r\n", |
| 412 &response_info, callback.callback()); | 410 request_headers, |
| 411 &response_info, |
| 412 callback.callback()); |
| 413 ASSERT_EQ(OK, rv); | 413 ASSERT_EQ(OK, rv); |
| 414 | 414 |
| 415 rv = parser.ReadResponseHeaders(callback.callback()); | 415 rv = parser.ReadResponseHeaders(callback.callback()); |
| 416 if (i == arraysize(reads) - 1) { | 416 if (i == arraysize(reads) - 1) { |
| 417 EXPECT_EQ(OK, rv); | 417 EXPECT_EQ(OK, rv); |
| 418 EXPECT_TRUE(response_info.headers.get()); | 418 EXPECT_TRUE(response_info.headers.get()); |
| 419 } else { | 419 } else { |
| 420 if (protocol == HTTP) { | 420 if (protocol == HTTP) { |
| 421 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); | 421 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); |
| 422 EXPECT_TRUE(response_info.headers.get()); | 422 EXPECT_TRUE(response_info.headers.get()); |
| 423 } else { | 423 } else { |
| 424 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, rv); | 424 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, rv); |
| 425 EXPECT_FALSE(response_info.headers.get()); | 425 EXPECT_FALSE(response_info.headers.get()); |
| 426 } | 426 } |
| 427 } | 427 } |
| 428 } | 428 } |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 | 431 |
| 432 // Confirm that on 101 response, the headers are parsed but the data that | 432 // Confirm that on 101 response, the headers are parsed but the data that |
| 433 // follows remains in the buffer. | 433 // follows remains in the buffer. |
| 434 TEST(HttpStreamParser, Websocket101Response) { | 434 TEST(HttpStreamParser, Websocket101Response) { |
| 435 MockRead reads[] = { | 435 MockRead reads[] = { |
| 436 MockRead(SYNCHRONOUS, 1, | 436 MockRead(SYNCHRONOUS, |
| 437 "HTTP/1.1 101 Switching Protocols\r\n" | 437 1, |
| 438 "Upgrade: websocket\r\n" | 438 "HTTP/1.1 101 Switching Protocols\r\n" |
| 439 "Connection: Upgrade\r\n" | 439 "Upgrade: websocket\r\n" |
| 440 "\r\n" | 440 "Connection: Upgrade\r\n" |
| 441 "a fake websocket frame"), | 441 "\r\n" |
| 442 "a fake websocket frame"), |
| 442 }; | 443 }; |
| 443 | 444 |
| 444 MockWrite writes[] = { | 445 MockWrite writes[] = { |
| 445 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), | 446 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), |
| 446 }; | 447 }; |
| 447 | 448 |
| 448 DeterministicSocketData data(reads, arraysize(reads), | 449 DeterministicSocketData data( |
| 449 writes, arraysize(writes)); | 450 reads, arraysize(reads), writes, arraysize(writes)); |
| 450 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 451 data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 451 data.SetStop(2); | 452 data.SetStop(2); |
| 452 | 453 |
| 453 scoped_ptr<DeterministicMockTCPClientSocket> transport( | 454 scoped_ptr<DeterministicMockTCPClientSocket> transport( |
| 454 new DeterministicMockTCPClientSocket(NULL, &data)); | 455 new DeterministicMockTCPClientSocket(NULL, &data)); |
| 455 data.set_delegate(transport->AsWeakPtr()); | 456 data.set_delegate(transport->AsWeakPtr()); |
| 456 | 457 |
| 457 TestCompletionCallback callback; | 458 TestCompletionCallback callback; |
| 458 int rv = transport->Connect(callback.callback()); | 459 int rv = transport->Connect(callback.callback()); |
| 459 rv = callback.GetResult(rv); | 460 rv = callback.GetResult(rv); |
| 460 ASSERT_EQ(OK, rv); | 461 ASSERT_EQ(OK, rv); |
| 461 | 462 |
| 462 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | 463 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); |
| 463 socket_handle->SetSocket(transport.PassAs<StreamSocket>()); | 464 socket_handle->SetSocket(transport.PassAs<StreamSocket>()); |
| 464 | 465 |
| 465 HttpRequestInfo request_info; | 466 HttpRequestInfo request_info; |
| 466 request_info.method = "GET"; | 467 request_info.method = "GET"; |
| 467 request_info.url = GURL("http://localhost"); | 468 request_info.url = GURL("http://localhost"); |
| 468 request_info.load_flags = LOAD_NORMAL; | 469 request_info.load_flags = LOAD_NORMAL; |
| 469 | 470 |
| 470 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | 471 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); |
| 471 HttpStreamParser parser( | 472 HttpStreamParser parser( |
| 472 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); | 473 socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog()); |
| 473 | 474 |
| 474 HttpRequestHeaders request_headers; | 475 HttpRequestHeaders request_headers; |
| 475 HttpResponseInfo response_info; | 476 HttpResponseInfo response_info; |
| 476 rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers, | 477 rv = parser.SendRequest("GET / HTTP/1.1\r\n", |
| 477 &response_info, callback.callback()); | 478 request_headers, |
| 479 &response_info, |
| 480 callback.callback()); |
| 478 ASSERT_EQ(OK, rv); | 481 ASSERT_EQ(OK, rv); |
| 479 | 482 |
| 480 rv = parser.ReadResponseHeaders(callback.callback()); | 483 rv = parser.ReadResponseHeaders(callback.callback()); |
| 481 EXPECT_EQ(OK, rv); | 484 EXPECT_EQ(OK, rv); |
| 482 ASSERT_TRUE(response_info.headers.get()); | 485 ASSERT_TRUE(response_info.headers.get()); |
| 483 EXPECT_EQ(101, response_info.headers->response_code()); | 486 EXPECT_EQ(101, response_info.headers->response_code()); |
| 484 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade")); | 487 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade")); |
| 485 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket")); | 488 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket")); |
| 486 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset()); | 489 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset()); |
| 487 EXPECT_EQ("a fake websocket frame", | 490 EXPECT_EQ( |
| 488 base::StringPiece(read_buffer->StartOfBuffer(), | 491 "a fake websocket frame", |
| 489 read_buffer->capacity())); | 492 base::StringPiece(read_buffer->StartOfBuffer(), read_buffer->capacity())); |
| 490 } | 493 } |
| 491 | 494 |
| 492 // Helper class for constructing HttpStreamParser and running GET requests. | 495 // Helper class for constructing HttpStreamParser and running GET requests. |
| 493 class SimpleGetRunner { | 496 class SimpleGetRunner { |
| 494 public: | 497 public: |
| 495 SimpleGetRunner() : read_buffer_(new GrowableIOBuffer), sequence_number_(0) { | 498 SimpleGetRunner() : read_buffer_(new GrowableIOBuffer), sequence_number_(0) { |
| 496 writes_.push_back(MockWrite( | 499 writes_.push_back( |
| 497 SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n")); | 500 MockWrite(SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n")); |
| 498 } | 501 } |
| 499 | 502 |
| 500 HttpStreamParser* parser() { return parser_.get(); } | 503 HttpStreamParser* parser() { return parser_.get(); } |
| 501 GrowableIOBuffer* read_buffer() { return read_buffer_.get(); } | 504 GrowableIOBuffer* read_buffer() { return read_buffer_.get(); } |
| 502 HttpResponseInfo* response_info() { return &response_info_; } | 505 HttpResponseInfo* response_info() { return &response_info_; } |
| 503 | 506 |
| 504 void AddInitialData(const std::string& data) { | 507 void AddInitialData(const std::string& data) { |
| 505 int offset = read_buffer_->offset(); | 508 int offset = read_buffer_->offset(); |
| 506 int size = data.size(); | 509 int size = data.size(); |
| 507 read_buffer_->SetCapacity(offset + size); | 510 read_buffer_->SetCapacity(offset + size); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 532 | 535 |
| 533 socket_handle_->SetSocket(transport_.PassAs<StreamSocket>()); | 536 socket_handle_->SetSocket(transport_.PassAs<StreamSocket>()); |
| 534 | 537 |
| 535 request_info_.method = "GET"; | 538 request_info_.method = "GET"; |
| 536 request_info_.url = GURL("http://localhost"); | 539 request_info_.url = GURL("http://localhost"); |
| 537 request_info_.load_flags = LOAD_NORMAL; | 540 request_info_.load_flags = LOAD_NORMAL; |
| 538 | 541 |
| 539 parser_.reset(new HttpStreamParser( | 542 parser_.reset(new HttpStreamParser( |
| 540 socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog())); | 543 socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog())); |
| 541 | 544 |
| 542 rv = parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_, | 545 rv = parser_->SendRequest("GET / HTTP/1.1\r\n", |
| 543 &response_info_, callback.callback()); | 546 request_headers_, |
| 547 &response_info_, |
| 548 callback.callback()); |
| 544 ASSERT_EQ(OK, rv); | 549 ASSERT_EQ(OK, rv); |
| 545 } | 550 } |
| 546 | 551 |
| 547 void ReadHeaders() { | 552 void ReadHeaders() { |
| 548 TestCompletionCallback callback; | 553 TestCompletionCallback callback; |
| 549 EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback())); | 554 EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback())); |
| 550 } | 555 } |
| 551 | 556 |
| 552 void ReadBody(int user_buf_len, int* read_lengths) { | 557 void ReadBody(int user_buf_len, int* read_lengths) { |
| 553 TestCompletionCallback callback; | 558 TestCompletionCallback callback; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 EXPECT_EQ(0, get_runner.parser()->received_bytes()); | 593 EXPECT_EQ(0, get_runner.parser()->received_bytes()); |
| 589 int response_size = response.size(); | 594 int response_size = response.size(); |
| 590 int read_lengths[] = {response_size, 0}; | 595 int read_lengths[] = {response_size, 0}; |
| 591 get_runner.ReadBody(response_size, read_lengths); | 596 get_runner.ReadBody(response_size, read_lengths); |
| 592 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 597 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 593 } | 598 } |
| 594 | 599 |
| 595 // Test basic case where there is no keep-alive or extra data from the socket, | 600 // Test basic case where there is no keep-alive or extra data from the socket, |
| 596 // and the entire response is received in a single read. | 601 // and the entire response is received in a single read. |
| 597 TEST(HttpStreamParser, ReceivedBytesNormal) { | 602 TEST(HttpStreamParser, ReceivedBytesNormal) { |
| 598 std::string headers = "HTTP/1.1 200 OK\r\n" | 603 std::string headers = |
| 604 "HTTP/1.1 200 OK\r\n" |
| 599 "Content-Length: 7\r\n\r\n"; | 605 "Content-Length: 7\r\n\r\n"; |
| 600 std::string body = "content"; | 606 std::string body = "content"; |
| 601 std::string response = headers + body; | 607 std::string response = headers + body; |
| 602 | 608 |
| 603 SimpleGetRunner get_runner; | 609 SimpleGetRunner get_runner; |
| 604 get_runner.AddRead(response); | 610 get_runner.AddRead(response); |
| 605 get_runner.SetupParserAndSendRequest(); | 611 get_runner.SetupParserAndSendRequest(); |
| 606 get_runner.ReadHeaders(); | 612 get_runner.ReadHeaders(); |
| 607 int64 headers_size = headers.size(); | 613 int64 headers_size = headers.size(); |
| 608 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); | 614 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); |
| 609 int body_size = body.size(); | 615 int body_size = body.size(); |
| 610 int read_lengths[] = {body_size, 0}; | 616 int read_lengths[] = {body_size, 0}; |
| 611 get_runner.ReadBody(body_size, read_lengths); | 617 get_runner.ReadBody(body_size, read_lengths); |
| 612 int64 response_size = response.size(); | 618 int64 response_size = response.size(); |
| 613 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 619 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 614 } | 620 } |
| 615 | 621 |
| 616 // Test that bytes that represent "next" response are not counted | 622 // Test that bytes that represent "next" response are not counted |
| 617 // as current response "received_bytes". | 623 // as current response "received_bytes". |
| 618 TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) { | 624 TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) { |
| 619 std::string headers = "HTTP/1.1 200 OK\r\n" | 625 std::string headers = |
| 626 "HTTP/1.1 200 OK\r\n" |
| 620 "Content-Length: 8\r\n\r\n"; | 627 "Content-Length: 8\r\n\r\n"; |
| 621 std::string body = "content8"; | 628 std::string body = "content8"; |
| 622 std::string response = headers + body; | 629 std::string response = headers + body; |
| 623 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; | 630 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; |
| 624 std::string data = response + next_response; | 631 std::string data = response + next_response; |
| 625 | 632 |
| 626 SimpleGetRunner get_runner; | 633 SimpleGetRunner get_runner; |
| 627 get_runner.AddRead(data); | 634 get_runner.AddRead(data); |
| 628 get_runner.SetupParserAndSendRequest(); | 635 get_runner.SetupParserAndSendRequest(); |
| 629 get_runner.ReadHeaders(); | 636 get_runner.ReadHeaders(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 640 } | 647 } |
| 641 | 648 |
| 642 // Test that "received_bytes" calculation works fine when last read | 649 // Test that "received_bytes" calculation works fine when last read |
| 643 // contains more data than requested by user. | 650 // contains more data than requested by user. |
| 644 // We send data in two reads: | 651 // We send data in two reads: |
| 645 // 1) Headers + beginning of response | 652 // 1) Headers + beginning of response |
| 646 // 2) remaining part of response + next response start | 653 // 2) remaining part of response + next response start |
| 647 // We setup user read buffer so it fully accepts the beginnig of response | 654 // We setup user read buffer so it fully accepts the beginnig of response |
| 648 // body, but it is larger that remaining part of body. | 655 // body, but it is larger that remaining part of body. |
| 649 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) { | 656 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) { |
| 650 std::string headers = "HTTP/1.1 200 OK\r\n" | 657 std::string headers = |
| 658 "HTTP/1.1 200 OK\r\n" |
| 651 "Content-Length: 36\r\n\r\n"; | 659 "Content-Length: 36\r\n\r\n"; |
| 652 int64 user_buf_len = 32; | 660 int64 user_buf_len = 32; |
| 653 std::string body_start = std::string(user_buf_len, '#'); | 661 std::string body_start = std::string(user_buf_len, '#'); |
| 654 int body_start_size = body_start.size(); | 662 int body_start_size = body_start.size(); |
| 655 EXPECT_EQ(user_buf_len, body_start_size); | 663 EXPECT_EQ(user_buf_len, body_start_size); |
| 656 std::string response_start = headers + body_start; | 664 std::string response_start = headers + body_start; |
| 657 std::string body_end = "abcd"; | 665 std::string body_end = "abcd"; |
| 658 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; | 666 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; |
| 659 std::string response_end = body_end + next_response; | 667 std::string response_end = body_end + next_response; |
| 660 | 668 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 672 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 680 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 673 int64 next_response_size = next_response.size(); | 681 int64 next_response_size = next_response.size(); |
| 674 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); | 682 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); |
| 675 } | 683 } |
| 676 | 684 |
| 677 // Test that "received_bytes" calculation works fine when there is no | 685 // Test that "received_bytes" calculation works fine when there is no |
| 678 // network activity at all; that is when all data is read from read buffer. | 686 // network activity at all; that is when all data is read from read buffer. |
| 679 // In this case read buffer contains two responses. We expect that only | 687 // In this case read buffer contains two responses. We expect that only |
| 680 // bytes that correspond to the first one are taken into account. | 688 // bytes that correspond to the first one are taken into account. |
| 681 TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) { | 689 TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) { |
| 682 std::string headers = "HTTP/1.1 200 OK\r\n" | 690 std::string headers = |
| 691 "HTTP/1.1 200 OK\r\n" |
| 683 "Content-Length: 7\r\n\r\n"; | 692 "Content-Length: 7\r\n\r\n"; |
| 684 std::string body = "content"; | 693 std::string body = "content"; |
| 685 std::string response = headers + body; | 694 std::string response = headers + body; |
| 686 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; | 695 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO"; |
| 687 std::string data = response + next_response; | 696 std::string data = response + next_response; |
| 688 | 697 |
| 689 SimpleGetRunner get_runner; | 698 SimpleGetRunner get_runner; |
| 690 get_runner.AddInitialData(data); | 699 get_runner.AddInitialData(data); |
| 691 get_runner.SetupParserAndSendRequest(); | 700 get_runner.SetupParserAndSendRequest(); |
| 692 get_runner.ReadHeaders(); | 701 get_runner.ReadHeaders(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 719 int body_size = body.size(); | 728 int body_size = body.size(); |
| 720 int read_lengths[] = {body_size, 0}; | 729 int read_lengths[] = {body_size, 0}; |
| 721 get_runner.ReadBody(body_size, read_lengths); | 730 get_runner.ReadBody(body_size, read_lengths); |
| 722 EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes()); | 731 EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes()); |
| 723 EXPECT_EQ(0, get_runner.read_buffer()->offset()); | 732 EXPECT_EQ(0, get_runner.read_buffer()->offset()); |
| 724 } | 733 } |
| 725 | 734 |
| 726 // Test the case when the resulting read_buf contains both unused bytes and | 735 // Test the case when the resulting read_buf contains both unused bytes and |
| 727 // bytes ejected by chunked-encoding filter. | 736 // bytes ejected by chunked-encoding filter. |
| 728 TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) { | 737 TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) { |
| 729 std::string response = "HTTP/1.1 200 OK\r\n" | 738 std::string response = |
| 739 "HTTP/1.1 200 OK\r\n" |
| 730 "Transfer-Encoding: chunked\r\n\r\n" | 740 "Transfer-Encoding: chunked\r\n\r\n" |
| 731 "7\r\nChunk 1\r\n" | 741 "7\r\nChunk 1\r\n" |
| 732 "8\r\nChunky 2\r\n" | 742 "8\r\nChunky 2\r\n" |
| 733 "6\r\nTest 3\r\n" | 743 "6\r\nTest 3\r\n" |
| 734 "0\r\n\r\n"; | 744 "0\r\n\r\n"; |
| 735 std::string next_response = "foo bar\r\n"; | 745 std::string next_response = "foo bar\r\n"; |
| 736 std::string data = response + next_response; | 746 std::string data = response + next_response; |
| 737 | 747 |
| 738 SimpleGetRunner get_runner; | 748 SimpleGetRunner get_runner; |
| 739 get_runner.AddInitialData(data); | 749 get_runner.AddInitialData(data); |
| 740 get_runner.SetupParserAndSendRequest(); | 750 get_runner.SetupParserAndSendRequest(); |
| 741 get_runner.ReadHeaders(); | 751 get_runner.ReadHeaders(); |
| 742 int read_lengths[] = {4, 3, 6, 2, 6, 0}; | 752 int read_lengths[] = {4, 3, 6, 2, 6, 0}; |
| 743 get_runner.ReadBody(7, read_lengths); | 753 get_runner.ReadBody(7, read_lengths); |
| 744 int64 response_size = response.size(); | 754 int64 response_size = response.size(); |
| 745 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 755 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 746 int64 next_response_size = next_response.size(); | 756 int64 next_response_size = next_response.size(); |
| 747 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); | 757 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset()); |
| 748 } | 758 } |
| 749 | 759 |
| 750 // Test that data transfered in multiple reads is correctly processed. | 760 // Test that data transfered in multiple reads is correctly processed. |
| 751 // We feed data into 4-bytes reads. Also we set length of read | 761 // We feed data into 4-bytes reads. Also we set length of read |
| 752 // buffer to 5-bytes to test all possible buffer misaligments. | 762 // buffer to 5-bytes to test all possible buffer misaligments. |
| 753 TEST(HttpStreamParser, ReceivedBytesMultipleReads) { | 763 TEST(HttpStreamParser, ReceivedBytesMultipleReads) { |
| 754 std::string headers = "HTTP/1.1 200 OK\r\n" | 764 std::string headers = |
| 765 "HTTP/1.1 200 OK\r\n" |
| 755 "Content-Length: 33\r\n\r\n"; | 766 "Content-Length: 33\r\n\r\n"; |
| 756 std::string body = "foo bar baz\r\n" | 767 std::string body = |
| 768 "foo bar baz\r\n" |
| 757 "sputnik mir babushka"; | 769 "sputnik mir babushka"; |
| 758 std::string response = headers + body; | 770 std::string response = headers + body; |
| 759 | 771 |
| 760 size_t receive_length = 4; | 772 size_t receive_length = 4; |
| 761 std::vector<std::string> blocks; | 773 std::vector<std::string> blocks; |
| 762 for (size_t i = 0; i < response.size(); i += receive_length) { | 774 for (size_t i = 0; i < response.size(); i += receive_length) { |
| 763 size_t length = std::min(receive_length, response.size() - i); | 775 size_t length = std::min(receive_length, response.size() - i); |
| 764 blocks.push_back(response.substr(i, length)); | 776 blocks.push_back(response.substr(i, length)); |
| 765 } | 777 } |
| 766 | 778 |
| 767 SimpleGetRunner get_runner; | 779 SimpleGetRunner get_runner; |
| 768 for (std::vector<std::string>::size_type i = 0; i < blocks.size(); ++i) | 780 for (std::vector<std::string>::size_type i = 0; i < blocks.size(); ++i) |
| 769 get_runner.AddRead(blocks[i]); | 781 get_runner.AddRead(blocks[i]); |
| 770 get_runner.SetupParserAndSendRequest(); | 782 get_runner.SetupParserAndSendRequest(); |
| 771 get_runner.ReadHeaders(); | 783 get_runner.ReadHeaders(); |
| 772 int64 headers_size = headers.size(); | 784 int64 headers_size = headers.size(); |
| 773 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); | 785 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); |
| 774 int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0}; | 786 int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0}; |
| 775 get_runner.ReadBody(receive_length + 1, read_lengths); | 787 get_runner.ReadBody(receive_length + 1, read_lengths); |
| 776 int64 response_size = response.size(); | 788 int64 response_size = response.size(); |
| 777 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 789 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 778 } | 790 } |
| 779 | 791 |
| 780 // Test that "continue" HTTP header is counted as "received_bytes". | 792 // Test that "continue" HTTP header is counted as "received_bytes". |
| 781 TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) { | 793 TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) { |
| 782 std::string status100 = "HTTP/1.1 100 OK\r\n\r\n"; | 794 std::string status100 = "HTTP/1.1 100 OK\r\n\r\n"; |
| 783 std::string headers = "HTTP/1.1 200 OK\r\n" | 795 std::string headers = |
| 796 "HTTP/1.1 200 OK\r\n" |
| 784 "Content-Length: 7\r\n\r\n"; | 797 "Content-Length: 7\r\n\r\n"; |
| 785 int64 headers_size = status100.size() + headers.size(); | 798 int64 headers_size = status100.size() + headers.size(); |
| 786 std::string body = "content"; | 799 std::string body = "content"; |
| 787 std::string response = headers + body; | 800 std::string response = headers + body; |
| 788 | 801 |
| 789 SimpleGetRunner get_runner; | 802 SimpleGetRunner get_runner; |
| 790 get_runner.AddRead(status100); | 803 get_runner.AddRead(status100); |
| 791 get_runner.AddRead(response); | 804 get_runner.AddRead(response); |
| 792 get_runner.SetupParserAndSendRequest(); | 805 get_runner.SetupParserAndSendRequest(); |
| 793 get_runner.ReadHeaders(); | 806 get_runner.ReadHeaders(); |
| 794 EXPECT_EQ(100, get_runner.response_info()->headers->response_code()); | 807 EXPECT_EQ(100, get_runner.response_info()->headers->response_code()); |
| 795 int64 status100_size = status100.size(); | 808 int64 status100_size = status100.size(); |
| 796 EXPECT_EQ(status100_size, get_runner.parser()->received_bytes()); | 809 EXPECT_EQ(status100_size, get_runner.parser()->received_bytes()); |
| 797 get_runner.ReadHeaders(); | 810 get_runner.ReadHeaders(); |
| 798 EXPECT_EQ(200, get_runner.response_info()->headers->response_code()); | 811 EXPECT_EQ(200, get_runner.response_info()->headers->response_code()); |
| 799 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); | 812 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); |
| 800 int64 response_size = headers_size + body.size(); | 813 int64 response_size = headers_size + body.size(); |
| 801 int body_size = body.size(); | 814 int body_size = body.size(); |
| 802 int read_lengths[] = {body_size, 0}; | 815 int read_lengths[] = {body_size, 0}; |
| 803 get_runner.ReadBody(body_size, read_lengths); | 816 get_runner.ReadBody(body_size, read_lengths); |
| 804 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 817 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 805 } | 818 } |
| 806 | 819 |
| 807 } // namespace | 820 } // namespace |
| 808 | 821 |
| 809 } // namespace net | 822 } // namespace net |
| OLD | NEW |