OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 <memory> | |
6 #include <ostream> | |
7 #include <utility> | |
8 #include <vector> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 #include "base/memory/ptr_util.h" | |
12 #include "base/run_loop.h" | |
13 #include "base/stl_util.h" | |
14 #include "base/strings/string_number_conversions.h" | |
15 #include "net/base/elements_upload_data_stream.h" | |
16 #include "net/base/ip_address.h" | |
17 #include "net/base/test_completion_callback.h" | |
18 #include "net/base/upload_bytes_element_reader.h" | |
19 #include "net/base/upload_data_stream.h" | |
20 #include "net/cert/ct_policy_enforcer.h" | |
21 #include "net/cert/mock_cert_verifier.h" | |
22 #include "net/cert/multi_log_ct_verifier.h" | |
23 #include "net/dns/mapped_host_resolver.h" | |
24 #include "net/dns/mock_host_resolver.h" | |
25 #include "net/http/http_auth_handler_factory.h" | |
26 #include "net/http/http_network_session.h" | |
27 #include "net/http/http_network_transaction.h" | |
28 #include "net/http/http_server_properties_impl.h" | |
29 #include "net/http/http_transaction_test_util.h" | |
30 #include "net/http/transport_security_state.h" | |
31 #include "net/proxy/proxy_service.h" | |
32 #include "net/quic/test_tools/crypto_test_utils.h" | |
33 #include "net/quic/test_tools/quic_test_utils.h" | |
34 #include "net/ssl/default_channel_id_store.h" | |
35 #include "net/ssl/ssl_config_service_defaults.h" | |
36 #include "net/test/cert_test_util.h" | |
37 #include "net/test/gtest_util.h" | |
38 #include "net/test/test_data_directory.h" | |
39 #include "net/tools/quic/quic_in_memory_cache.h" | |
40 #include "net/tools/quic/quic_server.h" | |
41 #include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h" | |
42 #include "net/tools/quic/test_tools/server_thread.h" | |
43 #include "testing/gmock/include/gmock/gmock.h" | |
44 #include "testing/gtest/include/gtest/gtest.h" | |
45 #include "testing/platform_test.h" | |
46 | |
47 using base::StringPiece; | |
48 | |
49 namespace net { | |
50 | |
51 using test::IsOk; | |
52 using test::QuicInMemoryCachePeer; | |
53 using test::ServerThread; | |
54 | |
55 namespace test { | |
56 | |
57 namespace { | |
58 | |
59 const char kResponseBody[] = "some arbitrary response body"; | |
60 | |
61 // Factory for creating HttpTransactions, used by TestTransactionConsumer. | |
62 class TestTransactionFactory : public HttpTransactionFactory { | |
63 public: | |
64 explicit TestTransactionFactory(const HttpNetworkSession::Params& params) | |
65 : session_(new HttpNetworkSession(params)) {} | |
66 | |
67 ~TestTransactionFactory() override {} | |
68 | |
69 // HttpTransactionFactory methods | |
70 int CreateTransaction(RequestPriority priority, | |
71 std::unique_ptr<HttpTransaction>* trans) override { | |
72 trans->reset(new HttpNetworkTransaction(priority, session_.get())); | |
73 return OK; | |
74 } | |
75 | |
76 HttpCache* GetCache() override { return nullptr; } | |
77 | |
78 HttpNetworkSession* GetSession() override { return session_.get(); }; | |
79 | |
80 private: | |
81 std::unique_ptr<HttpNetworkSession> session_; | |
82 }; | |
83 | |
84 struct TestParams { | |
85 explicit TestParams(bool use_stateless_rejects) | |
86 : use_stateless_rejects(use_stateless_rejects) {} | |
87 | |
88 friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { | |
89 os << "{ use_stateless_rejects: " << p.use_stateless_rejects << " }"; | |
90 return os; | |
91 } | |
92 bool use_stateless_rejects; | |
93 }; | |
94 | |
95 std::vector<TestParams> GetTestParams() { | |
96 return std::vector<TestParams>{TestParams(true), TestParams(false)}; | |
97 } | |
98 | |
99 } // namespace | |
100 | |
101 class QuicEndToEndTest : public ::testing::TestWithParam<TestParams> { | |
102 protected: | |
103 QuicEndToEndTest() | |
104 : host_resolver_impl_(CreateResolverImpl()), | |
105 host_resolver_(std::move(host_resolver_impl_)), | |
106 cert_transparency_verifier_(new MultiLogCTVerifier()), | |
107 ssl_config_service_(new SSLConfigServiceDefaults), | |
108 proxy_service_(ProxyService::CreateDirect()), | |
109 auth_handler_factory_( | |
110 HttpAuthHandlerFactory::CreateDefault(&host_resolver_)), | |
111 strike_register_no_startup_period_(false) { | |
112 request_.method = "GET"; | |
113 request_.url = GURL("https://test.example.com/"); | |
114 request_.load_flags = 0; | |
115 | |
116 params_.enable_quic = true; | |
117 params_.quic_clock = nullptr; | |
118 params_.quic_random = nullptr; | |
119 if (GetParam().use_stateless_rejects) { | |
120 params_.quic_connection_options.push_back(kSREJ); | |
121 } | |
122 params_.host_resolver = &host_resolver_; | |
123 params_.cert_verifier = &cert_verifier_; | |
124 params_.transport_security_state = &transport_security_state_; | |
125 params_.cert_transparency_verifier = cert_transparency_verifier_.get(); | |
126 params_.ct_policy_enforcer = &ct_policy_enforcer_; | |
127 params_.proxy_service = proxy_service_.get(); | |
128 params_.ssl_config_service = ssl_config_service_.get(); | |
129 params_.http_auth_handler_factory = auth_handler_factory_.get(); | |
130 params_.http_server_properties = &http_server_properties_; | |
131 channel_id_service_.reset( | |
132 new ChannelIDService(new DefaultChannelIDStore(nullptr), | |
133 base::ThreadTaskRunnerHandle::Get())); | |
134 params_.channel_id_service = channel_id_service_.get(); | |
135 | |
136 CertVerifyResult verify_result; | |
137 verify_result.verified_cert = ImportCertFromFile( | |
138 GetTestCertsDirectory(), "quic_test.example.com.crt"); | |
139 cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(), | |
140 "test.example.com", verify_result, | |
141 OK); | |
142 verify_result.verified_cert = ImportCertFromFile( | |
143 GetTestCertsDirectory(), "quic_test_ecc.example.com.crt"); | |
144 cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(), | |
145 "test.example.com", verify_result, | |
146 OK); | |
147 } | |
148 | |
149 // Creates a mock host resolver in which test.example.com | |
150 // resolves to localhost. | |
151 static MockHostResolver* CreateResolverImpl() { | |
152 MockHostResolver* resolver = new MockHostResolver(); | |
153 resolver->rules()->AddRule("test.example.com", "127.0.0.1"); | |
154 return resolver; | |
155 } | |
156 | |
157 void SetUp() override { | |
158 QuicInMemoryCachePeer::ResetForTests(); | |
159 StartServer(); | |
160 | |
161 // Use a mapped host resolver so that request for test.example.com (port 80) | |
162 // reach the server running on localhost. | |
163 std::string map_rule = "MAP test.example.com test.example.com:" + | |
164 base::IntToString(server_thread_->GetPort()); | |
165 EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule)); | |
166 | |
167 // To simplify the test, and avoid the race with the HTTP request, we force | |
168 // QUIC for these requests. | |
169 params_.origins_to_force_quic_on.insert( | |
170 HostPortPair::FromString("test.example.com:443")); | |
171 | |
172 transaction_factory_.reset(new TestTransactionFactory(params_)); | |
173 } | |
174 | |
175 void TearDown() override { | |
176 StopServer(); | |
177 QuicInMemoryCachePeer::ResetForTests(); | |
178 } | |
179 | |
180 // Starts the QUIC server listening on a random port. | |
181 void StartServer() { | |
182 server_address_ = IPEndPoint(IPAddress(127, 0, 0, 1), 0); | |
183 server_config_.SetInitialStreamFlowControlWindowToSend( | |
184 kInitialStreamFlowControlWindowForTest); | |
185 server_config_.SetInitialSessionFlowControlWindowToSend( | |
186 kInitialSessionFlowControlWindowForTest); | |
187 server_config_options_.token_binding_enabled = true; | |
188 QuicServer* server = | |
189 new QuicServer(CryptoTestUtils::ProofSourceForTesting(), server_config_, | |
190 server_config_options_, QuicSupportedVersions()); | |
191 server_thread_.reset(new ServerThread(server, server_address_, | |
192 strike_register_no_startup_period_)); | |
193 server_thread_->Initialize(); | |
194 server_address_ = | |
195 IPEndPoint(server_address_.address(), server_thread_->GetPort()); | |
196 server_thread_->Start(); | |
197 server_started_ = true; | |
198 } | |
199 | |
200 // Stops the QUIC server. | |
201 void StopServer() { | |
202 if (!server_started_) { | |
203 return; | |
204 } | |
205 if (server_thread_.get()) { | |
206 server_thread_->Quit(); | |
207 server_thread_->Join(); | |
208 } | |
209 } | |
210 | |
211 // Adds an entry to the cache used by the QUIC server to serve | |
212 // responses. | |
213 void AddToCache(StringPiece path, | |
214 int response_code, | |
215 StringPiece response_detail, | |
216 StringPiece body) { | |
217 QuicInMemoryCache::GetInstance()->AddSimpleResponse( | |
218 "test.example.com", path, response_code, body); | |
219 } | |
220 | |
221 // Populates |request_body_| with |length_| ASCII bytes. | |
222 void GenerateBody(size_t length) { | |
223 request_body_.clear(); | |
224 request_body_.reserve(length); | |
225 for (size_t i = 0; i < length; ++i) { | |
226 request_body_.append(1, static_cast<char>(32 + i % (126 - 32))); | |
227 } | |
228 } | |
229 | |
230 // Initializes |request_| for a post of |length| bytes. | |
231 void InitializePostRequest(size_t length) { | |
232 GenerateBody(length); | |
233 std::vector<std::unique_ptr<UploadElementReader>> element_readers; | |
234 element_readers.push_back(base::WrapUnique(new UploadBytesElementReader( | |
235 request_body_.data(), request_body_.length()))); | |
236 upload_data_stream_.reset( | |
237 new ElementsUploadDataStream(std::move(element_readers), 0)); | |
238 request_.method = "POST"; | |
239 request_.url = GURL("https://test.example.com/"); | |
240 request_.upload_data_stream = upload_data_stream_.get(); | |
241 ASSERT_THAT(request_.upload_data_stream->Init(CompletionCallback()), | |
242 IsOk()); | |
243 } | |
244 | |
245 // Checks that |consumer| completed and received |status_line| and |body|. | |
246 void CheckResponse(const TestTransactionConsumer& consumer, | |
247 const std::string& status_line, | |
248 const std::string& body) { | |
249 ASSERT_TRUE(consumer.is_done()); | |
250 ASSERT_THAT(consumer.error(), IsOk()); | |
251 EXPECT_EQ(status_line, consumer.response_info()->headers->GetStatusLine()); | |
252 EXPECT_EQ(body, consumer.content()); | |
253 } | |
254 | |
255 std::unique_ptr<MockHostResolver> host_resolver_impl_; | |
256 MappedHostResolver host_resolver_; | |
257 MockCertVerifier cert_verifier_; | |
258 std::unique_ptr<ChannelIDService> channel_id_service_; | |
259 TransportSecurityState transport_security_state_; | |
260 std::unique_ptr<CTVerifier> cert_transparency_verifier_; | |
261 CTPolicyEnforcer ct_policy_enforcer_; | |
262 scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; | |
263 std::unique_ptr<ProxyService> proxy_service_; | |
264 std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_; | |
265 HttpServerPropertiesImpl http_server_properties_; | |
266 HttpNetworkSession::Params params_; | |
267 std::unique_ptr<TestTransactionFactory> transaction_factory_; | |
268 HttpRequestInfo request_; | |
269 std::string request_body_; | |
270 std::unique_ptr<UploadDataStream> upload_data_stream_; | |
271 std::unique_ptr<ServerThread> server_thread_; | |
272 IPEndPoint server_address_; | |
273 std::string server_hostname_; | |
274 QuicConfig server_config_; | |
275 QuicCryptoServerConfig::ConfigOptions server_config_options_; | |
276 bool server_started_; | |
277 bool strike_register_no_startup_period_; | |
278 }; | |
279 | |
280 INSTANTIATE_TEST_CASE_P(Tests, | |
281 QuicEndToEndTest, | |
282 ::testing::ValuesIn(GetTestParams())); | |
283 | |
284 TEST_P(QuicEndToEndTest, LargeGetWithNoPacketLoss) { | |
285 std::string response(10 * 1024, 'x'); | |
286 | |
287 AddToCache(request_.url.PathForRequest(), 200, "OK", response); | |
288 | |
289 TestTransactionConsumer consumer(DEFAULT_PRIORITY, | |
290 transaction_factory_.get()); | |
291 consumer.Start(&request_, BoundNetLog()); | |
292 | |
293 // Will terminate when the last consumer completes. | |
294 base::RunLoop().Run(); | |
295 | |
296 CheckResponse(consumer, "HTTP/1.1 200", response); | |
297 } | |
298 | |
299 TEST_P(QuicEndToEndTest, TokenBinding) { | |
300 // Enable token binding and re-initialize the TestTransactionFactory. | |
301 params_.enable_token_binding = true; | |
302 transaction_factory_.reset(new TestTransactionFactory(params_)); | |
303 | |
304 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody); | |
305 | |
306 TestTransactionConsumer consumer(DEFAULT_PRIORITY, | |
307 transaction_factory_.get()); | |
308 consumer.Start(&request_, BoundNetLog()); | |
309 | |
310 // Will terminate when the last consumer completes. | |
311 base::RunLoop().Run(); | |
312 | |
313 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody); | |
314 HttpRequestHeaders headers; | |
315 ASSERT_TRUE(consumer.transaction()->GetFullRequestHeaders(&headers)); | |
316 EXPECT_TRUE(headers.HasHeader(HttpRequestHeaders::kTokenBinding)); | |
317 } | |
318 | |
319 // crbug.com/559173 | |
320 #if defined(THREAD_SANITIZER) | |
321 TEST_P(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) { | |
322 #else | |
323 TEST_P(QuicEndToEndTest, LargePostWithNoPacketLoss) { | |
324 #endif | |
325 InitializePostRequest(1024 * 1024); | |
326 | |
327 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody); | |
328 | |
329 TestTransactionConsumer consumer(DEFAULT_PRIORITY, | |
330 transaction_factory_.get()); | |
331 consumer.Start(&request_, BoundNetLog()); | |
332 | |
333 // Will terminate when the last consumer completes. | |
334 base::RunLoop().Run(); | |
335 | |
336 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody); | |
337 } | |
338 | |
339 // crbug.com/559173 | |
340 #if defined(THREAD_SANITIZER) | |
341 TEST_P(QuicEndToEndTest, DISABLED_LargePostWithPacketLoss) { | |
342 #else | |
343 TEST_P(QuicEndToEndTest, LargePostWithPacketLoss) { | |
344 #endif | |
345 // FLAGS_fake_packet_loss_percentage = 30; | |
346 InitializePostRequest(1024 * 1024); | |
347 | |
348 const char kResponseBody[] = "some really big response body"; | |
349 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody); | |
350 | |
351 TestTransactionConsumer consumer(DEFAULT_PRIORITY, | |
352 transaction_factory_.get()); | |
353 consumer.Start(&request_, BoundNetLog()); | |
354 | |
355 // Will terminate when the last consumer completes. | |
356 base::RunLoop().Run(); | |
357 | |
358 CheckResponse(consumer, "HTTP/1.1 200", kResponseBody); | |
359 } | |
360 | |
361 // crbug.com/536845 | |
362 #if defined(THREAD_SANITIZER) | |
363 TEST_P(QuicEndToEndTest, DISABLED_UberTest) { | |
364 #else | |
365 TEST_P(QuicEndToEndTest, UberTest) { | |
366 #endif | |
367 // FLAGS_fake_packet_loss_percentage = 30; | |
368 | |
369 const char kResponseBody[] = "some really big response body"; | |
370 AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody); | |
371 | |
372 std::vector<TestTransactionConsumer*> consumers; | |
373 size_t num_requests = 100; | |
374 for (size_t i = 0; i < num_requests; ++i) { | |
375 TestTransactionConsumer* consumer = new TestTransactionConsumer( | |
376 DEFAULT_PRIORITY, transaction_factory_.get()); | |
377 consumers.push_back(consumer); | |
378 consumer->Start(&request_, BoundNetLog()); | |
379 } | |
380 | |
381 // Will terminate when the last consumer completes. | |
382 base::RunLoop().Run(); | |
383 | |
384 for (size_t i = 0; i < num_requests; ++i) { | |
385 CheckResponse(*consumers[i], "HTTP/1.1 200", kResponseBody); | |
386 } | |
387 STLDeleteElements(&consumers); | |
388 } | |
389 | |
390 } // namespace test | |
391 } // namespace net | |
OLD | NEW |