Fix Telemetry media seek action flakiness.
[chromium-blink-merge.git] / net / tools / fetch / fetch_client.cc
blobf0bec35ff76f7a12a768342bc4765e333edca091
1 // Copyright (c) 2012 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.
5 #include "build/build_config.h"
7 #include "base/at_exit.h"
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/command_line.h"
11 #include "base/lazy_instance.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/stats_counters.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/request_priority.h"
20 #include "net/cert/cert_verifier.h"
21 #include "net/dns/host_resolver.h"
22 #include "net/http/http_auth_handler_factory.h"
23 #include "net/http/http_cache.h"
24 #include "net/http/http_network_layer.h"
25 #include "net/http/http_network_session.h"
26 #include "net/http/http_request_info.h"
27 #include "net/http/http_server_properties_impl.h"
28 #include "net/http/http_transaction.h"
29 #include "net/http/transport_security_state.h"
30 #include "net/proxy/proxy_service.h"
31 #include "net/ssl/ssl_config_service_defaults.h"
33 void usage(const char* program_name) {
34 printf("usage: %s --url=<url> [--n=<clients>] [--stats] [--use_cache]\n",
35 program_name);
36 exit(1);
39 // Test Driver
40 class Driver {
41 public:
42 Driver()
43 : clients_(0) {}
45 void ClientStarted() { clients_++; }
46 void ClientStopped() {
47 if (!--clients_) {
48 base::MessageLoop::current()->Quit();
52 private:
53 int clients_;
56 static base::LazyInstance<Driver> g_driver = LAZY_INSTANCE_INITIALIZER;
58 // A network client
59 class Client {
60 public:
61 Client(net::HttpTransactionFactory* factory, const std::string& url) :
62 url_(url),
63 buffer_(new net::IOBuffer(kBufferSize)) {
64 int rv = factory->CreateTransaction(
65 net::DEFAULT_PRIORITY, &transaction_, NULL);
66 DCHECK_EQ(net::OK, rv);
67 buffer_->AddRef();
68 g_driver.Get().ClientStarted();
69 request_info_.url = url_;
70 request_info_.method = "GET";
71 int state = transaction_->Start(
72 &request_info_,
73 base::Bind(&Client::OnConnectComplete, base::Unretained(this)),
74 net::BoundNetLog());
75 DCHECK(state == net::ERR_IO_PENDING);
78 private:
79 void OnConnectComplete(int result) {
80 // Do work here.
81 int state = transaction_->Read(
82 buffer_.get(), kBufferSize,
83 base::Bind(&Client::OnReadComplete, base::Unretained(this)));
84 if (state == net::ERR_IO_PENDING)
85 return; // IO has started.
86 if (state < 0)
87 return; // ERROR!
88 OnReadComplete(state);
91 void OnReadComplete(int result) {
92 if (result == 0) {
93 OnRequestComplete(result);
94 return;
97 // Deal with received data here.
98 base::StatsCounter bytes_read("FetchClient.bytes_read");
99 bytes_read.Add(result);
101 // Issue a read for more data.
102 int state = transaction_->Read(
103 buffer_.get(), kBufferSize,
104 base::Bind(&Client::OnReadComplete, base::Unretained(this)));
105 if (state == net::ERR_IO_PENDING)
106 return; // IO has started.
107 if (state < 0)
108 return; // ERROR!
109 OnReadComplete(state);
112 void OnRequestComplete(int result) {
113 base::StatsCounter requests("FetchClient.requests");
114 requests.Increment();
115 g_driver.Get().ClientStopped();
116 printf(".");
119 static const int kBufferSize = (16 * 1024);
120 GURL url_;
121 net::HttpRequestInfo request_info_;
122 scoped_ptr<net::HttpTransaction> transaction_;
123 scoped_refptr<net::IOBuffer> buffer_;
126 int main(int argc, char** argv) {
127 base::AtExitManager exit;
128 base::StatsTable table("fetchclient", 50, 1000);
129 table.set_current(&table);
131 CommandLine::Init(argc, argv);
132 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
133 std::string url = parsed_command_line.GetSwitchValueASCII("url");
134 if (!url.length())
135 usage(argv[0]);
136 int client_limit = 1;
137 if (parsed_command_line.HasSwitch("n")) {
138 base::StringToInt(parsed_command_line.GetSwitchValueASCII("n"),
139 &client_limit);
141 bool use_cache = parsed_command_line.HasSwitch("use-cache");
143 // Do work here.
144 base::MessageLoop loop(base::MessageLoop::TYPE_IO);
146 scoped_ptr<net::HostResolver> host_resolver(
147 net::HostResolver::CreateDefaultResolver(NULL));
148 scoped_ptr<net::CertVerifier> cert_verifier(
149 net::CertVerifier::CreateDefault());
150 scoped_ptr<net::TransportSecurityState> transport_security_state(
151 new net::TransportSecurityState);
152 scoped_ptr<net::ProxyService> proxy_service(
153 net::ProxyService::CreateDirect());
154 scoped_refptr<net::SSLConfigService> ssl_config_service(
155 new net::SSLConfigServiceDefaults);
156 net::HttpTransactionFactory* factory = NULL;
157 scoped_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory(
158 net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
159 net::HttpServerPropertiesImpl http_server_properties;
161 net::HttpNetworkSession::Params session_params;
162 session_params.host_resolver = host_resolver.get();
163 session_params.cert_verifier = cert_verifier.get();
164 session_params.transport_security_state = transport_security_state.get();
165 session_params.proxy_service = proxy_service.get();
166 session_params.http_auth_handler_factory = http_auth_handler_factory.get();
167 session_params.http_server_properties = http_server_properties.GetWeakPtr();
168 session_params.ssl_config_service = ssl_config_service.get();
170 scoped_refptr<net::HttpNetworkSession> network_session(
171 new net::HttpNetworkSession(session_params));
172 if (use_cache) {
173 factory = new net::HttpCache(network_session.get(),
174 net::HttpCache::DefaultBackend::InMemory(0));
175 } else {
176 factory = new net::HttpNetworkLayer(network_session.get());
180 base::StatsCounterTimer driver_time("FetchClient.total_time");
181 base::StatsScope<base::StatsCounterTimer> scope(driver_time);
183 Client** clients = new Client*[client_limit];
184 for (int i = 0; i < client_limit; i++)
185 clients[i] = new Client(factory, url);
187 base::MessageLoop::current()->Run();
190 // Print Statistics here.
191 int num_clients = table.GetCounterValue("c:FetchClient.requests");
192 int test_time = table.GetCounterValue("t:FetchClient.total_time");
193 int bytes_read = table.GetCounterValue("c:FetchClient.bytes_read");
195 printf("\n");
196 printf("Clients : %d\n", num_clients);
197 printf("Time : %dms\n", test_time);
198 printf("Bytes Read : %d\n", bytes_read);
199 if (test_time > 0) {
200 const char *units = "bps";
201 double bps = static_cast<float>(bytes_read * 8) /
202 (static_cast<float>(test_time) / 1000.0);
204 if (bps > (1024*1024)) {
205 bps /= (1024*1024);
206 units = "Mbps";
207 } else if (bps > 1024) {
208 bps /= 1024;
209 units = "Kbps";
211 printf("Bandwidth : %.2f%s\n", bps, units);
214 if (parsed_command_line.HasSwitch("stats")) {
215 // Dump the stats table.
216 printf("<stats>\n");
217 int counter_max = table.GetMaxCounters();
218 for (int index = 0; index < counter_max; index++) {
219 std::string name(table.GetRowName(index));
220 if (name.length() > 0) {
221 int value = table.GetRowValue(index);
222 printf("%s:\t%d\n", name.c_str(), value);
225 printf("</stats>\n");
227 return 0;