| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/core/quic_client_promised_info.h" | 5 #include "net/quic/core/quic_client_promised_info.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "net/quic/core/spdy_utils.h" | 10 #include "net/quic/core/spdy_utils.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 &alarm_factory_, | 57 &alarm_factory_, |
| 58 Perspective::IS_CLIENT)), | 58 Perspective::IS_CLIENT)), |
| 59 session_(connection_, &push_promise_index_), | 59 session_(connection_, &push_promise_index_), |
| 60 body_("hello world"), | 60 body_("hello world"), |
| 61 promise_id_(kServerDataStreamId1) { | 61 promise_id_(kServerDataStreamId1) { |
| 62 session_.Initialize(); | 62 session_.Initialize(); |
| 63 | 63 |
| 64 headers_[":status"] = "200"; | 64 headers_[":status"] = "200"; |
| 65 headers_["content-length"] = "11"; | 65 headers_["content-length"] = "11"; |
| 66 | 66 |
| 67 headers_string_ = SpdyUtils::SerializeUncompressedHeaders(headers_); | |
| 68 | |
| 69 stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); | 67 stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); |
| 70 stream_visitor_.reset(new StreamVisitor()); | 68 stream_visitor_.reset(new StreamVisitor()); |
| 71 stream_->set_visitor(stream_visitor_.get()); | 69 stream_->set_visitor(stream_visitor_.get()); |
| 72 | 70 |
| 73 push_promise_[":path"] = "/bar"; | 71 push_promise_[":path"] = "/bar"; |
| 74 push_promise_[":authority"] = "www.google.com"; | 72 push_promise_[":authority"] = "www.google.com"; |
| 75 push_promise_[":version"] = "HTTP/1.1"; | 73 push_promise_[":version"] = "HTTP/1.1"; |
| 76 push_promise_[":method"] = "GET"; | 74 push_promise_[":method"] = "GET"; |
| 77 push_promise_[":scheme"] = "https"; | 75 push_promise_[":scheme"] = "https"; |
| 78 | 76 |
| 79 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_); | 77 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_); |
| 80 serialized_push_promise_ = | |
| 81 SpdyUtils::SerializeUncompressedHeaders(push_promise_); | |
| 82 | 78 |
| 83 client_request_ = push_promise_.Clone(); | 79 client_request_ = push_promise_.Clone(); |
| 84 } | 80 } |
| 85 | 81 |
| 86 class StreamVisitor : public QuicSpdyClientStream::Visitor { | 82 class StreamVisitor : public QuicSpdyClientStream::Visitor { |
| 87 void OnClose(QuicSpdyStream* stream) override { | 83 void OnClose(QuicSpdyStream* stream) override { |
| 88 DVLOG(1) << "stream " << stream->id(); | 84 DVLOG(1) << "stream " << stream->id(); |
| 89 } | 85 } |
| 90 }; | 86 }; |
| 91 | 87 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 111 QuicSpdyStream* rendezvous_stream() { return rendezvous_stream_; } | 107 QuicSpdyStream* rendezvous_stream() { return rendezvous_stream_; } |
| 112 bool rendezvous_fired() { return rendezvous_fired_; } | 108 bool rendezvous_fired() { return rendezvous_fired_; } |
| 113 | 109 |
| 114 private: | 110 private: |
| 115 bool match_; | 111 bool match_; |
| 116 bool rendezvous_fired_; | 112 bool rendezvous_fired_; |
| 117 QuicSpdyStream* rendezvous_stream_; | 113 QuicSpdyStream* rendezvous_stream_; |
| 118 }; | 114 }; |
| 119 | 115 |
| 120 void ReceivePromise(QuicStreamId id) { | 116 void ReceivePromise(QuicStreamId id) { |
| 121 stream_->OnStreamHeaders(serialized_push_promise_); | 117 auto headers = AsHeaderList(push_promise_); |
| 122 | 118 stream_->OnPromiseHeaderList(id, headers.uncompressed_header_bytes(), |
| 123 stream_->OnPromiseHeadersComplete(id, serialized_push_promise_.size()); | 119 headers); |
| 124 } | 120 } |
| 125 | 121 |
| 126 MockQuicConnectionHelper helper_; | 122 MockQuicConnectionHelper helper_; |
| 127 MockAlarmFactory alarm_factory_; | 123 MockAlarmFactory alarm_factory_; |
| 128 StrictMock<MockQuicConnection>* connection_; | 124 StrictMock<MockQuicConnection>* connection_; |
| 129 QuicClientPushPromiseIndex push_promise_index_; | 125 QuicClientPushPromiseIndex push_promise_index_; |
| 130 | 126 |
| 131 MockQuicClientSession session_; | 127 MockQuicClientSession session_; |
| 132 std::unique_ptr<QuicSpdyClientStream> stream_; | 128 std::unique_ptr<QuicSpdyClientStream> stream_; |
| 133 std::unique_ptr<StreamVisitor> stream_visitor_; | 129 std::unique_ptr<StreamVisitor> stream_visitor_; |
| 134 std::unique_ptr<QuicSpdyClientStream> promised_stream_; | 130 std::unique_ptr<QuicSpdyClientStream> promised_stream_; |
| 135 SpdyHeaderBlock headers_; | 131 SpdyHeaderBlock headers_; |
| 136 string headers_string_; | |
| 137 string body_; | 132 string body_; |
| 138 SpdyHeaderBlock push_promise_; | 133 SpdyHeaderBlock push_promise_; |
| 139 QuicStreamId promise_id_; | 134 QuicStreamId promise_id_; |
| 140 string promise_url_; | 135 string promise_url_; |
| 141 string serialized_push_promise_; | |
| 142 SpdyHeaderBlock client_request_; | 136 SpdyHeaderBlock client_request_; |
| 143 }; | 137 }; |
| 144 | 138 |
| 145 TEST_F(QuicClientPromisedInfoTest, PushPromise) { | 139 TEST_F(QuicClientPromisedInfoTest, PushPromise) { |
| 146 ReceivePromise(promise_id_); | 140 ReceivePromise(promise_id_); |
| 147 | 141 |
| 148 // Verify that the promise is in the unclaimed streams map. | 142 // Verify that the promise is in the unclaimed streams map. |
| 149 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr); | 143 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr); |
| 150 } | 144 } |
| 151 | 145 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 167 alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised)); | 161 alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised)); |
| 168 | 162 |
| 169 // Verify that the promise is gone after the alarm fires. | 163 // Verify that the promise is gone after the alarm fires. |
| 170 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 164 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 171 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); | 165 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); |
| 172 } | 166 } |
| 173 | 167 |
| 174 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidMethod) { | 168 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidMethod) { |
| 175 // Promise with an unsafe method | 169 // Promise with an unsafe method |
| 176 push_promise_[":method"] = "PUT"; | 170 push_promise_[":method"] = "PUT"; |
| 177 serialized_push_promise_ = | |
| 178 SpdyUtils::SerializeUncompressedHeaders(push_promise_); | |
| 179 | 171 |
| 180 EXPECT_CALL(*connection_, | 172 EXPECT_CALL(*connection_, |
| 181 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0)); | 173 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0)); |
| 182 ReceivePromise(promise_id_); | 174 ReceivePromise(promise_id_); |
| 183 | 175 |
| 184 // Verify that the promise headers were ignored | 176 // Verify that the promise headers were ignored |
| 185 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 177 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 186 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); | 178 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); |
| 187 } | 179 } |
| 188 | 180 |
| 189 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) { | 181 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) { |
| 190 // Remove required header field to make URL invalid | 182 // Remove required header field to make URL invalid |
| 191 push_promise_.erase(":authority"); | 183 push_promise_.erase(":authority"); |
| 192 serialized_push_promise_ = | |
| 193 SpdyUtils::SerializeUncompressedHeaders(push_promise_); | |
| 194 | 184 |
| 195 EXPECT_CALL(*connection_, | 185 EXPECT_CALL(*connection_, |
| 196 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_URL, 0)); | 186 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_URL, 0)); |
| 197 ReceivePromise(promise_id_); | 187 ReceivePromise(promise_id_); |
| 198 | 188 |
| 199 // Verify that the promise headers were ignored | 189 // Verify that the promise headers were ignored |
| 200 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 190 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 201 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); | 191 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr); |
| 202 } | 192 } |
| 203 | 193 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 216 TEST_F(QuicClientPromisedInfoTest, PushPromiseMismatch) { | 206 TEST_F(QuicClientPromisedInfoTest, PushPromiseMismatch) { |
| 217 ReceivePromise(promise_id_); | 207 ReceivePromise(promise_id_); |
| 218 | 208 |
| 219 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); | 209 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); |
| 220 ASSERT_NE(promised, nullptr); | 210 ASSERT_NE(promised, nullptr); |
| 221 | 211 |
| 222 // Need to send the promised response headers and initiate the | 212 // Need to send the promised response headers and initiate the |
| 223 // rendezvous for secondary validation to proceed. | 213 // rendezvous for secondary validation to proceed. |
| 224 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( | 214 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( |
| 225 session_.GetOrCreateStream(promise_id_)); | 215 session_.GetOrCreateStream(promise_id_)); |
| 226 promise_stream->OnStreamHeaders(headers_string_); | 216 auto headers = AsHeaderList(headers_); |
| 227 promise_stream->OnStreamHeadersComplete(false, headers_string_.size()); | 217 promise_stream->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 218 headers); |
| 228 | 219 |
| 229 PushPromiseDelegate delegate(/*match=*/false); | 220 PushPromiseDelegate delegate(/*match=*/false); |
| 230 EXPECT_CALL(*connection_, | 221 EXPECT_CALL(*connection_, |
| 231 SendRstStream(promise_id_, QUIC_PROMISE_VARY_MISMATCH, 0)); | 222 SendRstStream(promise_id_, QUIC_PROMISE_VARY_MISMATCH, 0)); |
| 232 EXPECT_CALL(session_, CloseStream(promise_id_)); | 223 EXPECT_CALL(session_, CloseStream(promise_id_)); |
| 233 | 224 |
| 234 promised->HandleClientRequest(client_request_, &delegate); | 225 promised->HandleClientRequest(client_request_, &delegate); |
| 235 } | 226 } |
| 236 | 227 |
| 237 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryWaits) { | 228 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryWaits) { |
| 238 ReceivePromise(promise_id_); | 229 ReceivePromise(promise_id_); |
| 239 | 230 |
| 240 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); | 231 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); |
| 241 ASSERT_NE(promised, nullptr); | 232 ASSERT_NE(promised, nullptr); |
| 242 | 233 |
| 243 // Now initiate rendezvous. | 234 // Now initiate rendezvous. |
| 244 PushPromiseDelegate delegate(/*match=*/true); | 235 PushPromiseDelegate delegate(/*match=*/true); |
| 245 promised->HandleClientRequest(client_request_, &delegate); | 236 promised->HandleClientRequest(client_request_, &delegate); |
| 246 | 237 |
| 247 // Promise is still there, waiting for response. | 238 // Promise is still there, waiting for response. |
| 248 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr); | 239 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr); |
| 249 | 240 |
| 250 // Send Response, should trigger promise validation and complete rendezvous | 241 // Send Response, should trigger promise validation and complete rendezvous |
| 251 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( | 242 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( |
| 252 session_.GetOrCreateStream(promise_id_)); | 243 session_.GetOrCreateStream(promise_id_)); |
| 253 ASSERT_NE(promise_stream, nullptr); | 244 ASSERT_NE(promise_stream, nullptr); |
| 254 promise_stream->OnStreamHeaders(headers_string_); | 245 auto headers = AsHeaderList(headers_); |
| 255 promise_stream->OnStreamHeadersComplete(false, headers_string_.size()); | 246 promise_stream->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 247 headers); |
| 256 | 248 |
| 257 // Promise is gone | 249 // Promise is gone |
| 258 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 250 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 259 } | 251 } |
| 260 | 252 |
| 261 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryNoWait) { | 253 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryNoWait) { |
| 262 ReceivePromise(promise_id_); | 254 ReceivePromise(promise_id_); |
| 263 | 255 |
| 264 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); | 256 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); |
| 265 ASSERT_NE(promised, nullptr); | 257 ASSERT_NE(promised, nullptr); |
| 266 | 258 |
| 267 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( | 259 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( |
| 268 session_.GetOrCreateStream(promise_id_)); | 260 session_.GetOrCreateStream(promise_id_)); |
| 269 ASSERT_NE(promise_stream, nullptr); | 261 ASSERT_NE(promise_stream, nullptr); |
| 270 | 262 |
| 271 // Send Response, should trigger promise validation and complete rendezvous | 263 // Send Response, should trigger promise validation and complete rendezvous |
| 272 promise_stream->OnStreamHeaders(headers_string_); | 264 auto headers = AsHeaderList(headers_); |
| 273 promise_stream->OnStreamHeadersComplete(false, headers_string_.size()); | 265 promise_stream->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 266 headers); |
| 274 | 267 |
| 275 // Now initiate rendezvous. | 268 // Now initiate rendezvous. |
| 276 PushPromiseDelegate delegate(/*match=*/true); | 269 PushPromiseDelegate delegate(/*match=*/true); |
| 277 promised->HandleClientRequest(client_request_, &delegate); | 270 promised->HandleClientRequest(client_request_, &delegate); |
| 278 | 271 |
| 279 // Promise is gone | 272 // Promise is gone |
| 280 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 273 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 281 // Have a push stream | 274 // Have a push stream |
| 282 EXPECT_TRUE(delegate.rendezvous_fired()); | 275 EXPECT_TRUE(delegate.rendezvous_fired()); |
| 283 | 276 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 314 ReceivePromise(promise_id_); | 307 ReceivePromise(promise_id_); |
| 315 | 308 |
| 316 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); | 309 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_); |
| 317 ASSERT_NE(promised, nullptr); | 310 ASSERT_NE(promised, nullptr); |
| 318 | 311 |
| 319 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( | 312 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>( |
| 320 session_.GetOrCreateStream(promise_id_)); | 313 session_.GetOrCreateStream(promise_id_)); |
| 321 ASSERT_NE(promise_stream, nullptr); | 314 ASSERT_NE(promise_stream, nullptr); |
| 322 | 315 |
| 323 // Send response, rendezvous will be able to finish synchronously. | 316 // Send response, rendezvous will be able to finish synchronously. |
| 324 promise_stream->OnStreamHeaders(headers_string_); | 317 auto headers = AsHeaderList(headers_); |
| 325 promise_stream->OnStreamHeadersComplete(false, headers_string_.size()); | 318 promise_stream->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 319 headers); |
| 326 | 320 |
| 327 EXPECT_CALL(session_, CloseStream(promise_id_)); | 321 EXPECT_CALL(session_, CloseStream(promise_id_)); |
| 328 EXPECT_CALL(*connection_, | 322 EXPECT_CALL(*connection_, |
| 329 SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0)); | 323 SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0)); |
| 330 session_.SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0); | 324 session_.SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0); |
| 331 | 325 |
| 332 // Now initiate rendezvous. | 326 // Now initiate rendezvous. |
| 333 PushPromiseDelegate delegate(/*match=*/true); | 327 PushPromiseDelegate delegate(/*match=*/true); |
| 334 EXPECT_EQ(promised->HandleClientRequest(client_request_, &delegate), | 328 EXPECT_EQ(promised->HandleClientRequest(client_request_, &delegate), |
| 335 QUIC_FAILURE); | 329 QUIC_FAILURE); |
| 336 | 330 |
| 337 // Got an indication of the stream failure, client should retry | 331 // Got an indication of the stream failure, client should retry |
| 338 // request. | 332 // request. |
| 339 EXPECT_FALSE(delegate.rendezvous_fired()); | 333 EXPECT_FALSE(delegate.rendezvous_fired()); |
| 340 EXPECT_EQ(delegate.rendezvous_stream(), nullptr); | 334 EXPECT_EQ(delegate.rendezvous_stream(), nullptr); |
| 341 | 335 |
| 342 // Promise is gone | 336 // Promise is gone |
| 343 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); | 337 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr); |
| 344 } | 338 } |
| 345 | 339 |
| 346 } // namespace | 340 } // namespace |
| 347 } // namespace test | 341 } // namespace test |
| 348 } // namespace net | 342 } // namespace net |
| OLD | NEW |