Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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 <inttypes.h> | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/callback.h" | |
| 10 #include "base/files/file_path.h" | |
| 11 #include "base/memory/ptr_util.h" | |
| 12 #include "base/message_loop/message_loop.h" | |
| 13 #include "base/run_loop.h" | |
| 14 #include "base/single_thread_task_runner.h" | |
| 15 #include "base/strings/string_number_conversions.h" | |
| 16 #include "base/strings/stringprintf.h" | |
| 17 #include "base/time/time.h" | |
| 18 #include "base/trace_event/memory_dump_manager.h" | |
| 19 #include "base/trace_event/memory_dump_request_args.h" | |
| 20 #include "base/trace_event/process_memory_dump.h" | |
| 21 #include "base/trace_event/trace_config.h" | |
| 22 #include "base/trace_event/trace_config_memory_test_util.h" | |
| 23 #include "base/trace_event/trace_event_argument.h" | |
| 24 #include "base/trace_event/trace_log.h" | |
| 25 #include "net/base/load_timing_info.h" | |
| 26 #include "net/cert/mock_cert_verifier.h" | |
| 27 #include "net/dns/mapped_host_resolver.h" | |
| 28 #include "net/dns/mock_host_resolver.h" | |
| 29 #include "net/http/http_status_code.h" | |
| 30 #include "net/quic/chromium/crypto/proof_source_chromium.h" | |
| 31 #include "net/quic/test_tools/crypto_test_utils.h" | |
| 32 #include "net/test/cert_test_util.h" | |
| 33 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 34 #include "net/test/embedded_test_server/http_response.h" | |
| 35 #include "net/test/gtest_util.h" | |
| 36 #include "net/test/test_data_directory.h" | |
| 37 #include "net/tools/quic/quic_http_response_cache.h" | |
| 38 #include "net/tools/quic/quic_simple_server.h" | |
| 39 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" | |
| 40 #include "net/url_request/url_request.h" | |
| 41 #include "net/url_request/url_request_test_util.h" | |
| 42 #include "testing/gmock/include/gmock/gmock.h" | |
| 43 #include "testing/gtest/include/gtest/gtest.h" | |
| 44 #include "testing/perf/perf_test.h" | |
| 45 #include "url/gurl.h" | |
| 46 | |
| 47 using testing::_; | |
| 48 using testing::Invoke; | |
| 49 | |
| 50 namespace net { | |
| 51 | |
| 52 namespace { | |
| 53 | |
| 54 const int kAltSvcPort = 6121; | |
| 55 const char kOriginHost[] = "mail.example.com"; | |
| 56 const char kAltSvcHost[] = "test.example.com"; | |
| 57 // Used as a simple response from the server. | |
| 58 const char kHelloPath[] = "/hello.txt"; | |
| 59 const char kHelloAltSvcResponse[] = "Hello from QUIC Server"; | |
| 60 const char kHelloOriginResponse[] = "Hello from TCP Server"; | |
| 61 const int kHelloStatus = 200; | |
| 62 | |
| 63 std::unique_ptr<test_server::HttpResponse> HandleRequest( | |
| 64 const test_server::HttpRequest& request) { | |
| 65 std::unique_ptr<test_server::BasicHttpResponse> http_response( | |
| 66 new test_server::BasicHttpResponse()); | |
| 67 http_response->AddCustomHeader( | |
| 68 "Alt-Svc", base::StringPrintf( | |
| 69 "quic=\"%s:%d\"; v=\"%u\"", kAltSvcHost, kAltSvcPort, | |
| 70 HttpNetworkSession::Params().quic_supported_versions[0])); | |
| 71 http_response->set_code(HTTP_OK); | |
| 72 http_response->set_content(kHelloOriginResponse); | |
| 73 http_response->set_content_type("text/plain"); | |
| 74 return std::move(http_response); | |
| 75 } | |
| 76 | |
| 77 void PrintPerfTest(const std::string& name, | |
| 78 int value, | |
| 79 const std::string& unit) { | |
| 80 const ::testing::TestInfo* test_info = | |
| 81 ::testing::UnitTest::GetInstance()->current_test_info(); | |
| 82 perf_test::PrintResult(test_info->test_case_name(), | |
| 83 std::string(".") + test_info->name(), name, | |
| 84 static_cast<double>(value), unit, true); | |
| 85 } | |
| 86 | |
| 87 // This mocks the RequestGlobalDumpFunction which is typically handled by | |
| 88 // process_local_dump_manager_impl.cc. | |
| 89 class GlobalMemoryDumpHandler { | |
| 90 public: | |
| 91 MOCK_METHOD2( | |
| 92 RequestGlobalMemoryDump, | |
| 93 void(const base::trace_event::MemoryDumpRequestArgs& args, | |
| 94 const base::trace_event::GlobalMemoryDumpCallback& callback)); | |
| 95 GlobalMemoryDumpHandler() {} | |
| 96 }; | |
| 97 | |
| 98 // A TestURLRequestContext that records memory dump stats when OnMemoryDump() is | |
| 99 // invoked. | |
| 100 class MemoryTestURLRequestContext : public TestURLRequestContext { | |
| 101 public: | |
| 102 MemoryTestURLRequestContext() : TestURLRequestContext(true) {} | |
| 103 | |
| 104 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, | |
| 105 base::trace_event::ProcessMemoryDump* pmd) override { | |
| 106 bool result = TestURLRequestContext::OnMemoryDump(args, pmd); | |
| 107 | |
| 108 const base::trace_event::MemoryAllocatorDump* url_request_context_dump = | |
| 109 pmd->GetAllocatorDump( | |
| 110 base::StringPrintf("net/url_request_context/unknown/0x%" PRIxPTR, | |
| 111 reinterpret_cast<uintptr_t>(this))); | |
| 112 url_request_context_dump_attrs_ = | |
| 113 url_request_context_dump->attributes_for_testing()->ToBaseValue(); | |
| 114 | |
| 115 const base::trace_event::MemoryAllocatorDump* quic_stream_factory_dump = | |
| 116 pmd->GetAllocatorDump(base::StringPrintf( | |
| 117 "net/http_network_session_%p/quic_stream_factory", | |
| 118 http_transaction_factory()->GetSession())); | |
| 119 quic_stream_factory_attrs_ = | |
| 120 quic_stream_factory_dump->attributes_for_testing()->ToBaseValue(); | |
| 121 | |
| 122 const base::trace_event::MemoryAllocatorDump* http_stream_factory_dump = | |
| 123 pmd->GetAllocatorDump( | |
| 124 base::StringPrintf("net/http_network_session_%p/stream_factory", | |
| 125 http_transaction_factory()->GetSession())); | |
| 126 EXPECT_EQ(nullptr, http_stream_factory_dump); | |
| 127 return result; | |
| 128 } | |
| 129 | |
| 130 std::unique_ptr<base::Value> url_request_context_dump_attrs_; | |
| 131 std::unique_ptr<base::Value> quic_stream_factory_attrs_; | |
| 132 }; | |
| 133 | |
| 134 class URLRequestQuicPerfTest : public ::testing::Test { | |
| 135 public: | |
| 136 void ProcessDumpRecordingCallbackAdapter( | |
| 137 base::trace_event::GlobalMemoryDumpCallback callback, | |
| 138 uint64_t dump_guid, | |
| 139 bool success, | |
| 140 const base::Optional<base::trace_event::MemoryDumpCallbackResult>& | |
| 141 result) { | |
| 142 if (result.has_value()) { | |
| 143 results_.push_back(result.value()); | |
| 144 } | |
| 145 callback.Run(dump_guid, success); | |
| 146 } | |
| 147 | |
| 148 protected: | |
| 149 URLRequestQuicPerfTest() : message_loop_(new base::MessageLoopForIO()) { | |
| 150 InitializeMemoryDumpManager(); | |
| 151 mdm_->set_dumper_registrations_ignored_for_testing(false); | |
| 152 context_ = base::MakeUnique<MemoryTestURLRequestContext>(); | |
| 153 mdm_->set_dumper_registrations_ignored_for_testing(true); | |
| 154 StartTcpServer(); | |
| 155 StartQuicServer(); | |
| 156 | |
| 157 // Host mapping. | |
| 158 std::unique_ptr<MockHostResolver> resolver(new MockHostResolver()); | |
| 159 resolver->rules()->AddRule(kAltSvcHost, "127.0.0.1"); | |
| 160 host_resolver_.reset(new MappedHostResolver(std::move(resolver))); | |
| 161 std::string map_rule = base::StringPrintf("MAP %s 127.0.0.1:%d", | |
| 162 kOriginHost, tcp_server_->port()); | |
| 163 EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule)); | |
| 164 | |
| 165 std::unique_ptr<HttpNetworkSession::Params> params( | |
| 166 new HttpNetworkSession::Params); | |
| 167 params->cert_verifier = &cert_verifier_; | |
| 168 params->enable_quic = true; | |
| 169 params->enable_user_alternate_protocol_ports = true; | |
| 170 context_->set_host_resolver(host_resolver_.get()); | |
| 171 context_->set_http_network_session_params(std::move(params)); | |
| 172 context_->set_cert_verifier(&cert_verifier_); | |
| 173 context_->Init(); | |
| 174 } | |
| 175 | |
| 176 void TearDown() override { | |
| 177 if (quic_server_) { | |
| 178 quic_server_->Shutdown(); | |
|
nednguyen
2017/05/27 00:28:39
what about shutting down tcp_server_?
xunjieli
2017/05/29 20:16:00
The destructor of EmbeddedTestServer calls Shutdow
nednguyen
2017/05/30 13:31:38
I see. Can you add comment explaining why we don't
xunjieli
2017/06/02 20:43:59
Done.
| |
| 179 // If possible, deliver the conncetion close packet to the client before | |
| 180 // destruct the TestURLRequestContext. | |
| 181 base::RunLoop().RunUntilIdle(); | |
| 182 } | |
| 183 mdm_.reset(); | |
| 184 message_loop_.reset(); | |
| 185 } | |
| 186 | |
| 187 std::unique_ptr<URLRequest> CreateRequest(const GURL& url, | |
| 188 RequestPriority priority, | |
| 189 URLRequest::Delegate* delegate) { | |
| 190 return context_->CreateRequest(url, priority, delegate, | |
| 191 TRAFFIC_ANNOTATION_FOR_TESTS); | |
| 192 } | |
| 193 | |
| 194 // Turns a Closure into a GlobalMemoryDumpCallback and takes care of posting | |
| 195 // the closure on the correct task runner. | |
| 196 void GlobalDumpCallbackAdapter( | |
| 197 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 198 base::Closure closure, | |
| 199 uint64_t dump_guid, | |
| 200 bool success) { | |
| 201 task_runner->PostTask(FROM_HERE, closure); | |
| 202 } | |
| 203 | |
| 204 void RequestGlobalDumpAndWait( | |
| 205 base::trace_event::MemoryDumpType dump_type, | |
| 206 base::trace_event::MemoryDumpLevelOfDetail level_of_detail) { | |
| 207 base::RunLoop run_loop; | |
| 208 base::trace_event::GlobalMemoryDumpCallback callback = | |
| 209 base::Bind(&URLRequestQuicPerfTest::GlobalDumpCallbackAdapter, | |
| 210 base::Unretained(this), base::ThreadTaskRunnerHandle::Get(), | |
| 211 run_loop.QuitClosure()); | |
| 212 mdm_->RequestGlobalDump(dump_type, level_of_detail, callback); | |
| 213 run_loop.Run(); | |
| 214 } | |
| 215 | |
| 216 MemoryTestURLRequestContext* context() const { return context_.get(); } | |
|
nednguyen
2017/05/27 00:28:39
why defining this if we can just use context_-> in
xunjieli
2017/05/29 20:16:00
It's hard to reason about the tests if the tests s
nednguyen
2017/05/30 13:31:38
I think if the accessor just returns the non-const
xunjieli
2017/06/02 20:43:59
I hear you, but I find it easier to reason about t
| |
| 217 | |
| 218 const std::vector<base::trace_event::MemoryDumpCallbackResult>* GetResults() | |
| 219 const { | |
| 220 return &results_; | |
| 221 } | |
| 222 | |
| 223 GlobalMemoryDumpHandler global_dump_handler_; | |
| 224 std::unique_ptr<base::trace_event::MemoryDumpManager> mdm_; | |
| 225 | |
| 226 private: | |
| 227 void InitializeMemoryDumpManager() { | |
| 228 mdm_ = base::trace_event::MemoryDumpManager::CreateInstanceForTesting(); | |
| 229 mdm_->set_dumper_registrations_ignored_for_testing(true); | |
| 230 mdm_->Initialize( | |
| 231 BindRepeating(&GlobalMemoryDumpHandler::RequestGlobalMemoryDump, | |
| 232 base::Unretained(&global_dump_handler_)), | |
| 233 /*is_coordinator=*/false); | |
| 234 } | |
| 235 | |
| 236 void StartQuicServer() { | |
| 237 net::QuicConfig config; | |
| 238 response_cache_.AddSimpleResponse(kOriginHost, kHelloPath, kHelloStatus, | |
| 239 kHelloAltSvcResponse); | |
| 240 quic_server_.reset(new QuicSimpleServer( | |
| 241 test::crypto_test_utils::ProofSourceForTesting(), config, | |
| 242 net::QuicCryptoServerConfig::ConfigOptions(), AllSupportedVersions(), | |
| 243 &response_cache_)); | |
| 244 int rv = quic_server_->Listen( | |
| 245 net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kAltSvcPort)); | |
| 246 ASSERT_GE(rv, 0) << "Quic server fails to start"; | |
| 247 | |
| 248 CertVerifyResult verify_result; | |
| 249 verify_result.verified_cert = ImportCertFromFile( | |
| 250 GetTestCertsDirectory(), "quic_test.example.com.crt"); | |
| 251 cert_verifier_.AddResultForCert(verify_result.verified_cert.get(), | |
| 252 verify_result, OK); | |
| 253 } | |
| 254 | |
| 255 void StartTcpServer() { | |
| 256 tcp_server_ = base::MakeUnique<EmbeddedTestServer>( | |
| 257 net::EmbeddedTestServer::TYPE_HTTPS); | |
| 258 tcp_server_->RegisterRequestHandler(base::Bind(&HandleRequest)); | |
| 259 ASSERT_TRUE(tcp_server_->Start()) << "HTTP/1.1 server fails to start"; | |
| 260 | |
| 261 CertVerifyResult verify_result; | |
| 262 verify_result.verified_cert = tcp_server_->GetCertificate(); | |
| 263 cert_verifier_.AddResultForCert(tcp_server_->GetCertificate(), | |
| 264 verify_result, OK); | |
| 265 } | |
| 266 | |
| 267 std::unique_ptr<MappedHostResolver> host_resolver_; | |
| 268 std::unique_ptr<EmbeddedTestServer> tcp_server_; | |
| 269 std::unique_ptr<QuicSimpleServer> quic_server_; | |
| 270 std::unique_ptr<base::MessageLoop> message_loop_; | |
| 271 std::unique_ptr<MemoryTestURLRequestContext> context_; | |
| 272 std::vector<base::trace_event::MemoryDumpCallbackResult> results_; | |
| 273 QuicHttpResponseCache response_cache_; | |
| 274 MockCertVerifier cert_verifier_; | |
| 275 }; | |
| 276 | |
| 277 } // namespace | |
| 278 | |
| 279 TEST_F(URLRequestQuicPerfTest, TestGetRequest) { | |
| 280 bool quic_succeeded = false; | |
| 281 GURL url(base::StringPrintf("https://%s%s", kOriginHost, kHelloPath)); | |
| 282 base::TimeTicks start = base::TimeTicks::Now(); | |
| 283 const int kNumRequest = 1000; | |
| 284 for (int i = 0; i < kNumRequest; ++i) { | |
| 285 TestDelegate delegate; | |
| 286 std::unique_ptr<URLRequest> request = | |
| 287 CreateRequest(url, DEFAULT_PRIORITY, &delegate); | |
| 288 | |
| 289 request->Start(); | |
| 290 EXPECT_TRUE(request->is_pending()); | |
| 291 base::RunLoop().Run(); | |
| 292 | |
| 293 EXPECT_TRUE(request->status().is_success()); | |
| 294 if (delegate.data_received() == kHelloAltSvcResponse) { | |
| 295 quic_succeeded = true; | |
| 296 } else { | |
| 297 EXPECT_EQ(kHelloOriginResponse, delegate.data_received()); | |
| 298 } | |
| 299 } | |
| 300 base::TimeTicks end = base::TimeTicks::Now(); | |
| 301 PrintPerfTest("time", (end - start).InMilliseconds() / kNumRequest, "ms"); | |
| 302 | |
| 303 EXPECT_TRUE(quic_succeeded); | |
| 304 base::trace_event::TraceLog::GetInstance()->SetEnabled( | |
| 305 base::trace_event::TraceConfig( | |
| 306 base::trace_event::MemoryDumpManager::kTraceCategory, ""), | |
| 307 base::trace_event::TraceLog::RECORDING_MODE); | |
| 308 | |
| 309 EXPECT_CALL(global_dump_handler_, RequestGlobalMemoryDump(_, _)) | |
|
nednguyen
2017/05/27 00:28:39
silly question, what is this mock test for?
xunjieli
2017/05/29 20:16:00
I am following the MemoryDumpManagerTest example.
nednguyen
2017/05/30 13:31:38
It seems a bit unintuitive to me to rely on gtest
xunjieli
2017/06/02 20:43:59
Acknowledged.
| |
| 310 .WillOnce(Invoke([this]( | |
| 311 const base::trace_event::MemoryDumpRequestArgs& args, | |
| 312 const base::trace_event::GlobalMemoryDumpCallback& | |
| 313 callback) { | |
| 314 base::trace_event::ProcessMemoryDumpCallback process_callback = | |
| 315 Bind(&URLRequestQuicPerfTest::ProcessDumpRecordingCallbackAdapter, | |
| 316 base::Unretained(this), callback); | |
| 317 mdm_->CreateProcessDump(args, process_callback); | |
| 318 })); | |
| 319 | |
| 320 RequestGlobalDumpAndWait( | |
| 321 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED, | |
| 322 base::trace_event::MemoryDumpLevelOfDetail::LIGHT); | |
| 323 base::trace_event::TraceLog::GetInstance()->SetDisabled(); | |
| 324 | |
| 325 // Check ProcessMemoryDump stats. | |
| 326 ASSERT_EQ(1u, GetResults()->size()); | |
| 327 base::trace_event::MemoryDumpCallbackResult result = GetResults()->front(); | |
| 328 PrintPerfTest("chrome_malloc_total_kb", result.chrome_dump.malloc_total_kb, | |
| 329 "kB"); | |
| 330 PrintPerfTest("os_resident_set_kb", result.os_dump.resident_set_kb, "kB"); | |
| 331 | |
| 332 // Check URLRequestContext::OnMemoryDump() stats. | |
| 333 base::DictionaryValue* attrs; | |
| 334 ASSERT_TRUE( | |
| 335 context()->url_request_context_dump_attrs_->GetAsDictionary(&attrs)); | |
| 336 base::DictionaryValue* object_count_attrs; | |
| 337 ASSERT_TRUE(attrs->GetDictionary( | |
| 338 base::trace_event::MemoryAllocatorDump::kNameObjectCount, | |
| 339 &object_count_attrs)); | |
| 340 std::string object_count_str; | |
| 341 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str)); | |
| 342 EXPECT_EQ("0", object_count_str); | |
| 343 | |
| 344 ASSERT_TRUE(context()->quic_stream_factory_attrs_->GetAsDictionary(&attrs)); | |
| 345 ASSERT_TRUE(attrs->GetDictionary("active_jobs", &object_count_attrs)); | |
| 346 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str)); | |
| 347 EXPECT_EQ("0", object_count_str); | |
| 348 int object_count = -1; | |
| 349 ASSERT_TRUE(base::HexStringToInt(object_count_str, &object_count)); | |
| 350 PrintPerfTest("active_quic_jobs", object_count, "count"); | |
| 351 | |
| 352 ASSERT_TRUE(attrs->GetDictionary("all_sessions", &object_count_attrs)); | |
| 353 ASSERT_TRUE(object_count_attrs->GetString("value", &object_count_str)); | |
| 354 EXPECT_EQ("1", object_count_str); | |
| 355 ASSERT_TRUE(base::HexStringToInt(object_count_str, &object_count)); | |
| 356 PrintPerfTest("active_quic_sessions", object_count, "count"); | |
| 357 } | |
| 358 | |
| 359 } // namespace net | |
| OLD | NEW |