• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
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/containers/span.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "net/base/completion_once_callback.h"
17 #include "net/base/elements_upload_data_stream.h"
18 #include "net/base/ip_address.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/base/upload_bytes_element_reader.h"
21 #include "net/base/upload_data_stream.h"
22 #include "net/cert/mock_cert_verifier.h"
23 #include "net/cert/multi_log_ct_verifier.h"
24 #include "net/dns/mapped_host_resolver.h"
25 #include "net/dns/mock_host_resolver.h"
26 #include "net/http/http_auth_handler_factory.h"
27 #include "net/http/http_network_session.h"
28 #include "net/http/http_network_transaction.h"
29 #include "net/http/http_server_properties.h"
30 #include "net/http/http_transaction_test_util.h"
31 #include "net/http/transport_security_state.h"
32 #include "net/log/net_log_with_source.h"
33 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
34 #include "net/quic/crypto_test_utils_chromium.h"
35 #include "net/quic/quic_context.h"
36 #include "net/socket/client_socket_factory.h"
37 #include "net/ssl/ssl_config_service_defaults.h"
38 #include "net/test/cert_test_util.h"
39 #include "net/test/gtest_util.h"
40 #include "net/test/test_data_directory.h"
41 #include "net/test/test_with_task_environment.h"
42 #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
43 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
44 #include "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h"
45 #include "net/tools/quic/quic_simple_server.h"
46 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
47 #include "net/url_request/static_http_user_agent_settings.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "testing/platform_test.h"
51 
52 namespace net {
53 
54 using test::IsOk;
55 
56 namespace test {
57 
58 namespace {
59 
60 const char kResponseBody[] = "some arbitrary response body";
61 
62 // Factory for creating HttpTransactions, used by TestTransactionConsumer.
63 class TestTransactionFactory : public HttpTransactionFactory {
64  public:
TestTransactionFactory(const HttpNetworkSessionParams & session_params,const HttpNetworkSessionContext & session_context)65   explicit TestTransactionFactory(
66       const HttpNetworkSessionParams& session_params,
67       const HttpNetworkSessionContext& session_context)
68       : session_(std::make_unique<HttpNetworkSession>(session_params,
69                                                       session_context)) {}
70 
71   ~TestTransactionFactory() override = default;
72 
73   // HttpTransactionFactory methods
CreateTransaction(RequestPriority priority,std::unique_ptr<HttpTransaction> * trans)74   int CreateTransaction(RequestPriority priority,
75                         std::unique_ptr<HttpTransaction>* trans) override {
76     *trans = std::make_unique<HttpNetworkTransaction>(priority, session_.get());
77     return OK;
78   }
79 
GetCache()80   HttpCache* GetCache() override { return nullptr; }
81 
GetSession()82   HttpNetworkSession* GetSession() override { return session_.get(); }
83 
84  private:
85   std::unique_ptr<HttpNetworkSession> session_;
86 };
87 
88 }  // namespace
89 
90 class QuicEndToEndTest : public ::testing::Test, public WithTaskEnvironment {
91  protected:
QuicEndToEndTest()92   QuicEndToEndTest()
93       : host_resolver_(CreateResolverImpl()),
94         ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()),
95         proxy_resolution_service_(
96             ConfiguredProxyResolutionService::CreateDirect()),
97         auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()) {
98     request_.method = "GET";
99     request_.url = GURL("https://test.example.com/");
100     request_.load_flags = 0;
101     request_.traffic_annotation =
102         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
103 
104     session_params_.enable_quic = true;
105 
106     session_context_.client_socket_factory =
107         ClientSocketFactory::GetDefaultFactory();
108     session_context_.quic_context = &quic_context_;
109     session_context_.host_resolver = &host_resolver_;
110     session_context_.cert_verifier = &cert_verifier_;
111     session_context_.transport_security_state = &transport_security_state_;
112     session_context_.proxy_resolution_service = proxy_resolution_service_.get();
113     session_context_.ssl_config_service = ssl_config_service_.get();
114     session_context_.http_user_agent_settings = &http_user_agent_settings_;
115     session_context_.http_auth_handler_factory = auth_handler_factory_.get();
116     session_context_.http_server_properties = &http_server_properties_;
117 
118     CertVerifyResult verify_result;
119     verify_result.verified_cert =
120         ImportCertFromFile(GetTestCertsDirectory(), "quic-chain.pem");
121     cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(),
122                                            "test.example.com", verify_result,
123                                            OK);
124   }
125 
126   // Creates a mock host resolver in which test.example.com
127   // resolves to localhost.
CreateResolverImpl()128   static std::unique_ptr<MockHostResolver> CreateResolverImpl() {
129     auto resolver = std::make_unique<MockHostResolver>();
130     resolver->rules()->AddRule("test.example.com", "127.0.0.1");
131     return resolver;
132   }
133 
SetUp()134   void SetUp() override {
135     StartServer();
136 
137     // Use a mapped host resolver so that request for test.example.com (port 80)
138     // reach the server running on localhost.
139     std::string map_rule =
140         "MAP test.example.com test.example.com:" +
141         base::NumberToString(server_->server_address().port());
142     EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule));
143 
144     // To simplify the test, and avoid the race with the HTTP request, we force
145     // QUIC for these requests.
146     quic_context_.params()->origins_to_force_quic_on.insert(
147         HostPortPair::FromString("test.example.com:443"));
148 
149     transaction_factory_ = std::make_unique<TestTransactionFactory>(
150         session_params_, session_context_);
151   }
152 
TearDown()153   void TearDown() override {}
154 
155   // Starts the QUIC server listening on a random port.
StartServer()156   void StartServer() {
157     server_address_ = IPEndPoint(IPAddress(127, 0, 0, 1), 0);
158     server_config_.SetInitialStreamFlowControlWindowToSend(
159         quic::test::kInitialStreamFlowControlWindowForTest);
160     server_config_.SetInitialSessionFlowControlWindowToSend(
161         quic::test::kInitialSessionFlowControlWindowForTest);
162     server_ = std::make_unique<QuicSimpleServer>(
163         net::test::ProofSourceForTestingChromium(), server_config_,
164         server_config_options_, AllSupportedQuicVersions(),
165         &memory_cache_backend_);
166     server_->Listen(server_address_);
167     server_address_ = server_->server_address();
168     server_->StartReading();
169     server_started_ = true;
170   }
171 
172   // Adds an entry to the cache used by the QUIC server to serve
173   // responses.
AddToCache(std::string_view path,int response_code,std::string_view response_detail,std::string_view body)174   void AddToCache(std::string_view path,
175                   int response_code,
176                   std::string_view response_detail,
177                   std::string_view body) {
178     memory_cache_backend_.AddSimpleResponse("test.example.com", path,
179                                             response_code, body);
180   }
181 
182   // Populates |request_body_| with |length_| ASCII bytes.
GenerateBody(size_t length)183   void GenerateBody(size_t length) {
184     request_body_.clear();
185     request_body_.reserve(length);
186     for (size_t i = 0; i < length; ++i) {
187       request_body_.append(1, static_cast<char>(32 + i % (126 - 32)));
188     }
189   }
190 
191   // Initializes |request_| for a post of |length| bytes.
InitializePostRequest(size_t length)192   void InitializePostRequest(size_t length) {
193     GenerateBody(length);
194     std::vector<std::unique_ptr<UploadElementReader>> element_readers;
195     element_readers.push_back(std::make_unique<UploadBytesElementReader>(
196         base::as_byte_span(request_body_)));
197     upload_data_stream_ = std::make_unique<ElementsUploadDataStream>(
198         std::move(element_readers), 0);
199     request_.method = "POST";
200     request_.url = GURL("https://test.example.com/");
201     request_.upload_data_stream = upload_data_stream_.get();
202     ASSERT_THAT(request_.upload_data_stream->Init(CompletionOnceCallback(),
203                                                   NetLogWithSource()),
204                 IsOk());
205   }
206 
207   // Checks that |consumer| completed and received |status_line| and |body|.
CheckResponse(const TestTransactionConsumer & consumer,const std::string & status_line,const std::string & body)208   void CheckResponse(const TestTransactionConsumer& consumer,
209                      const std::string& status_line,
210                      const std::string& body) {
211     ASSERT_TRUE(consumer.is_done());
212     ASSERT_THAT(consumer.error(), IsOk());
213     EXPECT_EQ(status_line, consumer.response_info()->headers->GetStatusLine());
214     EXPECT_EQ(body, consumer.content());
215   }
216 
217   QuicContext quic_context_;
218   MappedHostResolver host_resolver_;
219   MockCertVerifier cert_verifier_;
220   TransportSecurityState transport_security_state_;
221   std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
222   std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
223   std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
224   StaticHttpUserAgentSettings http_user_agent_settings_ = {"*", "test-ua"};
225   HttpServerProperties http_server_properties_;
226   HttpNetworkSessionParams session_params_;
227   HttpNetworkSessionContext session_context_;
228   std::unique_ptr<TestTransactionFactory> transaction_factory_;
229   std::string request_body_;
230   std::unique_ptr<UploadDataStream> upload_data_stream_;
231   HttpRequestInfo request_;
232   quic::QuicMemoryCacheBackend memory_cache_backend_;
233   std::unique_ptr<QuicSimpleServer> server_;
234   IPEndPoint server_address_;
235   std::string server_hostname_;
236   quic::QuicConfig server_config_;
237   quic::QuicCryptoServerConfig::ConfigOptions server_config_options_;
238   bool server_started_;
239   bool strike_register_no_startup_period_ = false;
240 };
241 
TEST_F(QuicEndToEndTest,LargeGetWithNoPacketLoss)242 TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
243   std::string response(10 * 1024, 'x');
244 
245   AddToCache(request_.url.PathForRequest(), 200, "OK", response);
246 
247   TestTransactionConsumer consumer(DEFAULT_PRIORITY,
248                                    transaction_factory_.get());
249   consumer.Start(&request_, NetLogWithSource());
250 
251   CheckResponse(consumer, "HTTP/1.1 200", response);
252 }
253 
254 // crbug.com/559173
255 #if defined(THREAD_SANITIZER)
TEST_F(QuicEndToEndTest,DISABLED_LargePostWithNoPacketLoss)256 TEST_F(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
257 #else
258 TEST_F(QuicEndToEndTest, LargePostWithNoPacketLoss) {
259 #endif
260   InitializePostRequest(1024 * 1024);
261 
262   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
263 
264   TestTransactionConsumer consumer(DEFAULT_PRIORITY,
265                                    transaction_factory_.get());
266   consumer.Start(&request_, NetLogWithSource());
267 
268   CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
269 }
270 
271 // crbug.com/559173
272 #if defined(THREAD_SANITIZER)
273 TEST_F(QuicEndToEndTest, DISABLED_LargePostWithPacketLoss) {
274 #else
275 TEST_F(QuicEndToEndTest, LargePostWithPacketLoss) {
276 #endif
277   // FLAGS_fake_packet_loss_percentage = 30;
278   InitializePostRequest(1024 * 1024);
279 
280   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
281 
282   TestTransactionConsumer consumer(DEFAULT_PRIORITY,
283                                    transaction_factory_.get());
284   consumer.Start(&request_, NetLogWithSource());
285 
286   CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
287 }
288 
289 // crbug.com/536845
290 #if defined(THREAD_SANITIZER)
291 TEST_F(QuicEndToEndTest, DISABLED_UberTest) {
292 #else
293 TEST_F(QuicEndToEndTest, UberTest) {
294 #endif
295   // FLAGS_fake_packet_loss_percentage = 30;
296 
297   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
298 
299   std::vector<std::unique_ptr<TestTransactionConsumer>> consumers;
300   for (size_t i = 0; i < 100; ++i) {
301     TestTransactionConsumer* consumer = new TestTransactionConsumer(
302         DEFAULT_PRIORITY, transaction_factory_.get());
303     consumers.push_back(base::WrapUnique(consumer));
304     consumer->Start(&request_, NetLogWithSource());
305   }
306 
307   for (const auto& consumer : consumers)
308     CheckResponse(*consumer.get(), "HTTP/1.1 200", kResponseBody);
309 }
310 
311 TEST_F(QuicEndToEndTest, EnableMLKEM) {
312   // Enable ML-KEM on the client.
313   base::test::ScopedFeatureList scoped_feature_list;
314   scoped_feature_list.InitWithFeatures({features::kPostQuantumKyber}, {});
315 
316   // Configure the server to only support ML-KEM.
317   server_->crypto_config()->set_preferred_groups({SSL_GROUP_X25519_MLKEM768});
318 
319   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
320 
321   TestTransactionConsumer consumer(DEFAULT_PRIORITY,
322                                    transaction_factory_.get());
323   consumer.Start(&request_, NetLogWithSource());
324 
325   CheckResponse(consumer, "HTTP/1.1 200", kResponseBody);
326   EXPECT_EQ(consumer.response_info()->ssl_info.key_exchange_group,
327             SSL_GROUP_X25519_MLKEM768);
328 }
329 
330 TEST_F(QuicEndToEndTest, MLKEMDisabled) {
331   // Disable ML-KEM on the client.
332   base::test::ScopedFeatureList scoped_feature_list;
333   scoped_feature_list.InitWithFeatures({}, {features::kPostQuantumKyber});
334 
335   // Configure the server to only support ML-KEM.
336   server_->crypto_config()->set_preferred_groups({SSL_GROUP_X25519_MLKEM768});
337 
338   AddToCache(request_.url.PathForRequest(), 200, "OK", kResponseBody);
339 
340   TestTransactionConsumer consumer(DEFAULT_PRIORITY,
341                                    transaction_factory_.get());
342   consumer.Start(&request_, NetLogWithSource());
343 
344   // Connection should fail because there's no supported group in common between
345   // client and server.
346   EXPECT_EQ(consumer.error(), net::ERR_QUIC_PROTOCOL_ERROR);
347 }
348 
349 }  // namespace test
350 }  // namespace net
351