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