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

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

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 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_client_promised_info.cc ('k') | net/quic/quic_client_push_promise_index.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_client_promised_info.h"
6
7 #include <memory>
8
9 #include "base/macros.h"
10 #include "base/scoped_ptr.h"
11 #include "net/gfe2/balsa_headers.h"
12 #include "net/quic/quic_client.h"
13 #include "net/quic/quic_client_session.h"
14 #include "net/quic/quic_spdy_client_stream.h"
15 #include "net/quic/quic_utils.h"
16 #include "net/quic/spdy_balsa_utils.h"
17 #include "net/quic/spdy_utils.h"
18 #include "net/quic/test_tools/crypto_test_utils.h"
19 #include "net/quic/test_tools/quic_test_utils.h"
20 #include "net/util/ipaddress.h"
21 #include "testing/base/public/gunit.h"
22
23 using SpdyHeaderBlock;
24 using BalsaHeaders;
25 using testing::StrictMock;
26
27 namespace net {
28 namespace test {
29
30 class QuicClientPromisedInfoPeer {
31 public:
32 static QuicAlarm* GetAlarm(QuicClientPromisedInfo* promised_stream) {
33 return promised_stream->cleanup_alarm_.get();
34 }
35
36 private:
37 DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfoPeer);
38 };
39
40 namespace {
41
42 class MockQuicClientSession : public QuicClientSession {
43 public:
44 explicit MockQuicClientSession(QuicConnection* connection,
45 QuicClientPushPromiseIndex* push_promise_index)
46 : QuicClientSession(
47 DefaultQuicConfig(),
48 connection,
49 QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED),
50 &crypto_config_,
51 push_promise_index),
52 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()),
53 authorized_(true) {}
54 ~MockQuicClientSession() override {}
55
56 bool IsAuthorized(const string& authority) override { return authorized_; }
57
58 void set_authorized(bool authorized) { authorized_ = authorized; }
59
60 MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id));
61
62 private:
63 QuicCryptoClientConfig crypto_config_;
64
65 bool authorized_;
66
67 DISALLOW_COPY_AND_ASSIGN(MockQuicClientSession);
68 };
69
70 class QuicClientPromisedInfoTest : public ::testing::Test {
71 public:
72 class StreamVisitor;
73
74 QuicClientPromisedInfoTest()
75 : connection_(new StrictMock<MockQuicConnection>(&helper_,
76 &alarm_factory_,
77 Perspective::IS_CLIENT)),
78 session_(connection_, &push_promise_index_),
79 body_("hello world"),
80 promise_id_(gfe_quic::test::kServerDataStreamId1) {
81 FLAGS_quic_supports_push_promise = true;
82
83 session_.Initialize();
84
85 headers_.SetResponseFirstline("HTTP/1.1", 200, "Ok");
86 headers_.ReplaceOrAppendHeader("content-length", "11");
87 headers_string_ = SpdyBalsaUtils::SerializeResponseHeaders(headers_);
88
89 stream_.reset(new QuicSpdyClientStream(gfe_quic::test::kClientDataStreamId1,
90 &session_));
91 stream_visitor_.reset(new StreamVisitor());
92 stream_->set_visitor(stream_visitor_.get());
93
94 push_promise_[":path"] = "/bar";
95 push_promise_[":authority"] = "www.google.com";
96 push_promise_[":version"] = "HTTP/1.1";
97 push_promise_[":method"] = "GET";
98 push_promise_[":scheme"] = "https";
99
100 promise_url_ = SpdyUtils::GetUrlFromHeaderBlock(push_promise_);
101 serialized_push_promise_ =
102 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
103
104 client_request_ = push_promise_.Clone();
105 }
106
107 class StreamVisitor : public QuicSpdyClientStream::Visitor {
108 void OnClose(QuicSpdyStream* stream) override {
109 DVLOG(1) << "stream " << stream->id();
110 }
111 };
112
113 class PushPromiseDelegate : public QuicClientPushPromiseIndex::Delegate {
114 public:
115 explicit PushPromiseDelegate(bool match)
116 : match_(match),
117 rendezvous_fired_(false),
118 rendezvous_stream_(nullptr) {}
119
120 bool CheckVary(const SpdyHeaderBlock& client_request,
121 const SpdyHeaderBlock& promise_request,
122 const SpdyHeaderBlock& promise_response) override {
123 DVLOG(1) << "match " << match_;
124 return match_;
125 }
126
127 void OnRendezvousResult(QuicSpdyClientStream* stream) override {
128 rendezvous_fired_ = true;
129 rendezvous_stream_ = stream;
130 }
131
132 QuicSpdyClientStream* rendezvous_stream() { return rendezvous_stream_; }
133 bool rendezvous_fired() { return rendezvous_fired_; }
134
135 private:
136 bool match_;
137 bool rendezvous_fired_;
138 QuicSpdyClientStream* rendezvous_stream_;
139 };
140
141 void ReceivePromise(QuicStreamId id) {
142 stream_->OnStreamHeaders(serialized_push_promise_);
143
144 stream_->OnPromiseHeadersComplete(id, serialized_push_promise_.size());
145 }
146
147 MockQuicConnectionHelper helper_;
148 MockAlarmFactory alarm_factory_;
149 StrictMock<MockQuicConnection>* connection_;
150 QuicClientPushPromiseIndex push_promise_index_;
151
152 MockQuicClientSession session_;
153 std::unique_ptr<QuicSpdyClientStream> stream_;
154 std::unique_ptr<StreamVisitor> stream_visitor_;
155 std::unique_ptr<QuicSpdyClientStream> promised_stream_;
156 BalsaHeaders headers_;
157 string headers_string_;
158 string body_;
159 SpdyHeaderBlock push_promise_;
160 QuicStreamId promise_id_;
161 string promise_url_;
162 string serialized_push_promise_;
163 SpdyHeaderBlock client_request_;
164 };
165
166 TEST_F(QuicClientPromisedInfoTest, PushPromise) {
167 ReceivePromise(promise_id_);
168
169 // Verify that the promise is in the unclaimed streams map.
170 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
171 }
172
173 TEST_F(QuicClientPromisedInfoTest, PushPromiseCleanupAlarm) {
174 ReceivePromise(promise_id_);
175
176 // Verify that the promise is in the unclaimed streams map.
177 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
178 ASSERT_NE(promised, nullptr);
179
180 // Fire the alarm that will cancel the promised stream.
181 EXPECT_CALL(*connection_,
182 SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
183 alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
184
185 // Verify that the promise is gone after the alarm fires.
186 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
187 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
188 }
189
190 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidMethod) {
191 // Promise with an unsafe method
192 push_promise_[":method"] = "PUT";
193 serialized_push_promise_ =
194 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
195
196 EXPECT_CALL(*connection_,
197 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
198 ReceivePromise(promise_id_);
199
200 // Verify that the promise headers were ignored
201 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
202 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
203 }
204
205 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
206 // Remove required header field to make URL invalid
207 push_promise_.erase(":authority");
208 serialized_push_promise_ =
209 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
210
211 EXPECT_CALL(*connection_,
212 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_URL, 0));
213 ReceivePromise(promise_id_);
214
215 // Verify that the promise headers were ignored
216 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
217 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
218 }
219
220 TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
221 // Promise with an unsafe method
222 push_promise_[":method"] = "PUT";
223 serialized_push_promise_ =
224 SpdyUtils::SerializeUncompressedHeaders(push_promise_);
225
226 EXPECT_CALL(*connection_,
227 SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
228 ReceivePromise(promise_id_);
229
230 // Verify that the promise headers were ignored
231 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
232 EXPECT_EQ(session_.GetPromisedByUrl(promise_url_), nullptr);
233 }
234
235 TEST_F(QuicClientPromisedInfoTest, PushPromiseUnauthorizedUrl) {
236 session_.set_authorized(false);
237
238 EXPECT_CALL(*connection_,
239 SendRstStream(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL, 0));
240
241 ReceivePromise(promise_id_);
242
243 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
244 ASSERT_EQ(promised, nullptr);
245 }
246
247 TEST_F(QuicClientPromisedInfoTest, PushPromiseMismatch) {
248 ReceivePromise(promise_id_);
249
250 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
251 ASSERT_NE(promised, nullptr);
252
253 // Need to send the promised response headers and initiate the
254 // rendezvous for secondary validation to proceed.
255 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>(
256 session_.GetOrCreateStream(promise_id_));
257 promise_stream->OnStreamHeaders(headers_string_);
258 promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
259
260 PushPromiseDelegate delegate(/*match=*/false);
261 EXPECT_CALL(*connection_,
262 SendRstStream(promise_id_, QUIC_PROMISE_VARY_MISMATCH, 0));
263 EXPECT_CALL(session_, CloseStream(promise_id_));
264
265 promised->HandleClientRequest(client_request_, &delegate);
266 }
267
268 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryWaits) {
269 ReceivePromise(promise_id_);
270
271 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
272 ASSERT_NE(promised, nullptr);
273
274 // Now initiate rendezvous.
275 PushPromiseDelegate delegate(/*match=*/true);
276 promised->HandleClientRequest(std::move(client_request_), &delegate);
277
278 // Promise is still there, waiting for response.
279 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
280
281 // Send Response, should trigger promise validation and complete rendezvous
282 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>(
283 session_.GetOrCreateStream(promise_id_));
284 ASSERT_NE(promise_stream, nullptr);
285 promise_stream->OnStreamHeaders(headers_string_);
286 promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
287
288 // Promise is gone
289 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
290 }
291
292 TEST_F(QuicClientPromisedInfoTest, PushPromiseVaryNoWait) {
293 ReceivePromise(promise_id_);
294
295 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
296 ASSERT_NE(promised, nullptr);
297
298 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>(
299 session_.GetOrCreateStream(promise_id_));
300 ASSERT_NE(promise_stream, nullptr);
301
302 // Send Response, should trigger promise validation and complete rendezvous
303 promise_stream->OnStreamHeaders(headers_string_);
304 promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
305
306 // Now initiate rendezvous.
307 PushPromiseDelegate delegate(/*match=*/true);
308 promised->HandleClientRequest(std::move(client_request_), &delegate);
309
310 // Promise is gone
311 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
312 // Have a push stream
313 EXPECT_TRUE(delegate.rendezvous_fired());
314
315 EXPECT_NE(delegate.rendezvous_stream(), nullptr);
316 }
317
318 TEST_F(QuicClientPromisedInfoTest, PushPromiseWaitCancels) {
319 ReceivePromise(promise_id_);
320
321 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
322 ASSERT_NE(promised, nullptr);
323
324 // Now initiate rendezvous.
325 PushPromiseDelegate delegate(/*match=*/true);
326 promised->HandleClientRequest(std::move(client_request_), &delegate);
327
328 // Promise is still there, waiting for response.
329 EXPECT_NE(session_.GetPromisedById(promise_id_), nullptr);
330
331 // Create response stream, but no data yet.
332 session_.GetOrCreateStream(promise_id_);
333
334 // Fire the alarm that will cancel the promised stream.
335 EXPECT_CALL(session_, CloseStream(promise_id_));
336 EXPECT_CALL(*connection_,
337 SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
338 promised->Cancel();
339
340 // Promise is gone
341 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
342 }
343
344 TEST_F(QuicClientPromisedInfoTest, PushPromiseDataClosed) {
345 ReceivePromise(promise_id_);
346
347 QuicClientPromisedInfo* promised = session_.GetPromisedById(promise_id_);
348 ASSERT_NE(promised, nullptr);
349
350 QuicSpdyClientStream* promise_stream = static_cast<QuicSpdyClientStream*>(
351 session_.GetOrCreateStream(promise_id_));
352 ASSERT_NE(promise_stream, nullptr);
353
354 // Send response, rendezvous will be able to finish synchronously.
355 promise_stream->OnStreamHeaders(headers_string_);
356 promise_stream->OnStreamHeadersComplete(false, headers_string_.size());
357
358 EXPECT_CALL(session_, CloseStream(promise_id_));
359 EXPECT_CALL(*connection_,
360 SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0));
361 session_.SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0);
362
363 // Now initiate rendezvous.
364 PushPromiseDelegate delegate(/*match=*/true);
365 EXPECT_EQ(
366 promised->HandleClientRequest(std::move(client_request_), &delegate),
367 QUIC_FAILURE);
368
369 // Got an indication of the stream failure, client should retry
370 // request.
371 EXPECT_FALSE(delegate.rendezvous_fired());
372 EXPECT_EQ(delegate.rendezvous_stream(), nullptr);
373
374 // Promise is gone
375 EXPECT_EQ(session_.GetPromisedById(promise_id_), nullptr);
376 }
377
378 } // namespace
379 } // namespace test
380 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_client_promised_info.cc ('k') | net/quic/quic_client_push_promise_index.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698