Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: net/quic/quic_http_stream_test.cc

Issue 1692253004: QUIC - chromium server push support. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review feedback round 2. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_http_stream.cc ('k') | net/quic/quic_stream_factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/quic/quic_http_stream.h" 5 #include "net/quic/quic_http_stream.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 IoMode mode; 132 IoMode mode;
133 QuicEncryptedPacket* packet; 133 QuicEncryptedPacket* packet;
134 int rv; 134 int rv;
135 }; 135 };
136 136
137 QuicHttpStreamTest() 137 QuicHttpStreamTest()
138 : net_log_(BoundNetLog()), 138 : net_log_(BoundNetLog()),
139 use_closing_stream_(false), 139 use_closing_stream_(false),
140 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()), 140 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
141 read_buffer_(new IOBufferWithSize(4096)), 141 read_buffer_(new IOBufferWithSize(4096)),
142 promise_id_(kServerDataStreamId1),
143 stream_id_(kClientDataStreamId1),
142 connection_id_(2), 144 connection_id_(2),
143 stream_id_(kClientDataStreamId1),
144 maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName), 145 maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName),
145 random_generator_(0) { 146 random_generator_(0),
147 response_offset_(0) {
146 IPAddress ip(192, 0, 2, 33); 148 IPAddress ip(192, 0, 2, 33);
147 peer_addr_ = IPEndPoint(ip, 443); 149 peer_addr_ = IPEndPoint(ip, 443);
148 self_addr_ = IPEndPoint(ip, 8435); 150 self_addr_ = IPEndPoint(ip, 8435);
149 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); 151 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
150 } 152 }
151 153
152 ~QuicHttpStreamTest() { 154 ~QuicHttpStreamTest() {
153 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR); 155 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR);
154 for (size_t i = 0; i < writes_.size(); i++) { 156 for (size_t i = 0; i < writes_.size(); i++) {
155 delete writes_[i].packet; 157 delete writes_[i].packet;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_, 242 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
241 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_, 243 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_,
242 base::ThreadTaskRunnerHandle::Get().get(), 244 base::ThreadTaskRunnerHandle::Get().get(),
243 /*socket_performance_watcher=*/nullptr, nullptr)); 245 /*socket_performance_watcher=*/nullptr, nullptr));
244 session_->Initialize(); 246 session_->Initialize();
245 session_->GetCryptoStream()->CryptoConnect(); 247 session_->GetCryptoStream()->CryptoConnect();
246 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed()); 248 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
247 stream_.reset(use_closing_stream_ 249 stream_.reset(use_closing_stream_
248 ? new AutoClosingStream(session_->GetWeakPtr()) 250 ? new AutoClosingStream(session_->GetWeakPtr())
249 : new QuicHttpStream(session_->GetWeakPtr())); 251 : new QuicHttpStream(session_->GetWeakPtr()));
252
253 promised_stream_.reset(use_closing_stream_
254 ? new AutoClosingStream(session_->GetWeakPtr())
255 : new QuicHttpStream(session_->GetWeakPtr()));
256
257 push_promise_[":path"] = "/bar";
258 push_promise_[":authority"] = "www.example.org";
259 push_promise_[":version"] = "HTTP/1.1";
260 push_promise_[":method"] = "GET";
261 push_promise_[":scheme"] = "https";
262
263 promised_response_[":status"] = "200 OK";
264 promised_response_[":version"] = "HTTP/1.1";
265 promised_response_["content-type"] = "text/plain";
266
267 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
268
269 serialized_push_promise_ =
270 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
250 } 271 }
251 272
252 void SetRequest(const std::string& method, 273 void SetRequest(const std::string& method,
253 const std::string& path, 274 const std::string& path,
254 RequestPriority priority) { 275 RequestPriority priority) {
255 request_headers_ = maker_.GetRequestHeaders(method, "http", path); 276 request_headers_ = maker_.GetRequestHeaders(method, "http", path);
256 } 277 }
257 278
258 void SetResponse(const std::string& status, const std::string& body) { 279 void SetResponse(const std::string& status, const std::string& body) {
259 response_headers_ = maker_.GetResponseHeaders(status); 280 response_headers_ = maker_.GetResponseHeaders(status);
260 response_data_ = body; 281 response_data_ = body;
261 } 282 }
262 283
284 scoped_ptr<QuicEncryptedPacket> InnerConstructDataPacket(
285 QuicPacketNumber packet_number,
286 QuicStreamId stream_id,
287 bool should_include_version,
288 bool fin,
289 QuicStreamOffset offset,
290 base::StringPiece data) {
291 return maker_.MakeDataPacket(packet_number, stream_id,
292 should_include_version, fin, offset, data);
293 }
294
263 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket( 295 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
264 QuicPacketNumber packet_number, 296 QuicPacketNumber packet_number,
265 bool should_include_version, 297 bool should_include_version,
266 bool fin, 298 bool fin,
267 QuicStreamOffset offset, 299 QuicStreamOffset offset,
268 base::StringPiece data) { 300 base::StringPiece data) {
269 return maker_.MakeDataPacket(packet_number, stream_id_, 301 return InnerConstructDataPacket(packet_number, stream_id_,
270 should_include_version, fin, offset, data); 302 should_include_version, fin, offset, data);
303 }
304
305 scoped_ptr<QuicEncryptedPacket> InnerConstructRequestHeadersPacket(
306 QuicPacketNumber packet_number,
307 QuicStreamId stream_id,
308 bool should_include_version,
309 bool fin,
310 RequestPriority request_priority,
311 size_t* spdy_headers_frame_length) {
312 SpdyPriority priority =
313 ConvertRequestPriorityToQuicPriority(request_priority);
314 return maker_.MakeRequestHeadersPacket(
315 packet_number, stream_id, should_include_version, fin, priority,
316 request_headers_, spdy_headers_frame_length);
271 } 317 }
272 318
273 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket( 319 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
274 QuicPacketNumber packet_number, 320 QuicPacketNumber packet_number,
275 bool fin, 321 bool fin,
276 RequestPriority request_priority, 322 RequestPriority request_priority,
277 size_t* spdy_headers_frame_length) { 323 size_t* spdy_headers_frame_length) {
278 SpdyPriority priority = 324 return InnerConstructRequestHeadersPacket(
279 ConvertRequestPriorityToQuicPriority(request_priority); 325 packet_number, stream_id_, kIncludeVersion, fin, request_priority,
280 return maker_.MakeRequestHeadersPacket( 326 spdy_headers_frame_length);
281 packet_number, stream_id_, kIncludeVersion, fin, priority, 327 }
282 request_headers_, spdy_headers_frame_length); 328
329 scoped_ptr<QuicEncryptedPacket> InnerConstructResponseHeadersPacket(
330 QuicPacketNumber packet_number,
331 QuicStreamId stream_id,
332 bool fin,
333 size_t* spdy_headers_frame_length) {
334 return maker_.MakeResponseHeadersPacket(
335 packet_number, stream_id, !kIncludeVersion, fin, response_headers_,
336 spdy_headers_frame_length, &response_offset_);
283 } 337 }
284 338
285 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket( 339 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
286 QuicPacketNumber packet_number, 340 QuicPacketNumber packet_number,
287 bool fin, 341 bool fin,
288 size_t* spdy_headers_frame_length) { 342 size_t* spdy_headers_frame_length) {
289 return maker_.MakeResponseHeadersPacket( 343 return InnerConstructResponseHeadersPacket(packet_number, stream_id_, fin,
290 packet_number, stream_id_, !kIncludeVersion, fin, response_headers_, 344 spdy_headers_frame_length);
291 spdy_headers_frame_length);
292 } 345 }
293 346
294 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket( 347 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
295 QuicPacketNumber packet_number) { 348 QuicPacketNumber packet_number) {
296 return maker_.MakeRstPacket( 349 return maker_.MakeRstPacket(
297 packet_number, true, stream_id_, 350 packet_number, true, stream_id_,
298 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam())); 351 AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
299 } 352 }
300 353
301 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket( 354 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket(
302 QuicPacketNumber packet_number) { 355 QuicPacketNumber packet_number) {
303 return maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_, 356 return maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
304 QUIC_STREAM_CANCELLED); 357 QUIC_STREAM_CANCELLED);
305 } 358 }
306 359
360 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamVaryMismatchPacket(
361 QuicPacketNumber packet_number) {
362 return maker_.MakeRstPacket(packet_number, !kIncludeVersion, promise_id_,
363 QUIC_PROMISE_VARY_MISMATCH);
364 }
365
307 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket( 366 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
308 QuicPacketNumber packet_number) { 367 QuicPacketNumber packet_number) {
309 return maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion, 368 return maker_.MakeAckAndRstPacket(packet_number, !kIncludeVersion,
310 stream_id_, QUIC_STREAM_CANCELLED, 2, 1, 369 stream_id_, QUIC_STREAM_CANCELLED, 2, 1,
311 !kIncludeCongestionFeedback); 370 !kIncludeCongestionFeedback);
312 } 371 }
313 372
314 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket( 373 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
315 QuicPacketNumber packet_number, 374 QuicPacketNumber packet_number,
316 QuicPacketNumber largest_received, 375 QuicPacketNumber largest_received,
317 QuicPacketNumber least_unacked) { 376 QuicPacketNumber least_unacked) {
318 return maker_.MakeAckPacket(packet_number, largest_received, least_unacked, 377 return maker_.MakeAckPacket(packet_number, largest_received, least_unacked,
319 !kIncludeCongestionFeedback); 378 !kIncludeCongestionFeedback);
320 } 379 }
321 380
381 void ReceivePromise(QuicStreamId id) {
382 QuicChromiumClientStream* stream =
383 QuicHttpStreamPeer::GetQuicChromiumClientStream(stream_.get());
384 stream->OnStreamHeaders(serialized_push_promise_);
385
386 stream->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
387 }
388
322 BoundNetLog net_log_; 389 BoundNetLog net_log_;
323 bool use_closing_stream_; 390 bool use_closing_stream_;
324 MockSendAlgorithm* send_algorithm_; 391 MockSendAlgorithm* send_algorithm_;
325 scoped_refptr<TestTaskRunner> runner_; 392 scoped_refptr<TestTaskRunner> runner_;
326 scoped_ptr<MockWrite[]> mock_writes_; 393 scoped_ptr<MockWrite[]> mock_writes_;
327 MockClock clock_; 394 MockClock clock_;
328 TestQuicConnection* connection_; 395 TestQuicConnection* connection_;
329 scoped_ptr<QuicChromiumConnectionHelper> helper_; 396 scoped_ptr<QuicChromiumConnectionHelper> helper_;
330 testing::StrictMock<MockConnectionVisitor> visitor_; 397 testing::StrictMock<MockConnectionVisitor> visitor_;
331 scoped_ptr<QuicHttpStream> stream_; 398 scoped_ptr<QuicHttpStream> stream_;
332 TransportSecurityState transport_security_state_; 399 TransportSecurityState transport_security_state_;
333 scoped_ptr<QuicChromiumClientSession> session_; 400 scoped_ptr<QuicChromiumClientSession> session_;
334 QuicCryptoClientConfig crypto_config_; 401 QuicCryptoClientConfig crypto_config_;
335 TestCompletionCallback callback_; 402 TestCompletionCallback callback_;
336 HttpRequestInfo request_; 403 HttpRequestInfo request_;
337 HttpRequestHeaders headers_; 404 HttpRequestHeaders headers_;
338 HttpResponseInfo response_; 405 HttpResponseInfo response_;
339 scoped_refptr<IOBufferWithSize> read_buffer_; 406 scoped_refptr<IOBufferWithSize> read_buffer_;
340 SpdyHeaderBlock request_headers_; 407 SpdyHeaderBlock request_headers_;
341 SpdyHeaderBlock response_headers_; 408 SpdyHeaderBlock response_headers_;
342 std::string request_data_; 409 std::string request_data_;
343 std::string response_data_; 410 std::string response_data_;
344 QuicClientPushPromiseIndex push_promise_index_; 411 QuicClientPushPromiseIndex push_promise_index_;
345 412
413 // For server push testing
414 scoped_ptr<QuicHttpStream> promised_stream_;
415 SpdyHeaderBlock push_promise_;
416 SpdyHeaderBlock promised_response_;
417 const QuicStreamId promise_id_;
418 string promise_url_;
419 string serialized_push_promise_;
420 const QuicStreamId stream_id_;
421
346 private: 422 private:
347 const QuicConnectionId connection_id_; 423 const QuicConnectionId connection_id_;
348 const QuicStreamId stream_id_;
349 QuicTestPacketMaker maker_; 424 QuicTestPacketMaker maker_;
350 IPEndPoint self_addr_; 425 IPEndPoint self_addr_;
351 IPEndPoint peer_addr_; 426 IPEndPoint peer_addr_;
352 MockRandom random_generator_; 427 MockRandom random_generator_;
353 ProofVerifyDetailsChromium verify_details_; 428 ProofVerifyDetailsChromium verify_details_;
354 MockCryptoClientStreamFactory crypto_client_stream_factory_; 429 MockCryptoClientStreamFactory crypto_client_stream_factory_;
355 scoped_ptr<StaticSocketDataProvider> socket_data_; 430 scoped_ptr<StaticSocketDataProvider> socket_data_;
356 std::vector<PacketToWrite> writes_; 431 std::vector<PacketToWrite> writes_;
432 QuicStreamOffset response_offset_;
357 }; 433 };
358 434
359 INSTANTIATE_TEST_CASE_P(Version, 435 INSTANTIATE_TEST_CASE_P(Version,
360 QuicHttpStreamTest, 436 QuicHttpStreamTest,
361 ::testing::ValuesIn(QuicSupportedVersions())); 437 ::testing::ValuesIn(QuicSupportedVersions()));
362 438
363 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) { 439 TEST_P(QuicHttpStreamTest, RenewStreamForAuth) {
364 Initialize(); 440 Initialize();
365 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth()); 441 EXPECT_EQ(nullptr, stream_->RenewStreamForAuth());
366 } 442 }
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 request_.upload_data_stream = &upload_data_stream; 1098 request_.upload_data_stream = &upload_data_stream;
1023 ASSERT_EQ(OK, request_.upload_data_stream->Init( 1099 ASSERT_EQ(OK, request_.upload_data_stream->Init(
1024 TestCompletionCallback().callback())); 1100 TestCompletionCallback().callback()));
1025 1101
1026 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_, 1102 ASSERT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1027 callback_.callback())); 1103 callback_.callback()));
1028 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, 1104 ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
1029 stream_->SendRequest(headers_, &response_, callback_.callback())); 1105 stream_->SendRequest(headers_, &response_, callback_.callback()));
1030 } 1106 }
1031 1107
1108 TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
1109 SetRequest("GET", "/", DEFAULT_PRIORITY);
1110 Initialize();
1111
1112 // Initialize the first stream, for receiving the promise on.
1113 request_.method = "GET";
1114 request_.url = GURL("http://www.example.org/");
1115
1116 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1117 callback_.callback()));
1118
1119 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1120 // packet, but does it matter?
1121 ReceivePromise(promise_id_);
1122 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1123
1124 request_.url = GURL(promise_url_);
1125
1126 // Make the second stream that will exercise the first step of the
1127 // server push rendezvous mechanism.
1128 EXPECT_EQ(OK,
1129 promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1130 net_log_, callback_.callback()));
1131
1132 // Receive the promised response headers.
1133 response_headers_ = promised_response_;
1134 size_t spdy_response_headers_frame_length;
1135 ProcessPacket(InnerConstructResponseHeadersPacket(
1136 1, promise_id_, false, &spdy_response_headers_frame_length));
1137
1138 // Receive the promised response body.
1139 const char kResponseBody[] = "Hello world!";
1140 ProcessPacket(
1141 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1142
1143 // Now sending a matching request will have successful rendezvous
1144 // with the promised stream.
1145 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1146 callback_.callback()));
1147
1148 EXPECT_EQ(
1149 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1150 ->id(),
1151 promise_id_);
1152
1153 // The headers will be immediately available.
1154 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1155
1156 // As will be the body.
1157 EXPECT_EQ(
1158 static_cast<int>(strlen(kResponseBody)),
1159 promised_stream_->ReadResponseBody(
1160 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1161 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1162 EXPECT_TRUE(AtEof());
1163
1164 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1165 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1166 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1167 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1168 strlen(kResponseBody)),
1169 promised_stream_->GetTotalReceivedBytes());
1170 }
1171
1172 TEST_P(QuicHttpStreamTest, ServerPushGetRequestSlowResponse) {
1173 SetRequest("GET", "/", DEFAULT_PRIORITY);
1174 Initialize();
1175
1176 // Initialize the first stream, for receiving the promise on.
1177 request_.method = "GET";
1178 request_.url = GURL("http://www.example.org/");
1179
1180 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1181 callback_.callback()));
1182
1183 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1184 // packet, but does it matter?
1185 ReceivePromise(promise_id_);
1186 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1187
1188 request_.url = GURL(promise_url_);
1189
1190 // Make the second stream that will exercise the first step of the
1191 // server push rendezvous mechanism.
1192 EXPECT_EQ(OK,
1193 promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1194 net_log_, callback_.callback()));
1195
1196 // Now sending a matching request will rendezvous with the promised
1197 // stream, but pending secondary validation.
1198 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1199 headers_, &response_, callback_.callback()));
1200
1201 // Receive the promised response headers.
1202 response_headers_ = promised_response_;
1203 size_t spdy_response_headers_frame_length;
1204 ProcessPacket(InnerConstructResponseHeadersPacket(
1205 1, promise_id_, false, &spdy_response_headers_frame_length));
1206
1207 // Receive the promised response body.
1208 const char kResponseBody[] = "Hello world!";
1209 ProcessPacket(
1210 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1211
1212 base::MessageLoop::current()->RunUntilIdle();
1213
1214 // Rendezvous should have succeeded now, so the promised stream
1215 // should point at our push stream, and we should be able read
1216 // headers and data from it.
1217 EXPECT_EQ(OK, callback_.WaitForResult());
1218
1219 EXPECT_EQ(
1220 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1221 ->id(),
1222 promise_id_);
1223
1224 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1225
1226 EXPECT_EQ(
1227 static_cast<int>(strlen(kResponseBody)),
1228 promised_stream_->ReadResponseBody(
1229 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1230
1231 // Callback should return
1232 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1233 EXPECT_TRUE(AtEof());
1234
1235 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1236 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1237 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1238 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1239 strlen(kResponseBody)),
1240 promised_stream_->GetTotalReceivedBytes());
1241 }
1242
1243 TEST_P(QuicHttpStreamTest, ServerPushCrossOriginOK) {
1244 SetRequest("GET", "/", DEFAULT_PRIORITY);
1245 Initialize();
1246
1247 // Initialize the first stream, for receiving the promise on.
1248 request_.method = "GET";
1249 request_.url = GURL("http://www.example.org/");
1250
1251 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1252 callback_.callback()));
1253
1254 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1255 // packet, but does it matter?
1256
1257 push_promise_[":authority"] = "mail.example.org";
1258 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1259 serialized_push_promise_ =
1260 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1261
1262 ReceivePromise(promise_id_);
1263 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1264
1265 request_.url = GURL(promise_url_);
1266
1267 // Make the second stream that will exercise the first step of the
1268 // server push rendezvous mechanism.
1269 EXPECT_EQ(OK,
1270 promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1271 net_log_, callback_.callback()));
1272
1273 // Receive the promised response headers.
1274 response_headers_ = promised_response_;
1275 size_t spdy_response_headers_frame_length;
1276 ProcessPacket(InnerConstructResponseHeadersPacket(
1277 1, promise_id_, false, &spdy_response_headers_frame_length));
1278
1279 // Receive the promised response body.
1280 const char kResponseBody[] = "Hello world!";
1281 ProcessPacket(
1282 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1283
1284 // Now sending a matching request will have successful rendezvous
1285 // with the promised stream.
1286 EXPECT_EQ(OK, promised_stream_->SendRequest(headers_, &response_,
1287 callback_.callback()));
1288
1289 EXPECT_EQ(
1290 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1291 ->id(),
1292 promise_id_);
1293
1294 // The headers will be immediately available.
1295 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1296
1297 // As will be the body.
1298 EXPECT_EQ(
1299 static_cast<int>(strlen(kResponseBody)),
1300 promised_stream_->ReadResponseBody(
1301 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1302 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1303 EXPECT_TRUE(AtEof());
1304
1305 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1306 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1307 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1308 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1309 strlen(kResponseBody)),
1310 promised_stream_->GetTotalReceivedBytes());
1311 }
1312
1313 TEST_P(QuicHttpStreamTest, ServerPushCrossOriginFail) {
1314 SetRequest("GET", "/", DEFAULT_PRIORITY);
1315 Initialize();
1316
1317 // Initialize the first stream, for receiving the promise on.
1318 request_.method = "GET";
1319 request_.url = GURL("http://www.example.org/");
1320
1321 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1322 callback_.callback()));
1323
1324 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1325 // packet, but does it matter?
1326 push_promise_[":authority"] = "www.notexample.org";
1327 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
1328 serialized_push_promise_ =
1329 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1330
1331 ReceivePromise(promise_id_);
1332 // The promise will have been rejected because the cert doesn't
1333 // match.
1334 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1335 }
1336
1337 TEST_P(QuicHttpStreamTest, ServerPushVaryCheckOK) {
1338 SetRequest("GET", "/", DEFAULT_PRIORITY);
1339 Initialize();
1340
1341 // Initialize the first stream, for receiving the promise on.
1342 request_.method = "GET";
1343 request_.url = GURL("http://www.example.org/");
1344
1345 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1346 callback_.callback()));
1347
1348 push_promise_["accept-encoding"] = "gzip";
1349 serialized_push_promise_ =
1350 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1351
1352 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1353 // packet, but does it matter?
1354 ReceivePromise(promise_id_);
1355 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1356
1357 request_.url = GURL(promise_url_);
1358
1359 // Make the second stream that will exercise the first step of the
1360 // server push rendezvous mechanism.
1361 EXPECT_EQ(OK,
1362 promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1363 net_log_, callback_.callback()));
1364
1365 headers_.SetHeader("accept-encoding", "gzip");
1366
1367 // Now sending a matching request will rendezvous with the promised
1368 // stream, but pending secondary validation.
1369 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1370 headers_, &response_, callback_.callback()));
1371
1372 // Receive the promised response headers.
1373 promised_response_["vary"] = "accept-encoding";
1374 response_headers_ = promised_response_;
1375 size_t spdy_response_headers_frame_length;
1376 ProcessPacket(InnerConstructResponseHeadersPacket(
1377 1, promise_id_, false, &spdy_response_headers_frame_length));
1378
1379 // Receive the promised response body.
1380 const char kResponseBody[] = "Hello world!";
1381 ProcessPacket(
1382 InnerConstructDataPacket(2, promise_id_, false, kFin, 0, kResponseBody));
1383
1384 base::MessageLoop::current()->RunUntilIdle();
1385
1386 // Rendezvous should have succeeded now, so the promised stream
1387 // should point at our push stream, and we should be able read
1388 // headers and data from it.
1389 EXPECT_EQ(OK, callback_.WaitForResult());
1390
1391 EXPECT_EQ(
1392 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1393 ->id(),
1394 promise_id_);
1395
1396 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1397
1398 EXPECT_EQ(
1399 static_cast<int>(strlen(kResponseBody)),
1400 promised_stream_->ReadResponseBody(
1401 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1402
1403 // Callback should return
1404 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1405 EXPECT_TRUE(AtEof());
1406
1407 EXPECT_EQ(0, stream_->GetTotalSentBytes());
1408 EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
1409 EXPECT_EQ(0, promised_stream_->GetTotalSentBytes());
1410 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length +
1411 strlen(kResponseBody)),
1412 promised_stream_->GetTotalReceivedBytes());
1413 }
1414
1415 TEST_P(QuicHttpStreamTest, ServerPushVaryCheckFail) {
1416 SetRequest("GET", "/", DEFAULT_PRIORITY);
1417 request_headers_[":scheme"] = "https";
1418 request_headers_[":path"] = "/bar";
1419 request_headers_["accept-encoding"] = "sdch";
1420
1421 size_t spdy_request_header_frame_length;
1422 AddWrite(ConstructRstStreamVaryMismatchPacket(1));
1423 AddWrite(InnerConstructRequestHeadersPacket(
1424 2, stream_id_ + 2, !kIncludeVersion, kFin, DEFAULT_PRIORITY,
1425 &spdy_request_header_frame_length));
1426 AddWrite(ConstructAckPacket(3, 3, 1));
1427 AddWrite(ConstructRstStreamCancelledPacket(4));
1428 Initialize();
1429
1430 // Initialize the first stream, for receiving the promise on.
1431 request_.method = "GET";
1432 request_.url = GURL("http://www.example.org/");
1433
1434 EXPECT_EQ(OK, stream_->InitializeStream(&request_, DEFAULT_PRIORITY, net_log_,
1435 callback_.callback()));
1436
1437 push_promise_["accept-encoding"] = "gzip";
1438 serialized_push_promise_ =
1439 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
1440
1441 // TODO(ckrasic) - could do this via constructing a PUSH_PROMISE
1442 // packet, but does it matter?
1443 ReceivePromise(promise_id_);
1444 EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
1445
1446 request_.url = GURL(promise_url_);
1447
1448 // Make the second stream that will exercise the first step of the
1449 // server push rendezvous mechanism.
1450 EXPECT_EQ(OK,
1451 promised_stream_->InitializeStream(&request_, DEFAULT_PRIORITY,
1452 net_log_, callback_.callback()));
1453
1454 headers_.SetHeader("accept-encoding", "sdch");
1455
1456 // Now sending a matching request will rendezvous with the promised
1457 // stream, but pending secondary validation.
1458 EXPECT_EQ(ERR_IO_PENDING, promised_stream_->SendRequest(
1459 headers_, &response_, callback_.callback()));
1460
1461 // Receive the promised response headers.
1462 promised_response_["vary"] = "accept-encoding";
1463 response_headers_ = promised_response_;
1464 size_t spdy_response_headers_frame_length;
1465 ProcessPacket(InnerConstructResponseHeadersPacket(
1466 1, promise_id_, false, &spdy_response_headers_frame_length));
1467
1468 base::MessageLoop::current()->RunUntilIdle();
1469
1470 // Rendezvous should have failed due to vary mismatch, so the
1471 // promised stream should have been aborted, and instead we have a
1472 // new, regular client initiated stream.
1473 EXPECT_EQ(OK, callback_.WaitForResult());
1474
1475 // Not a server-initiated stream.
1476 EXPECT_NE(
1477 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1478 ->id(),
1479 promise_id_);
1480
1481 // Instead, a new client-initiated stream.
1482 EXPECT_EQ(
1483 QuicHttpStreamPeer::GetQuicChromiumClientStream(promised_stream_.get())
1484 ->id(),
1485 stream_id_ + 2);
1486
1487 // After rendezvous failure, the push stream has been cancelled.
1488 EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr);
1489
1490 // The rest of the test verifies that the retried as
1491 // client-initiated version of |promised_stream_| works as intended.
1492
1493 // Ack the request.
1494 ProcessPacket(ConstructAckPacket(2, 0, 0));
1495
1496 SetResponse("404 Not Found", std::string());
1497 size_t spdy_response_header_frame_length;
1498 ProcessPacket(InnerConstructResponseHeadersPacket(
1499 3, stream_id_ + 2, kFin, &spdy_response_header_frame_length));
1500
1501 base::MessageLoop::current()->RunUntilIdle();
1502
1503 EXPECT_EQ(OK, promised_stream_->ReadResponseHeaders(callback_.callback()));
1504 ASSERT_TRUE(response_.headers.get());
1505 EXPECT_EQ(404, response_.headers->response_code());
1506 EXPECT_TRUE(response_.headers->HasHeaderValue("Content-Type", "text/plain"));
1507 EXPECT_FALSE(response_.response_time.is_null());
1508 EXPECT_FALSE(response_.request_time.is_null());
1509
1510 // There is no body, so this should return immediately.
1511 EXPECT_EQ(
1512 0, promised_stream_->ReadResponseBody(
1513 read_buffer_.get(), read_buffer_->size(), callback_.callback()));
1514 EXPECT_TRUE(promised_stream_->IsResponseBodyComplete());
1515
1516 stream_->Close(true);
1517
1518 EXPECT_TRUE(AtEof());
1519
1520 // QuicHttpStream::GetTotalSent/ReceivedBytes currently only includes the
1521 // headers and payload.
1522 EXPECT_EQ(static_cast<int64_t>(spdy_request_header_frame_length),
1523 promised_stream_->GetTotalSentBytes());
1524 EXPECT_EQ(static_cast<int64_t>(spdy_response_header_frame_length),
1525 promised_stream_->GetTotalReceivedBytes());
1526 }
1527
1032 } // namespace test 1528 } // namespace test
1033 } // namespace net 1529 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_http_stream.cc ('k') | net/quic/quic_stream_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698