Chromium Code Reviews| 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 <stdint.h> | |
| 8 | |
| 7 #include <algorithm> | 9 #include <algorithm> |
| 8 #include <string> | 10 #include <string> |
| 9 #include <vector> | 11 #include <vector> |
| 10 | 12 |
| 11 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 12 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
| 13 #include "base/files/scoped_temp_dir.h" | 15 #include "base/files/scoped_temp_dir.h" |
| 14 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
| 15 #include "base/run_loop.h" | 17 #include "base/run_loop.h" |
| 16 #include "base/strings/string_piece.h" | 18 #include "base/strings/string_piece.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 data->set_socket(socket.get()); | 54 data->set_socket(socket.get()); |
| 53 | 55 |
| 54 TestCompletionCallback callback; | 56 TestCompletionCallback callback; |
| 55 EXPECT_EQ(OK, socket->Connect(callback.callback())); | 57 EXPECT_EQ(OK, socket->Connect(callback.callback())); |
| 56 | 58 |
| 57 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); | 59 scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); |
| 58 socket_handle->SetSocket(socket.Pass()); | 60 socket_handle->SetSocket(socket.Pass()); |
| 59 return socket_handle.Pass(); | 61 return socket_handle.Pass(); |
| 60 } | 62 } |
| 61 | 63 |
| 64 // Helper method to get the total data size of the MockWrites in |writes|. | |
| 65 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
| |
| 66 int64_t total = 0; | |
| 67 for (const MockWrite* write = writes; write != writes + length; ++write) { | |
| 68 total += write->data_len; | |
| 69 } | |
| 70 return total; | |
| 71 } | |
| 72 | |
| 62 // The empty payload is how the last chunk is encoded. | 73 // The empty payload is how the last chunk is encoded. |
| 63 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { | 74 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) { |
| 64 char output[kOutputSize]; | 75 char output[kOutputSize]; |
| 65 | 76 |
| 66 const base::StringPiece kPayload = ""; | 77 const base::StringPiece kPayload = ""; |
| 67 const base::StringPiece kExpected = "0\r\n\r\n"; | 78 const base::StringPiece kExpected = "0\r\n\r\n"; |
| 68 const int num_bytes_written = | 79 const int num_bytes_written = |
| 69 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); | 80 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output)); |
| 70 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); | 81 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written)); |
| 71 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); | 82 EXPECT_EQ(kExpected, base::StringPiece(output, num_bytes_written)); |
| (...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 998 get_runner.ReadHeaders(); | 1009 get_runner.ReadHeaders(); |
| 999 EXPECT_EQ(200, get_runner.response_info()->headers->response_code()); | 1010 EXPECT_EQ(200, get_runner.response_info()->headers->response_code()); |
| 1000 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); | 1011 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes()); |
| 1001 int64 response_size = headers_size + body.size(); | 1012 int64 response_size = headers_size + body.size(); |
| 1002 int body_size = body.size(); | 1013 int body_size = body.size(); |
| 1003 int read_lengths[] = {body_size, 0}; | 1014 int read_lengths[] = {body_size, 0}; |
| 1004 get_runner.ReadBody(body_size, read_lengths); | 1015 get_runner.ReadBody(body_size, read_lengths); |
| 1005 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); | 1016 EXPECT_EQ(response_size, get_runner.parser()->received_bytes()); |
| 1006 } | 1017 } |
| 1007 | 1018 |
| 1019 TEST(HttpStreamParser, SentBytesNoHeaders) { | |
| 1020 MockWrite writes[] = { | |
| 1021 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), | |
| 1022 }; | |
| 1023 | |
| 1024 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1025 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1026 CreateConnectedSocketHandle(&data); | |
| 1027 | |
| 1028 HttpRequestInfo request; | |
| 1029 request.method = "GET"; | |
| 1030 request.url = GURL("http://localhost"); | |
| 1031 | |
| 1032 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1033 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1034 BoundNetLog()); | |
| 1035 | |
| 1036 HttpResponseInfo response; | |
| 1037 TestCompletionCallback callback; | |
| 1038 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.
| |
| 1039 &response, callback.callback())); | |
| 1040 | |
| 1041 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1042 } | |
| 1043 | |
| 1044 TEST(HttpStreamParser, SentBytesWithHeaders) { | |
| 1045 MockWrite writes[] = { | |
| 1046 MockWrite(SYNCHRONOUS, 0, | |
| 1047 "GET / HTTP/1.1\r\n" | |
| 1048 "Host: localhost\r\n" | |
| 1049 "Connection: Keep-Alive\r\n\r\n"), | |
| 1050 }; | |
| 1051 | |
| 1052 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1053 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1054 CreateConnectedSocketHandle(&data); | |
| 1055 | |
| 1056 HttpRequestInfo request; | |
| 1057 request.method = "GET"; | |
| 1058 request.url = GURL("http://localhost"); | |
| 1059 | |
| 1060 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1061 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1062 BoundNetLog()); | |
| 1063 | |
| 1064 HttpRequestHeaders headers; | |
| 1065 headers.SetHeader("Host", "localhost"); | |
| 1066 headers.SetHeader("Connection", "Keep-Alive"); | |
| 1067 | |
| 1068 HttpResponseInfo response; | |
| 1069 TestCompletionCallback callback; | |
| 1070 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, | |
| 1071 callback.callback())); | |
| 1072 | |
| 1073 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1074 } | |
| 1075 | |
| 1076 TEST(HttpStreamParser, SentBytesWithHeadersMultiWrite) { | |
| 1077 MockWrite writes[] = { | |
| 1078 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), | |
| 1079 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), | |
| 1080 MockWrite(SYNCHRONOUS, 2, "Connection: Keep-Alive\r\n\r\n"), | |
| 1081 }; | |
| 1082 | |
| 1083 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1084 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1085 CreateConnectedSocketHandle(&data); | |
| 1086 | |
| 1087 HttpRequestInfo request; | |
| 1088 request.method = "GET"; | |
| 1089 request.url = GURL("http://localhost"); | |
| 1090 | |
| 1091 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1092 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1093 BoundNetLog()); | |
| 1094 | |
| 1095 HttpRequestHeaders headers; | |
| 1096 headers.SetHeader("Host", "localhost"); | |
| 1097 headers.SetHeader("Connection", "Keep-Alive"); | |
| 1098 | |
| 1099 HttpResponseInfo response; | |
| 1100 TestCompletionCallback callback; | |
| 1101 | |
| 1102 int rv = parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, | |
| 1103 callback.callback()); | |
| 1104 ASSERT_EQ(OK, rv); | |
| 1105 | |
| 1106 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1107 } | |
| 1108 | |
| 1109 TEST(HttpStreamParser, SentBytesWithErrorWritingHeaders) { | |
| 1110 MockWrite writes[] = { | |
| 1111 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), | |
| 1112 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), | |
| 1113 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 2), | |
| 1114 }; | |
| 1115 | |
| 1116 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1117 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1118 CreateConnectedSocketHandle(&data); | |
| 1119 | |
| 1120 HttpRequestInfo request; | |
| 1121 request.method = "GET"; | |
| 1122 request.url = GURL("http://localhost"); | |
| 1123 | |
| 1124 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1125 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1126 BoundNetLog()); | |
| 1127 | |
| 1128 HttpRequestHeaders headers; | |
| 1129 headers.SetHeader("Host", "localhost"); | |
| 1130 headers.SetHeader("Connection", "Keep-Alive"); | |
| 1131 | |
| 1132 HttpResponseInfo response; | |
| 1133 TestCompletionCallback callback; | |
| 1134 ASSERT_EQ(ERR_CONNECTION_RESET, | |
| 1135 parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, | |
| 1136 callback.callback())); | |
| 1137 | |
| 1138 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1139 } | |
| 1140 | |
| 1141 TEST(HttpStreamParser, SentBytesPost) { | |
| 1142 MockWrite writes[] = { | |
| 1143 MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"), | |
| 1144 MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"), | |
| 1145 MockWrite(SYNCHRONOUS, 2, "hello world!"), | |
| 1146 }; | |
| 1147 | |
| 1148 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1149 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1150 CreateConnectedSocketHandle(&data); | |
| 1151 | |
| 1152 ScopedVector<UploadElementReader> element_readers; | |
| 1153 element_readers.push_back(new UploadBytesElementReader("hello world!", 12)); | |
| 1154 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); | |
| 1155 ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); | |
| 1156 | |
| 1157 HttpRequestInfo request; | |
| 1158 request.method = "POST"; | |
| 1159 request.url = GURL("http://localhost"); | |
| 1160 request.upload_data_stream = &upload_data_stream; | |
| 1161 | |
| 1162 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1163 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1164 BoundNetLog()); | |
| 1165 | |
| 1166 HttpRequestHeaders headers; | |
| 1167 headers.SetHeader("Content-Length", "12"); | |
| 1168 | |
| 1169 HttpResponseInfo response; | |
| 1170 TestCompletionCallback callback; | |
| 1171 ASSERT_EQ(OK, parser.SendRequest("POST / HTTP/1.1\r\n", headers, &response, | |
| 1172 callback.callback())); | |
| 1173 | |
| 1174 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1175 } | |
| 1176 | |
| 1177 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.
| |
| 1178 static const char kChunk1[] = "Chunk 1"; | |
| 1179 static const char kChunk2[] = "Chunky 2"; | |
| 1180 static const char kChunk3[] = "Test 3"; | |
| 1181 | |
| 1182 MockWrite writes[] = { | |
| 1183 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"), | |
| 1184 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"), | |
| 1185 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"), | |
| 1186 MockWrite(ASYNC, 3, "8\r\nChunky 2\r\n"), | |
| 1187 MockWrite(ASYNC, 4, "6\r\nTest 3\r\n"), | |
| 1188 MockWrite(ASYNC, 5, "0\r\n\r\n"), | |
| 1189 }; | |
| 1190 | |
| 1191 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1192 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1193 CreateConnectedSocketHandle(&data); | |
| 1194 | |
| 1195 ChunkedUploadDataStream upload_data_stream(0); | |
| 1196 ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); | |
| 1197 | |
| 1198 HttpRequestInfo request; | |
| 1199 request.method = "POST"; | |
| 1200 request.url = GURL("http://localhost"); | |
| 1201 request.upload_data_stream = &upload_data_stream; | |
| 1202 | |
| 1203 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1204 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1205 BoundNetLog()); | |
| 1206 | |
| 1207 HttpRequestHeaders headers; | |
| 1208 headers.SetHeader("Transfer-Encoding", "chunked"); | |
| 1209 | |
| 1210 HttpResponseInfo response; | |
| 1211 TestCompletionCallback callback; | |
| 1212 ASSERT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers, | |
| 1213 &response, callback.callback())); | |
| 1214 | |
| 1215 base::RunLoop().RunUntilIdle(); | |
| 1216 upload_data_stream.AppendData(kChunk1, arraysize(kChunk1) - 1, false); | |
| 1217 | |
| 1218 base::RunLoop().RunUntilIdle(); | |
| 1219 upload_data_stream.AppendData(kChunk2, arraysize(kChunk2) - 1, false); | |
| 1220 | |
| 1221 base::RunLoop().RunUntilIdle(); | |
| 1222 upload_data_stream.AppendData(kChunk3, arraysize(kChunk3) - 1, true); | |
| 1223 | |
| 1224 ASSERT_EQ(OK, callback.WaitForResult()); | |
| 1225 | |
| 1226 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1227 } | |
| 1228 | |
| 1229 TEST(HttpStreamParser, SentBytesChunkedPostError) { | |
| 1230 static const char kChunk[] = "Chunk 1"; | |
| 1231 | |
| 1232 MockWrite writes[] = { | |
| 1233 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"), | |
| 1234 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"), | |
| 1235 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"), | |
| 1236 MockWrite(SYNCHRONOUS, ERR_FAILED, 3), | |
| 1237 }; | |
| 1238 | |
| 1239 SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); | |
| 1240 scoped_ptr<ClientSocketHandle> socket_handle = | |
| 1241 CreateConnectedSocketHandle(&data); | |
| 1242 | |
| 1243 ChunkedUploadDataStream upload_data_stream(0); | |
| 1244 ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); | |
| 1245 | |
| 1246 HttpRequestInfo request; | |
| 1247 request.method = "POST"; | |
| 1248 request.url = GURL("http://localhost"); | |
| 1249 request.upload_data_stream = &upload_data_stream; | |
| 1250 | |
| 1251 scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); | |
| 1252 HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), | |
| 1253 BoundNetLog()); | |
| 1254 | |
| 1255 HttpRequestHeaders headers; | |
| 1256 headers.SetHeader("Transfer-Encoding", "chunked"); | |
| 1257 | |
| 1258 HttpResponseInfo response; | |
| 1259 TestCompletionCallback callback; | |
| 1260 ASSERT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers, | |
| 1261 &response, callback.callback())); | |
| 1262 | |
| 1263 base::RunLoop().RunUntilIdle(); | |
| 1264 upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); | |
| 1265 | |
| 1266 base::RunLoop().RunUntilIdle(); | |
| 1267 // This write should fail. | |
| 1268 upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); | |
| 1269 ASSERT_EQ(ERR_FAILED, callback.WaitForResult()); | |
| 1270 | |
| 1271 EXPECT_EQ(WritesSize(writes, arraysize(writes)), parser.sent_bytes()); | |
| 1272 } | |
| 1273 | |
| 1008 // Test that an HttpStreamParser can be read from after it's received headers | 1274 // Test that an HttpStreamParser can be read from after it's received headers |
| 1009 // and data structures owned by its owner have been deleted. This happens | 1275 // and data structures owned by its owner have been deleted. This happens |
| 1010 // when a ResponseBodyDrainer is used. | 1276 // when a ResponseBodyDrainer is used. |
| 1011 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { | 1277 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { |
| 1012 MockWrite writes[] = { | 1278 MockWrite writes[] = { |
| 1013 MockWrite(SYNCHRONOUS, 0, | 1279 MockWrite(SYNCHRONOUS, 0, |
| 1014 "GET /foo.html HTTP/1.1\r\n\r\n"), | 1280 "GET /foo.html HTTP/1.1\r\n\r\n"), |
| 1015 }; | 1281 }; |
| 1016 | 1282 |
| 1017 const int kBodySize = 1; | 1283 const int kBodySize = 1; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1049 response_info.reset(); | 1315 response_info.reset(); |
| 1050 | 1316 |
| 1051 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); | 1317 scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); |
| 1052 ASSERT_EQ(kBodySize, parser.ReadResponseBody( | 1318 ASSERT_EQ(kBodySize, parser.ReadResponseBody( |
| 1053 body_buffer.get(), kBodySize, callback.callback())); | 1319 body_buffer.get(), kBodySize, callback.callback())); |
| 1054 } | 1320 } |
| 1055 | 1321 |
| 1056 } // namespace | 1322 } // namespace |
| 1057 | 1323 |
| 1058 } // namespace net | 1324 } // namespace net |
| OLD | NEW |