| 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 |