xref: /aosp_15_r20/external/cronet/net/http/http_transaction_test_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 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 "net/http/http_transaction_test_util.h"
6 
7 #include <algorithm>
8 #include <unordered_map>
9 #include <utility>
10 
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/location.h"
14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/time/clock.h"
18 #include "base/time/time.h"
19 #include "net/base/ip_address.h"
20 #include "net/base/ip_endpoint.h"
21 #include "net/base/load_flags.h"
22 #include "net/base/load_timing_info.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/network_isolation_key.h"
25 #include "net/base/schemeful_site.h"
26 #include "net/cert/x509_certificate.h"
27 #include "net/disk_cache/disk_cache.h"
28 #include "net/http/http_cache.h"
29 #include "net/http/http_request_info.h"
30 #include "net/http/http_response_info.h"
31 #include "net/http/http_transaction.h"
32 #include "net/log/net_log.h"
33 #include "net/log/net_log_source.h"
34 #include "net/ssl/ssl_private_key.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "url/gurl.h"
37 
38 namespace net {
39 
40 namespace {
41 using MockTransactionMap =
42     std::unordered_map<std::string, const MockTransaction*>;
43 static MockTransactionMap mock_transactions;
44 
AddMockTransaction(const MockTransaction * trans)45 void AddMockTransaction(const MockTransaction* trans) {
46   auto result =
47       mock_transactions.insert(std::make_pair(GURL(trans->url).spec(), trans));
48   CHECK(result.second) << "Transaction already exists: " << trans->url;
49 }
50 
RemoveMockTransaction(const MockTransaction * trans)51 void RemoveMockTransaction(const MockTransaction* trans) {
52   mock_transactions.erase(GURL(trans->url).spec());
53 }
54 
55 }  // namespace
56 
DefaultTransportInfo()57 TransportInfo DefaultTransportInfo() {
58   return TransportInfo(TransportType::kDirect,
59                        IPEndPoint(IPAddress::IPv4Localhost(), 80),
60                        /*accept_ch_frame_arg=*/"",
61                        /*cert_is_issued_by_known_root=*/false, kProtoUnknown);
62 }
63 
64 //-----------------------------------------------------------------------------
65 // mock transaction data
66 
67 const MockTransaction kSimpleGET_Transaction = {
68     "http://www.google.com/",
69     "GET",
70     base::Time(),
71     "",
72     LOAD_NORMAL,
73     DefaultTransportInfo(),
74     "HTTP/1.1 200 OK",
75     "Cache-Control: max-age=10000\n",
76     base::Time(),
77     "<html><body>Google Blah Blah</body></html>",
78     {},
79     std::nullopt,
80     std::nullopt,
81     TEST_MODE_NORMAL,
82     MockTransactionHandler(),
83     MockTransactionReadHandler(),
84     nullptr,
85     0,
86     0,
87     OK,
88     OK,
89 };
90 
91 const MockTransaction kSimplePOST_Transaction = {
92     "http://bugdatabase.com/edit",
93     "POST",
94     base::Time(),
95     "",
96     LOAD_NORMAL,
97     DefaultTransportInfo(),
98     "HTTP/1.1 200 OK",
99     "",
100     base::Time(),
101     "<html><body>Google Blah Blah</body></html>",
102     {},
103     std::nullopt,
104     std::nullopt,
105     TEST_MODE_NORMAL,
106     MockTransactionHandler(),
107     MockTransactionReadHandler(),
108     nullptr,
109     0,
110     0,
111     OK,
112     OK,
113 };
114 
115 const MockTransaction kTypicalGET_Transaction = {
116     "http://www.example.com/~foo/bar.html",
117     "GET",
118     base::Time(),
119     "",
120     LOAD_NORMAL,
121     DefaultTransportInfo(),
122     "HTTP/1.1 200 OK",
123     "Date: Wed, 28 Nov 2007 09:40:09 GMT\n"
124     "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n",
125     base::Time(),
126     "<html><body>Google Blah Blah</body></html>",
127     {},
128     std::nullopt,
129     std::nullopt,
130     TEST_MODE_NORMAL,
131     MockTransactionHandler(),
132     MockTransactionReadHandler(),
133     nullptr,
134     0,
135     0,
136     OK,
137     OK,
138 };
139 
140 const MockTransaction kETagGET_Transaction = {
141     "http://www.google.com/foopy",
142     "GET",
143     base::Time(),
144     "",
145     LOAD_NORMAL,
146     DefaultTransportInfo(),
147     "HTTP/1.1 200 OK",
148     "Cache-Control: max-age=10000\n"
149     "Etag: \"foopy\"\n",
150     base::Time(),
151     "<html><body>Google Blah Blah</body></html>",
152     {},
153     std::nullopt,
154     std::nullopt,
155     TEST_MODE_NORMAL,
156     MockTransactionHandler(),
157     MockTransactionReadHandler(),
158     nullptr,
159     0,
160     0,
161     OK,
162     OK,
163 };
164 
165 const MockTransaction kRangeGET_Transaction = {
166     "http://www.google.com/",
167     "GET",
168     base::Time(),
169     "Range: 0-100\r\n",
170     LOAD_NORMAL,
171     DefaultTransportInfo(),
172     "HTTP/1.1 200 OK",
173     "Cache-Control: max-age=10000\n",
174     base::Time(),
175     "<html><body>Google Blah Blah</body></html>",
176     {},
177     std::nullopt,
178     std::nullopt,
179     TEST_MODE_NORMAL,
180     MockTransactionHandler(),
181     MockTransactionReadHandler(),
182     nullptr,
183     0,
184     0,
185     OK,
186     OK,
187 };
188 
189 static const MockTransaction* const kBuiltinMockTransactions[] = {
190   &kSimpleGET_Transaction,
191   &kSimplePOST_Transaction,
192   &kTypicalGET_Transaction,
193   &kETagGET_Transaction,
194   &kRangeGET_Transaction
195 };
196 
FindMockTransaction(const GURL & url)197 const MockTransaction* FindMockTransaction(const GURL& url) {
198   // look for overrides:
199   MockTransactionMap::const_iterator it = mock_transactions.find(url.spec());
200   if (it != mock_transactions.end())
201     return it->second;
202 
203   // look for builtins:
204   for (const auto* transaction : kBuiltinMockTransactions) {
205     if (url == GURL(transaction->url))
206       return transaction;
207   }
208   return nullptr;
209 }
210 
ScopedMockTransaction(const char * url)211 ScopedMockTransaction::ScopedMockTransaction(const char* url)
212     : MockTransaction({nullptr}) {
213   CHECK(url);
214   this->url = url;
215   AddMockTransaction(this);
216 }
217 
ScopedMockTransaction(const MockTransaction & t,const char * url)218 ScopedMockTransaction::ScopedMockTransaction(const MockTransaction& t,
219                                              const char* url)
220     : MockTransaction(t) {
221   if (url) {
222     this->url = url;
223   }
224   AddMockTransaction(this);
225 }
226 
~ScopedMockTransaction()227 ScopedMockTransaction::~ScopedMockTransaction() {
228   RemoveMockTransaction(this);
229 }
230 
MockHttpRequest(const MockTransaction & t)231 MockHttpRequest::MockHttpRequest(const MockTransaction& t) {
232   url = GURL(t.url);
233   method = t.method;
234   extra_headers.AddHeadersFromString(t.request_headers);
235   load_flags = t.load_flags;
236   SchemefulSite site(url);
237   network_isolation_key = NetworkIsolationKey(site, site);
238   network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(site);
239   frame_origin = url::Origin::Create(url);
240   fps_cache_filter = t.fps_cache_filter;
241   browser_run_id = t.browser_run_id;
242 }
243 
CacheKey()244 std::string MockHttpRequest::CacheKey() {
245   return *HttpCache::GenerateCacheKeyForRequest(this);
246 }
247 
248 //-----------------------------------------------------------------------------
249 
TestTransactionConsumer(RequestPriority priority,HttpTransactionFactory * factory)250 TestTransactionConsumer::TestTransactionConsumer(
251     RequestPriority priority,
252     HttpTransactionFactory* factory) {
253   // Disregard the error code.
254   factory->CreateTransaction(priority, &trans_);
255 }
256 
257 TestTransactionConsumer::~TestTransactionConsumer() = default;
258 
Start(const HttpRequestInfo * request,const NetLogWithSource & net_log)259 void TestTransactionConsumer::Start(const HttpRequestInfo* request,
260                                     const NetLogWithSource& net_log) {
261   state_ = State::kStarting;
262   int result =
263       trans_->Start(request,
264                     base::BindOnce(&TestTransactionConsumer::OnIOComplete,
265                                    base::Unretained(this)),
266                     net_log);
267   if (result != ERR_IO_PENDING)
268     DidStart(result);
269 
270   base::RunLoop loop;
271   quit_closure_ = loop.QuitClosure();
272   loop.Run();
273 }
274 
DidStart(int result)275 void TestTransactionConsumer::DidStart(int result) {
276   if (result != OK) {
277     DidFinish(result);
278   } else {
279     Read();
280   }
281 }
282 
DidRead(int result)283 void TestTransactionConsumer::DidRead(int result) {
284   if (result <= 0) {
285     DidFinish(result);
286   } else {
287     content_.append(read_buf_->data(), result);
288     Read();
289   }
290 }
291 
DidFinish(int result)292 void TestTransactionConsumer::DidFinish(int result) {
293   state_ = State::kDone;
294   error_ = result;
295   if (!quit_closure_.is_null()) {
296     std::move(quit_closure_).Run();
297   }
298 }
299 
Read()300 void TestTransactionConsumer::Read() {
301   state_ = State::kReading;
302   read_buf_ = base::MakeRefCounted<IOBufferWithSize>(1024);
303   int result =
304       trans_->Read(read_buf_.get(), 1024,
305                    base::BindOnce(&TestTransactionConsumer::OnIOComplete,
306                                   base::Unretained(this)));
307   if (result != ERR_IO_PENDING)
308     DidRead(result);
309 }
310 
OnIOComplete(int result)311 void TestTransactionConsumer::OnIOComplete(int result) {
312   switch (state_) {
313     case State::kStarting:
314       DidStart(result);
315       break;
316     case State::kReading:
317       DidRead(result);
318       break;
319     default:
320       NOTREACHED();
321   }
322 }
323 
MockNetworkTransaction(RequestPriority priority,MockNetworkLayer * factory)324 MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority,
325                                                MockNetworkLayer* factory)
326     : priority_(priority), transaction_factory_(factory->AsWeakPtr()) {}
327 
~MockNetworkTransaction()328 MockNetworkTransaction::~MockNetworkTransaction() {
329   // Use `original_request_ptr_` as in ~HttpNetworkTransaction to make sure its
330   // valid and not already freed by the consumer. Only check till Read is
331   // invoked since HttpNetworkTransaction sets request_ to nullptr when Read is
332   // invoked. See crbug.com/734037.
333   if (original_request_ptr_ && !reading_) {
334     DCHECK(original_request_ptr_->load_flags >= 0);
335   }
336 }
337 
Start(const HttpRequestInfo * request,CompletionOnceCallback callback,const NetLogWithSource & net_log)338 int MockNetworkTransaction::Start(const HttpRequestInfo* request,
339                                   CompletionOnceCallback callback,
340                                   const NetLogWithSource& net_log) {
341   net_log_ = net_log;
342   CHECK(!original_request_ptr_);
343   original_request_ptr_ = request;
344   return StartInternal(*request, std::move(callback));
345 }
346 
RestartIgnoringLastError(CompletionOnceCallback callback)347 int MockNetworkTransaction::RestartIgnoringLastError(
348     CompletionOnceCallback callback) {
349   return ERR_FAILED;
350 }
351 
RestartWithCertificate(scoped_refptr<X509Certificate> client_cert,scoped_refptr<SSLPrivateKey> client_private_key,CompletionOnceCallback callback)352 int MockNetworkTransaction::RestartWithCertificate(
353     scoped_refptr<X509Certificate> client_cert,
354     scoped_refptr<SSLPrivateKey> client_private_key,
355     CompletionOnceCallback callback) {
356   return ERR_FAILED;
357 }
358 
RestartWithAuth(const AuthCredentials & credentials,CompletionOnceCallback callback)359 int MockNetworkTransaction::RestartWithAuth(const AuthCredentials& credentials,
360                                             CompletionOnceCallback callback) {
361   if (!IsReadyToRestartForAuth())
362     return ERR_FAILED;
363 
364   HttpRequestInfo auth_request_info = *original_request_ptr_;
365   auth_request_info.extra_headers.SetHeader("Authorization", "Bar");
366 
367   // Let the MockTransactionHandler worry about this: the only way for this
368   // test to succeed is by using an explicit handler for the transaction so
369   // that server behavior can be simulated.
370   return StartInternal(std::move(auth_request_info), std::move(callback));
371 }
372 
PopulateNetErrorDetails(NetErrorDetails *) const373 void MockNetworkTransaction::PopulateNetErrorDetails(
374     NetErrorDetails* /*details*/) const {
375   NOTIMPLEMENTED();
376 }
377 
IsReadyToRestartForAuth()378 bool MockNetworkTransaction::IsReadyToRestartForAuth() {
379   CHECK(original_request_ptr_);
380   if (!original_request_ptr_->extra_headers.HasHeader("X-Require-Mock-Auth")) {
381     return false;
382   }
383 
384   // Allow the mock server to decide whether authentication is required or not.
385   std::string status_line = response_.headers->GetStatusLine();
386   return status_line.find(" 401 ") != std::string::npos ||
387       status_line.find(" 407 ") != std::string::npos;
388 }
389 
Read(net::IOBuffer * buf,int buf_len,CompletionOnceCallback callback)390 int MockNetworkTransaction::Read(net::IOBuffer* buf,
391                                  int buf_len,
392                                  CompletionOnceCallback callback) {
393   const MockTransaction* t = FindMockTransaction(current_request_.url);
394   DCHECK(t);
395 
396   CHECK(!done_reading_called_);
397   reading_ = true;
398 
399   int num = t->read_return_code;
400 
401   if (OK == num) {
402     if (t->read_handler) {
403       num = t->read_handler.Run(content_length_, data_cursor_, buf, buf_len);
404       data_cursor_ += num;
405     } else {
406       int data_len = static_cast<int>(data_.size());
407       num = std::min(static_cast<int64_t>(buf_len), data_len - data_cursor_);
408       if (test_mode_ & TEST_MODE_SLOW_READ)
409         num = std::min(num, 1);
410       if (num) {
411         memcpy(buf->data(), data_.data() + data_cursor_, num);
412         data_cursor_ += num;
413       }
414     }
415   }
416 
417   if (test_mode_ & TEST_MODE_SYNC_NET_READ)
418     return num;
419 
420   CallbackLater(std::move(callback), num);
421   return ERR_IO_PENDING;
422 }
423 
StopCaching()424 void MockNetworkTransaction::StopCaching() {
425   if (transaction_factory_.get())
426     transaction_factory_->TransactionStopCaching();
427 }
428 
GetTotalReceivedBytes() const429 int64_t MockNetworkTransaction::GetTotalReceivedBytes() const {
430   return received_bytes_;
431 }
432 
GetTotalSentBytes() const433 int64_t MockNetworkTransaction::GetTotalSentBytes() const {
434   return sent_bytes_;
435 }
436 
DoneReading()437 void MockNetworkTransaction::DoneReading() {
438   CHECK(!done_reading_called_);
439   done_reading_called_ = true;
440   if (transaction_factory_.get())
441     transaction_factory_->TransactionDoneReading();
442 }
443 
GetResponseInfo() const444 const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const {
445   return &response_;
446 }
447 
GetLoadState() const448 LoadState MockNetworkTransaction::GetLoadState() const {
449   if (data_cursor_)
450     return LOAD_STATE_READING_RESPONSE;
451   return LOAD_STATE_IDLE;
452 }
453 
SetQuicServerInfo(QuicServerInfo * quic_server_info)454 void MockNetworkTransaction::SetQuicServerInfo(
455     QuicServerInfo* quic_server_info) {
456 }
457 
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const458 bool MockNetworkTransaction::GetLoadTimingInfo(
459     LoadTimingInfo* load_timing_info) const {
460   if (socket_log_id_ != NetLogSource::kInvalidId) {
461     // The minimal set of times for a request that gets a response, assuming it
462     // gets a new socket.
463     load_timing_info->socket_reused = false;
464     load_timing_info->socket_log_id = socket_log_id_;
465     load_timing_info->connect_timing.connect_start = base::TimeTicks::Now();
466     load_timing_info->connect_timing.connect_end = base::TimeTicks::Now();
467     load_timing_info->send_start = base::TimeTicks::Now();
468     load_timing_info->send_end = base::TimeTicks::Now();
469   } else {
470     // If there's no valid socket ID, just use the generic socket reused values.
471     // No tests currently depend on this, just should not match the values set
472     // by a cache hit.
473     load_timing_info->socket_reused = true;
474     load_timing_info->send_start = base::TimeTicks::Now();
475     load_timing_info->send_end = base::TimeTicks::Now();
476   }
477   return true;
478 }
479 
GetRemoteEndpoint(IPEndPoint * endpoint) const480 bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
481   *endpoint = IPEndPoint(IPAddress(127, 0, 0, 1), 80);
482   return true;
483 }
484 
SetPriority(RequestPriority priority)485 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
486   priority_ = priority;
487 }
488 
SetWebSocketHandshakeStreamCreateHelper(WebSocketHandshakeStreamBase::CreateHelper * create_helper)489 void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
490     WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
491   websocket_handshake_stream_create_helper_ = create_helper;
492 }
493 
494 // static
495 const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000;
496 
497 // static
498 const int64_t MockNetworkTransaction::kTotalSentBytes = 100;
499 
StartInternal(HttpRequestInfo request,CompletionOnceCallback callback)500 int MockNetworkTransaction::StartInternal(HttpRequestInfo request,
501                                           CompletionOnceCallback callback) {
502   current_request_ = std::move(request);
503   const MockTransaction* t = FindMockTransaction(current_request_.url);
504   if (!t) {
505     return ERR_FAILED;
506   }
507   test_mode_ = t->test_mode;
508 
509   // Return immediately if we're returning an error.
510   if (OK != t->start_return_code) {
511     if (test_mode_ & TEST_MODE_SYNC_NET_START) {
512       return t->start_return_code;
513     }
514     CallbackLater(std::move(callback), t->start_return_code);
515     return ERR_IO_PENDING;
516   }
517 
518   next_state_ = State::NOTIFY_BEFORE_CREATE_STREAM;
519   int rv = DoLoop(OK);
520   if (rv == ERR_IO_PENDING) {
521     callback_ = std::move(callback);
522   }
523   return rv;
524 }
525 
DoNotifyBeforeCreateStream()526 int MockNetworkTransaction::DoNotifyBeforeCreateStream() {
527   next_state_ = State::CREATE_STREAM;
528   bool defer = false;
529   if (!before_network_start_callback_.is_null()) {
530     std::move(before_network_start_callback_).Run(&defer);
531   }
532   if (!defer) {
533     return OK;
534   }
535   return ERR_IO_PENDING;
536 }
537 
DoCreateStream()538 int MockNetworkTransaction::DoCreateStream() {
539   next_state_ = State::CREATE_STREAM_COMPLETE;
540   if (test_mode_ & TEST_MODE_SYNC_NET_START) {
541     return OK;
542   }
543   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
544       FROM_HERE, base::BindOnce(&MockNetworkTransaction::OnIOComplete,
545                                 weak_factory_.GetWeakPtr(), OK));
546   return ERR_IO_PENDING;
547 }
548 
DoCreateStreamComplete(int result)549 int MockNetworkTransaction::DoCreateStreamComplete(int result) {
550   // We don't have a logic which simulate stream creation
551   CHECK_EQ(OK, result);
552   next_state_ = State::CONNECTED_CALLBACK;
553   return OK;
554 }
555 
DoConnectedCallback()556 int MockNetworkTransaction::DoConnectedCallback() {
557   next_state_ = State::CONNECTED_CALLBACK_COMPLETE;
558   if (connected_callback_.is_null()) {
559     return OK;
560   }
561 
562   const MockTransaction* t = FindMockTransaction(current_request_.url);
563   CHECK(t);
564   return connected_callback_.Run(
565       t->transport_info, base::BindOnce(&MockNetworkTransaction::OnIOComplete,
566                                         weak_factory_.GetWeakPtr()));
567 }
568 
DoConnectedCallbackComplete(int result)569 int MockNetworkTransaction::DoConnectedCallbackComplete(int result) {
570   if (result != OK) {
571     return result;
572   }
573   next_state_ = State::BUILD_REQUEST;
574   return OK;
575 }
576 
DoBuildRequest()577 int MockNetworkTransaction::DoBuildRequest() {
578   next_state_ = State::BUILD_REQUEST_COMPLETE;
579   if (modify_request_headers_callback_) {
580     modify_request_headers_callback_.Run(&current_request_.extra_headers);
581   }
582   return OK;
583 }
584 
DoBuildRequestComplete(int result)585 int MockNetworkTransaction::DoBuildRequestComplete(int result) {
586   CHECK_EQ(OK, result);
587   next_state_ = State::SEND_REQUEST;
588   return OK;
589 }
590 
DoSendRequest()591 int MockNetworkTransaction::DoSendRequest() {
592   next_state_ = State::SEND_REQUEST_COMPLETE;
593 
594   sent_bytes_ = kTotalSentBytes;
595   received_bytes_ = kTotalReceivedBytes;
596 
597   const MockTransaction* t = FindMockTransaction(current_request_.url);
598   CHECK(t);
599 
600   std::string resp_status = t->status;
601   std::string resp_headers = t->response_headers;
602   std::string resp_data = t->data;
603 
604   if (t->handler) {
605     t->handler.Run(&current_request_, &resp_status, &resp_headers, &resp_data);
606   }
607   std::string header_data =
608       base::StringPrintf("%s\n%s\n", resp_status.c_str(), resp_headers.c_str());
609   std::replace(header_data.begin(), header_data.end(), '\n', '\0');
610 
611   response_.request_time = transaction_factory_->Now();
612   if (!t->request_time.is_null())
613     response_.request_time = t->request_time;
614 
615   response_.was_cached = false;
616   response_.network_accessed = true;
617   response_.remote_endpoint = t->transport_info.endpoint;
618   response_.was_fetched_via_proxy =
619       t->transport_info.type == TransportType::kProxied;
620 
621   response_.response_time = transaction_factory_->Now();
622   if (!t->response_time.is_null())
623     response_.response_time = t->response_time;
624 
625   response_.headers = base::MakeRefCounted<HttpResponseHeaders>(header_data);
626   response_.ssl_info.cert = t->cert;
627   response_.ssl_info.cert_status = t->cert_status;
628   response_.ssl_info.connection_status = t->ssl_connection_status;
629   response_.dns_aliases = t->dns_aliases;
630   data_ = resp_data;
631   content_length_ = response_.headers->GetContentLength();
632 
633   if (net_log_.net_log()) {
634     socket_log_id_ = net_log_.net_log()->NextID();
635   }
636 
637   if (current_request_.load_flags & LOAD_PREFETCH) {
638     response_.unused_since_prefetch = true;
639   }
640 
641   if (current_request_.load_flags & LOAD_RESTRICTED_PREFETCH) {
642     DCHECK(response_.unused_since_prefetch);
643     response_.restricted_prefetch = true;
644   }
645   return OK;
646 }
647 
DoSendRequestComplete(int result)648 int MockNetworkTransaction::DoSendRequestComplete(int result) {
649   CHECK_EQ(OK, result);
650   next_state_ = State::READ_HEADERS;
651   return OK;
652 }
653 
DoReadHeaders()654 int MockNetworkTransaction::DoReadHeaders() {
655   next_state_ = State::READ_HEADERS_COMPLETE;
656   return OK;
657 }
658 
DoReadHeadersComplete(int result)659 int MockNetworkTransaction::DoReadHeadersComplete(int result) {
660   CHECK_EQ(OK, result);
661   return OK;
662 }
663 
DoLoop(int result)664 int MockNetworkTransaction::DoLoop(int result) {
665   CHECK(next_state_ != State::NONE);
666 
667   int rv = result;
668   do {
669     State state = next_state_;
670     next_state_ = State::NONE;
671     switch (state) {
672       case State::NOTIFY_BEFORE_CREATE_STREAM:
673         CHECK_EQ(OK, rv);
674         rv = DoNotifyBeforeCreateStream();
675         break;
676       case State::CREATE_STREAM:
677         CHECK_EQ(OK, rv);
678         rv = DoCreateStream();
679         break;
680       case State::CREATE_STREAM_COMPLETE:
681         rv = DoCreateStreamComplete(rv);
682         break;
683       case State::CONNECTED_CALLBACK:
684         rv = DoConnectedCallback();
685         break;
686       case State::CONNECTED_CALLBACK_COMPLETE:
687         rv = DoConnectedCallbackComplete(rv);
688         break;
689       case State::BUILD_REQUEST:
690         CHECK_EQ(OK, rv);
691         rv = DoBuildRequest();
692         break;
693       case State::BUILD_REQUEST_COMPLETE:
694         rv = DoBuildRequestComplete(rv);
695         break;
696       case State::SEND_REQUEST:
697         CHECK_EQ(OK, rv);
698         rv = DoSendRequest();
699         break;
700       case State::SEND_REQUEST_COMPLETE:
701         rv = DoSendRequestComplete(rv);
702         break;
703       case State::READ_HEADERS:
704         CHECK_EQ(OK, rv);
705         rv = DoReadHeaders();
706         break;
707       case State::READ_HEADERS_COMPLETE:
708         rv = DoReadHeadersComplete(rv);
709         break;
710       default:
711         NOTREACHED() << "bad state";
712         rv = ERR_FAILED;
713         break;
714     }
715   } while (rv != ERR_IO_PENDING && next_state_ != State::NONE);
716 
717   return rv;
718 }
719 
OnIOComplete(int result)720 void MockNetworkTransaction::OnIOComplete(int result) {
721   int rv = DoLoop(result);
722   if (rv != ERR_IO_PENDING) {
723     CHECK(callback_);
724     std::move(callback_).Run(rv);
725   }
726 }
727 
SetBeforeNetworkStartCallback(BeforeNetworkStartCallback callback)728 void MockNetworkTransaction::SetBeforeNetworkStartCallback(
729     BeforeNetworkStartCallback callback) {
730   before_network_start_callback_ = std::move(callback);
731 }
732 
SetModifyRequestHeadersCallback(base::RepeatingCallback<void (net::HttpRequestHeaders *)> callback)733 void MockNetworkTransaction::SetModifyRequestHeadersCallback(
734     base::RepeatingCallback<void(net::HttpRequestHeaders*)> callback) {
735   modify_request_headers_callback_ = std::move(callback);
736 }
737 
SetConnectedCallback(const ConnectedCallback & callback)738 void MockNetworkTransaction::SetConnectedCallback(
739     const ConnectedCallback& callback) {
740   connected_callback_ = callback;
741 }
742 
ResumeNetworkStart()743 int MockNetworkTransaction::ResumeNetworkStart() {
744   CHECK_EQ(next_state_, State::CREATE_STREAM);
745   return DoLoop(OK);
746 }
747 
GetConnectionAttempts() const748 ConnectionAttempts MockNetworkTransaction::GetConnectionAttempts() const {
749   // TODO(ricea): Replace this with a proper implementation if needed.
750   return {};
751 }
752 
CloseConnectionOnDestruction()753 void MockNetworkTransaction::CloseConnectionOnDestruction() {
754   NOTIMPLEMENTED();
755 }
756 
IsMdlMatchForMetrics() const757 bool MockNetworkTransaction::IsMdlMatchForMetrics() const {
758   return false;
759 }
760 
CallbackLater(CompletionOnceCallback callback,int result)761 void MockNetworkTransaction::CallbackLater(CompletionOnceCallback callback,
762                                            int result) {
763   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
764       FROM_HERE,
765       base::BindOnce(&MockNetworkTransaction::RunCallback,
766                      weak_factory_.GetWeakPtr(), std::move(callback), result));
767 }
768 
RunCallback(CompletionOnceCallback callback,int result)769 void MockNetworkTransaction::RunCallback(CompletionOnceCallback callback,
770                                          int result) {
771   std::move(callback).Run(result);
772 }
773 
774 MockNetworkLayer::MockNetworkLayer() = default;
775 
776 MockNetworkLayer::~MockNetworkLayer() = default;
777 
TransactionDoneReading()778 void MockNetworkLayer::TransactionDoneReading() {
779   CHECK(!done_reading_called_);
780   done_reading_called_ = true;
781 }
782 
TransactionStopCaching()783 void MockNetworkLayer::TransactionStopCaching() {
784   stop_caching_called_ = true;
785 }
786 
ResetTransactionCount()787 void MockNetworkLayer::ResetTransactionCount() {
788   transaction_count_ = 0;
789 }
790 
CreateTransaction(RequestPriority priority,std::unique_ptr<HttpTransaction> * trans)791 int MockNetworkLayer::CreateTransaction(
792     RequestPriority priority,
793     std::unique_ptr<HttpTransaction>* trans) {
794   transaction_count_++;
795   last_create_transaction_priority_ = priority;
796   auto mock_transaction =
797       std::make_unique<MockNetworkTransaction>(priority, this);
798   last_transaction_ = mock_transaction->AsWeakPtr();
799   *trans = std::move(mock_transaction);
800   return OK;
801 }
802 
GetCache()803 HttpCache* MockNetworkLayer::GetCache() {
804   return nullptr;
805 }
806 
GetSession()807 HttpNetworkSession* MockNetworkLayer::GetSession() {
808   return nullptr;
809 }
810 
SetClock(base::Clock * clock)811 void MockNetworkLayer::SetClock(base::Clock* clock) {
812   DCHECK(!clock_);
813   clock_ = clock;
814 }
815 
Now()816 base::Time MockNetworkLayer::Now() {
817   if (clock_)
818     return clock_->Now();
819   return base::Time::Now();
820 }
821 
822 //-----------------------------------------------------------------------------
823 // helpers
824 
ReadTransaction(HttpTransaction * trans,std::string * result)825 int ReadTransaction(HttpTransaction* trans, std::string* result) {
826   int rv;
827 
828   std::string content;
829   do {
830     TestCompletionCallback callback;
831     auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
832     rv = trans->Read(buf.get(), 256, callback.callback());
833     if (rv == ERR_IO_PENDING) {
834       rv = callback.WaitForResult();
835       base::RunLoop().RunUntilIdle();
836     }
837 
838     if (rv > 0)
839       content.append(buf->data(), rv);
840     else if (rv < 0)
841       return rv;
842   } while (rv > 0);
843 
844   result->swap(content);
845   return OK;
846 }
847 
848 //-----------------------------------------------------------------------------
849 // connected callback handler
850 
851 ConnectedHandler::ConnectedHandler() = default;
852 ConnectedHandler::~ConnectedHandler() = default;
853 
854 ConnectedHandler::ConnectedHandler(const ConnectedHandler&) = default;
855 ConnectedHandler& ConnectedHandler::operator=(const ConnectedHandler&) =
856     default;
857 ConnectedHandler::ConnectedHandler(ConnectedHandler&&) = default;
858 ConnectedHandler& ConnectedHandler::operator=(ConnectedHandler&&) = default;
859 
OnConnected(const TransportInfo & info,CompletionOnceCallback callback)860 int ConnectedHandler::OnConnected(const TransportInfo& info,
861                                   CompletionOnceCallback callback) {
862   transports_.push_back(info);
863   if (run_callback_) {
864     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
865         FROM_HERE, base::BindOnce(std::move(callback), result_));
866     return net::ERR_IO_PENDING;
867   }
868   return result_;
869 }
870 
871 }  // namespace net
872