[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / net / tools / quic / test_tools / quic_test_client.cc
blob35e754770b98c604fe9520982eb452a0a5a43f67
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 "net/tools/quic/test_tools/quic_test_client.h"
7 #include "base/time/time.h"
8 #include "net/base/completion_callback.h"
9 #include "net/base/net_errors.h"
10 #include "net/cert/cert_verify_result.h"
11 #include "net/cert/x509_certificate.h"
12 #include "net/quic/crypto/proof_verifier.h"
13 #include "net/quic/quic_server_id.h"
14 #include "net/quic/test_tools/quic_connection_peer.h"
15 #include "net/quic/test_tools/quic_session_peer.h"
16 #include "net/quic/test_tools/quic_test_utils.h"
17 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
18 #include "net/tools/balsa/balsa_headers.h"
19 #include "net/tools/quic/quic_epoll_connection_helper.h"
20 #include "net/tools/quic/quic_packet_writer_wrapper.h"
21 #include "net/tools/quic/quic_spdy_client_stream.h"
22 #include "net/tools/quic/spdy_balsa_utils.h"
23 #include "net/tools/quic/test_tools/http_message.h"
24 #include "net/tools/quic/test_tools/quic_client_peer.h"
25 #include "url/gurl.h"
27 using base::StringPiece;
28 using net::QuicServerId;
29 using net::test::QuicConnectionPeer;
30 using net::test::QuicSessionPeer;
31 using net::test::ReliableQuicStreamPeer;
32 using std::string;
33 using std::vector;
35 namespace net {
36 namespace tools {
37 namespace test {
38 namespace {
40 // RecordingProofVerifier accepts any certificate chain and records the common
41 // name of the leaf.
42 class RecordingProofVerifier : public ProofVerifier {
43 public:
44 // ProofVerifier interface.
45 QuicAsyncStatus VerifyProof(const string& hostname,
46 const string& server_config,
47 const vector<string>& certs,
48 const string& signature,
49 const ProofVerifyContext* context,
50 string* error_details,
51 scoped_ptr<ProofVerifyDetails>* details,
52 ProofVerifierCallback* callback) override {
53 common_name_.clear();
54 if (certs.empty()) {
55 return QUIC_FAILURE;
58 // Convert certs to X509Certificate.
59 vector<StringPiece> cert_pieces(certs.size());
60 for (unsigned i = 0; i < certs.size(); i++) {
61 cert_pieces[i] = StringPiece(certs[i]);
63 scoped_refptr<net::X509Certificate> cert =
64 net::X509Certificate::CreateFromDERCertChain(cert_pieces);
65 if (!cert.get()) {
66 return QUIC_FAILURE;
69 common_name_ = cert->subject().GetDisplayName();
70 return QUIC_SUCCESS;
73 const string& common_name() const { return common_name_; }
75 private:
76 string common_name_;
79 } // anonymous namespace
81 BalsaHeaders* MungeHeaders(const BalsaHeaders* const_headers,
82 bool secure) {
83 StringPiece uri = const_headers->request_uri();
84 if (uri.empty()) {
85 return nullptr;
87 if (const_headers->request_method() == "CONNECT") {
88 return nullptr;
90 BalsaHeaders* headers = new BalsaHeaders;
91 headers->CopyFrom(*const_headers);
92 if (!uri.starts_with("https://") &&
93 !uri.starts_with("http://")) {
94 // If we have a relative URL, set some defaults.
95 string full_uri = secure ? "https://www.google.com" :
96 "http://www.google.com";
97 full_uri.append(uri.as_string());
98 headers->SetRequestUri(full_uri);
100 return headers;
103 MockableQuicClient::MockableQuicClient(
104 IPEndPoint server_address,
105 const QuicServerId& server_id,
106 const QuicVersionVector& supported_versions,
107 EpollServer* epoll_server)
108 : QuicClient(server_address,
109 server_id,
110 supported_versions,
111 epoll_server),
112 override_connection_id_(0),
113 test_writer_(nullptr) {}
115 MockableQuicClient::MockableQuicClient(
116 IPEndPoint server_address,
117 const QuicServerId& server_id,
118 const QuicConfig& config,
119 const QuicVersionVector& supported_versions,
120 EpollServer* epoll_server)
121 : QuicClient(server_address,
122 server_id,
123 supported_versions,
124 config,
125 epoll_server),
126 override_connection_id_(0),
127 test_writer_(nullptr) {}
129 MockableQuicClient::~MockableQuicClient() {
130 if (connected()) {
131 Disconnect();
135 QuicPacketWriter* MockableQuicClient::CreateQuicPacketWriter() {
136 QuicPacketWriter* writer = QuicClient::CreateQuicPacketWriter();
137 if (!test_writer_) {
138 return writer;
140 test_writer_->set_writer(writer);
141 return test_writer_;
144 QuicConnectionId MockableQuicClient::GenerateConnectionId() {
145 return override_connection_id_ ? override_connection_id_
146 : QuicClient::GenerateConnectionId();
149 // Takes ownership of writer.
150 void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) {
151 CHECK(test_writer_ == nullptr);
152 test_writer_ = writer;
155 void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) {
156 override_connection_id_ = connection_id;
159 QuicTestClient::QuicTestClient(IPEndPoint server_address,
160 const string& server_hostname,
161 bool secure,
162 const QuicVersionVector& supported_versions)
163 : client_(new MockableQuicClient(server_address,
164 QuicServerId(server_hostname,
165 server_address.port(),
166 secure,
167 PRIVACY_MODE_DISABLED),
168 supported_versions,
169 &epoll_server_)) {
170 Initialize(secure);
173 QuicTestClient::QuicTestClient(
174 IPEndPoint server_address,
175 const string& server_hostname,
176 bool secure,
177 const QuicConfig& config,
178 const QuicVersionVector& supported_versions)
179 : client_(
180 new MockableQuicClient(server_address,
181 QuicServerId(server_hostname,
182 server_address.port(),
183 secure,
184 PRIVACY_MODE_DISABLED),
185 config,
186 supported_versions,
187 &epoll_server_)) {
188 Initialize(secure);
191 QuicTestClient::QuicTestClient() {
194 QuicTestClient::~QuicTestClient() {
195 if (stream_) {
196 stream_->set_visitor(nullptr);
200 void QuicTestClient::Initialize(bool secure) {
201 priority_ = 3;
202 connect_attempted_ = false;
203 secure_ = secure;
204 auto_reconnect_ = false;
205 buffer_body_ = true;
206 fec_policy_ = FEC_PROTECT_OPTIONAL;
207 proof_verifier_ = nullptr;
208 ClearPerRequestState();
209 ExpectCertificates(secure_);
210 // As chrome will generally do this, we want it to be the default when it's
211 // not overridden.
212 if (!client_->config()->HasSetBytesForConnectionIdToSend()) {
213 client_->config()->SetBytesForConnectionIdToSend(0);
217 void QuicTestClient::ExpectCertificates(bool on) {
218 if (on) {
219 proof_verifier_ = new RecordingProofVerifier;
220 client_->SetProofVerifier(proof_verifier_);
221 } else {
222 proof_verifier_ = nullptr;
223 client_->SetProofVerifier(nullptr);
227 void QuicTestClient::SetUserAgentID(const string& user_agent_id) {
228 client_->SetUserAgentID(user_agent_id);
231 ssize_t QuicTestClient::SendRequest(const string& uri) {
232 HTTPMessage message(HttpConstants::HTTP_1_1,
233 HttpConstants::GET,
234 uri);
235 return SendMessage(message);
238 ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) {
239 stream_ = nullptr; // Always force creation of a stream for SendMessage.
241 // If we're not connected, try to find an sni hostname.
242 if (!connected()) {
243 GURL url(message.headers()->request_uri().as_string());
244 if (!url.host().empty()) {
245 client_->set_server_id(
246 QuicServerId(url.host(),
247 url.EffectiveIntPort(),
248 url.SchemeIs("https"),
249 PRIVACY_MODE_DISABLED));
253 QuicSpdyClientStream* stream = GetOrCreateStream();
254 if (!stream) { return 0; }
256 scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(),
257 secure_));
258 ssize_t ret = GetOrCreateStream()->SendRequest(
259 SpdyBalsaUtils::RequestHeadersToSpdyHeaders(
260 munged_headers.get() ? *munged_headers : *message.headers(),
261 stream->version()),
262 message.body(), message.has_complete_message());
263 WaitForWriteToFlush();
264 return ret;
267 ssize_t QuicTestClient::SendData(string data, bool last_data) {
268 return SendData(data, last_data, nullptr);
271 ssize_t QuicTestClient::SendData(string data,
272 bool last_data,
273 QuicAckNotifier::DelegateInterface* delegate) {
274 QuicSpdyClientStream* stream = GetOrCreateStream();
275 if (!stream) { return 0; }
276 GetOrCreateStream()->SendBody(data, last_data, delegate);
277 WaitForWriteToFlush();
278 return data.length();
281 bool QuicTestClient::response_complete() const {
282 return response_complete_;
285 int QuicTestClient::response_header_size() const {
286 return response_header_size_;
289 int64 QuicTestClient::response_body_size() const {
290 return response_body_size_;
293 bool QuicTestClient::buffer_body() const {
294 return buffer_body_;
297 void QuicTestClient::set_buffer_body(bool buffer_body) {
298 buffer_body_ = buffer_body;
301 bool QuicTestClient::ServerInLameDuckMode() const {
302 return false;
305 const string& QuicTestClient::response_body() {
306 return response_;
309 string QuicTestClient::SendCustomSynchronousRequest(
310 const HTTPMessage& message) {
311 SendMessage(message);
312 WaitForResponse();
313 return response_;
316 string QuicTestClient::SendSynchronousRequest(const string& uri) {
317 if (SendRequest(uri) == 0) {
318 DLOG(ERROR) << "Failed the request for uri:" << uri;
319 return "";
321 WaitForResponse();
322 return response_;
325 QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
326 if (!connect_attempted_ || auto_reconnect_) {
327 if (!connected()) {
328 Connect();
330 if (!connected()) {
331 return nullptr;
334 if (!stream_) {
335 stream_ = client_->CreateReliableClientStream();
336 if (stream_ == nullptr) {
337 return nullptr;
339 stream_->set_visitor(this);
340 reinterpret_cast<QuicSpdyClientStream*>(stream_)->set_priority(priority_);
341 // Set FEC policy on stream.
342 ReliableQuicStreamPeer::SetFecPolicy(stream_, fec_policy_);
345 return stream_;
348 QuicErrorCode QuicTestClient::connection_error() {
349 return client()->session()->error();
352 MockableQuicClient* QuicTestClient::client() { return client_.get(); }
354 const string& QuicTestClient::cert_common_name() const {
355 return reinterpret_cast<RecordingProofVerifier*>(proof_verifier_)
356 ->common_name();
359 QuicTagValueMap QuicTestClient::GetServerConfig() const {
360 QuicCryptoClientConfig* config =
361 QuicClientPeer::GetCryptoConfig(client_.get());
362 QuicCryptoClientConfig::CachedState* state =
363 config->LookupOrCreate(client_->server_id());
364 const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig();
365 if (handshake_msg != nullptr) {
366 return handshake_msg->tag_value_map();
367 } else {
368 return QuicTagValueMap();
372 bool QuicTestClient::connected() const {
373 return client_->connected();
376 void QuicTestClient::Connect() {
377 DCHECK(!connected());
378 if (!connect_attempted_) {
379 client_->Initialize();
381 client_->Connect();
382 connect_attempted_ = true;
385 void QuicTestClient::ResetConnection() {
386 Disconnect();
387 Connect();
390 void QuicTestClient::Disconnect() {
391 client_->Disconnect();
392 connect_attempted_ = false;
395 IPEndPoint QuicTestClient::LocalSocketAddress() const {
396 return client_->client_address();
399 void QuicTestClient::ClearPerRequestState() {
400 stream_error_ = QUIC_STREAM_NO_ERROR;
401 stream_ = nullptr;
402 response_ = "";
403 response_complete_ = false;
404 response_headers_complete_ = false;
405 headers_.Clear();
406 bytes_read_ = 0;
407 bytes_written_ = 0;
408 response_header_size_ = 0;
409 response_body_size_ = 0;
412 void QuicTestClient::WaitForResponseForMs(int timeout_ms) {
413 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
414 int64 old_timeout_us = epoll_server()->timeout_in_us();
415 if (timeout_us > 0) {
416 epoll_server()->set_timeout_in_us(timeout_us);
418 const QuicClock* clock =
419 QuicConnectionPeer::GetHelper(client()->session()->connection())->
420 GetClock();
421 QuicTime end_waiting_time = clock->Now().Add(
422 QuicTime::Delta::FromMicroseconds(timeout_us));
423 while (stream_ != nullptr &&
424 !client_->session()->IsClosedStream(stream_->id()) &&
425 (timeout_us < 0 || clock->Now() < end_waiting_time)) {
426 client_->WaitForEvents();
428 if (timeout_us > 0) {
429 epoll_server()->set_timeout_in_us(old_timeout_us);
433 void QuicTestClient::WaitForInitialResponseForMs(int timeout_ms) {
434 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
435 int64 old_timeout_us = epoll_server()->timeout_in_us();
436 if (timeout_us > 0) {
437 epoll_server()->set_timeout_in_us(timeout_us);
439 const QuicClock* clock =
440 QuicConnectionPeer::GetHelper(client()->session()->connection())->
441 GetClock();
442 QuicTime end_waiting_time = clock->Now().Add(
443 QuicTime::Delta::FromMicroseconds(timeout_us));
444 while (stream_ != nullptr &&
445 !client_->session()->IsClosedStream(stream_->id()) &&
446 stream_->stream_bytes_read() == 0 &&
447 (timeout_us < 0 || clock->Now() < end_waiting_time)) {
448 client_->WaitForEvents();
450 if (timeout_us > 0) {
451 epoll_server()->set_timeout_in_us(old_timeout_us);
455 ssize_t QuicTestClient::Send(const void *buffer, size_t size) {
456 return SendData(string(static_cast<const char*>(buffer), size), false);
459 bool QuicTestClient::response_headers_complete() const {
460 if (stream_ != nullptr) {
461 return stream_->headers_decompressed();
463 return response_headers_complete_;
466 const BalsaHeaders* QuicTestClient::response_headers() const {
467 if (stream_ != nullptr) {
468 SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_,
469 stream_->version());
470 return &headers_;
471 } else {
472 return &headers_;
476 int64 QuicTestClient::response_size() const {
477 return bytes_read_;
480 size_t QuicTestClient::bytes_read() const {
481 return bytes_read_;
484 size_t QuicTestClient::bytes_written() const {
485 return bytes_written_;
488 void QuicTestClient::OnClose(QuicDataStream* stream) {
489 if (stream_ != stream) {
490 return;
492 if (buffer_body()) {
493 // TODO(fnk): The stream still buffers the whole thing. Fix that.
494 response_ = stream_->data();
496 response_complete_ = true;
497 response_headers_complete_ = stream_->headers_decompressed();
498 SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_,
499 stream_->version());
500 stream_error_ = stream_->stream_error();
501 bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
502 bytes_written_ =
503 stream_->stream_bytes_written() + stream_->header_bytes_written();
504 response_header_size_ = headers_.GetSizeForWriteBuffer();
505 response_body_size_ = stream_->data().size();
506 stream_ = nullptr;
509 void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
510 client_->UseWriter(writer);
513 void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) {
514 DCHECK(!connected());
515 client_->UseConnectionId(connection_id);
518 ssize_t QuicTestClient::SendAndWaitForResponse(const void *buffer,
519 size_t size) {
520 LOG(DFATAL) << "Not implemented";
521 return 0;
524 void QuicTestClient::Bind(IPEndPoint* local_address) {
525 DLOG(WARNING) << "Bind will be done during connect";
528 string QuicTestClient::SerializeMessage(const HTTPMessage& message) {
529 LOG(DFATAL) << "Not implemented";
530 return "";
533 IPAddressNumber QuicTestClient::bind_to_address() const {
534 return client_->bind_to_address();
537 void QuicTestClient::set_bind_to_address(IPAddressNumber address) {
538 client_->set_bind_to_address(address);
541 const IPEndPoint& QuicTestClient::address() const {
542 LOG(DFATAL) << "Not implemented";
543 return client_->server_address();
546 size_t QuicTestClient::requests_sent() const {
547 LOG(DFATAL) << "Not implemented";
548 return 0;
551 void QuicTestClient::WaitForWriteToFlush() {
552 while (connected() && client()->session()->HasDataToWrite()) {
553 client_->WaitForEvents();
557 void QuicTestClient::SetFecPolicy(FecPolicy fec_policy) {
558 fec_policy_ = fec_policy;
559 // Set policy for headers and crypto streams.
560 ReliableQuicStreamPeer::SetFecPolicy(
561 QuicSessionPeer::GetHeadersStream(client()->session()), fec_policy);
562 ReliableQuicStreamPeer::SetFecPolicy(client()->session()->GetCryptoStream(),
563 fec_policy);
566 } // namespace test
567 } // namespace tools
568 } // namespace net