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 |