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