xref: /aosp_15_r20/system/update_engine/common/mock_http_fetcher.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2009 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/mock_http_fetcher.h"
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <algorithm>
20*5a923131SAndroid Build Coastguard Worker 
21*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
22*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
23*5a923131SAndroid Build Coastguard Worker #include <base/time/time.h>
24*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop.h>
25*5a923131SAndroid Build Coastguard Worker #include <gtest/gtest.h>
26*5a923131SAndroid Build Coastguard Worker 
27*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
28*5a923131SAndroid Build Coastguard Worker 
29*5a923131SAndroid Build Coastguard Worker // This is a mock implementation of HttpFetcher which is useful for testing.
30*5a923131SAndroid Build Coastguard Worker 
31*5a923131SAndroid Build Coastguard Worker using brillo::MessageLoop;
32*5a923131SAndroid Build Coastguard Worker using std::min;
33*5a923131SAndroid Build Coastguard Worker 
34*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
35*5a923131SAndroid Build Coastguard Worker 
~MockHttpFetcher()36*5a923131SAndroid Build Coastguard Worker MockHttpFetcher::~MockHttpFetcher() {
37*5a923131SAndroid Build Coastguard Worker   CHECK(timeout_id_ == MessageLoop::kTaskIdNull)
38*5a923131SAndroid Build Coastguard Worker       << "Call TerminateTransfer() before dtor.";
39*5a923131SAndroid Build Coastguard Worker }
40*5a923131SAndroid Build Coastguard Worker 
BeginTransfer(const std::string & url)41*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::BeginTransfer(const std::string& url) {
42*5a923131SAndroid Build Coastguard Worker   EXPECT_FALSE(never_use_);
43*5a923131SAndroid Build Coastguard Worker   if (fail_transfer_ || data_.empty()) {
44*5a923131SAndroid Build Coastguard Worker     // No data to send, just notify of completion..
45*5a923131SAndroid Build Coastguard Worker     SignalTransferComplete();
46*5a923131SAndroid Build Coastguard Worker     return;
47*5a923131SAndroid Build Coastguard Worker   }
48*5a923131SAndroid Build Coastguard Worker   if (sent_offset_ < data_.size())
49*5a923131SAndroid Build Coastguard Worker     SendData(true);
50*5a923131SAndroid Build Coastguard Worker }
51*5a923131SAndroid Build Coastguard Worker 
SendData(bool skip_delivery)52*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::SendData(bool skip_delivery) {
53*5a923131SAndroid Build Coastguard Worker   if (fail_transfer_ || sent_offset_ == data_.size()) {
54*5a923131SAndroid Build Coastguard Worker     SignalTransferComplete();
55*5a923131SAndroid Build Coastguard Worker     return;
56*5a923131SAndroid Build Coastguard Worker   }
57*5a923131SAndroid Build Coastguard Worker 
58*5a923131SAndroid Build Coastguard Worker   if (paused_) {
59*5a923131SAndroid Build Coastguard Worker     // If we're paused, we should return so no callback is scheduled.
60*5a923131SAndroid Build Coastguard Worker     return;
61*5a923131SAndroid Build Coastguard Worker   }
62*5a923131SAndroid Build Coastguard Worker 
63*5a923131SAndroid Build Coastguard Worker   // Setup timeout callback even if the transfer is about to be completed in
64*5a923131SAndroid Build Coastguard Worker   // order to get a call to |TransferComplete|.
65*5a923131SAndroid Build Coastguard Worker   if (timeout_id_ == MessageLoop::kTaskIdNull && delay_) {
66*5a923131SAndroid Build Coastguard Worker     CHECK(MessageLoop::current());
67*5a923131SAndroid Build Coastguard Worker     timeout_id_ = MessageLoop::current()->PostDelayedTask(
68*5a923131SAndroid Build Coastguard Worker         FROM_HERE,
69*5a923131SAndroid Build Coastguard Worker         base::Bind(&MockHttpFetcher::TimeoutCallback, base::Unretained(this)),
70*5a923131SAndroid Build Coastguard Worker         base::TimeDelta::FromMilliseconds(10));
71*5a923131SAndroid Build Coastguard Worker   }
72*5a923131SAndroid Build Coastguard Worker 
73*5a923131SAndroid Build Coastguard Worker   if (!skip_delivery || !delay_) {
74*5a923131SAndroid Build Coastguard Worker     const size_t chunk_size =
75*5a923131SAndroid Build Coastguard Worker         min(kMockHttpFetcherChunkSize, data_.size() - sent_offset_);
76*5a923131SAndroid Build Coastguard Worker     sent_offset_ += chunk_size;
77*5a923131SAndroid Build Coastguard Worker     bytes_sent_ += chunk_size;
78*5a923131SAndroid Build Coastguard Worker     CHECK(delegate_);
79*5a923131SAndroid Build Coastguard Worker     delegate_->ReceivedBytes(
80*5a923131SAndroid Build Coastguard Worker         this, &data_[sent_offset_ - chunk_size], chunk_size);
81*5a923131SAndroid Build Coastguard Worker   }
82*5a923131SAndroid Build Coastguard Worker   // We may get terminated and deleted right after |ReceivedBytes| call, so we
83*5a923131SAndroid Build Coastguard Worker   // should not access any class member variable after this call.
84*5a923131SAndroid Build Coastguard Worker }
85*5a923131SAndroid Build Coastguard Worker 
TimeoutCallback()86*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::TimeoutCallback() {
87*5a923131SAndroid Build Coastguard Worker   CHECK(!paused_);
88*5a923131SAndroid Build Coastguard Worker   timeout_id_ = MessageLoop::kTaskIdNull;
89*5a923131SAndroid Build Coastguard Worker   CHECK_LE(sent_offset_, data_.size());
90*5a923131SAndroid Build Coastguard Worker   // Same here, we should not access any member variable after this call.
91*5a923131SAndroid Build Coastguard Worker   SendData(false);
92*5a923131SAndroid Build Coastguard Worker }
93*5a923131SAndroid Build Coastguard Worker 
94*5a923131SAndroid Build Coastguard Worker // If the transfer is in progress, aborts the transfer early.
95*5a923131SAndroid Build Coastguard Worker // The transfer cannot be resumed.
TerminateTransfer()96*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::TerminateTransfer() {
97*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Terminating transfer.";
98*5a923131SAndroid Build Coastguard Worker   // During testing, MessageLoop may or may not be available.
99*5a923131SAndroid Build Coastguard Worker   // So don't call CancelTask() unless necessary.
100*5a923131SAndroid Build Coastguard Worker   if (timeout_id_ != MessageLoop::kTaskIdNull) {
101*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->CancelTask(timeout_id_);
102*5a923131SAndroid Build Coastguard Worker     timeout_id_ = MessageLoop::kTaskIdNull;
103*5a923131SAndroid Build Coastguard Worker   }
104*5a923131SAndroid Build Coastguard Worker   if (delegate_) {
105*5a923131SAndroid Build Coastguard Worker     delegate_->TransferTerminated(this);
106*5a923131SAndroid Build Coastguard Worker   }
107*5a923131SAndroid Build Coastguard Worker }
108*5a923131SAndroid Build Coastguard Worker 
SetHeader(const std::string & header_name,const std::string & header_value)109*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::SetHeader(const std::string& header_name,
110*5a923131SAndroid Build Coastguard Worker                                 const std::string& header_value) {
111*5a923131SAndroid Build Coastguard Worker   extra_headers_[ToLower(header_name)] = header_value;
112*5a923131SAndroid Build Coastguard Worker }
113*5a923131SAndroid Build Coastguard Worker 
GetHeader(const std::string & header_name) const114*5a923131SAndroid Build Coastguard Worker std::string MockHttpFetcher::GetHeader(const std::string& header_name) const {
115*5a923131SAndroid Build Coastguard Worker   const auto it = extra_headers_.find(ToLower(header_name));
116*5a923131SAndroid Build Coastguard Worker   if (it == extra_headers_.end())
117*5a923131SAndroid Build Coastguard Worker     return "";
118*5a923131SAndroid Build Coastguard Worker   return it->second;
119*5a923131SAndroid Build Coastguard Worker }
120*5a923131SAndroid Build Coastguard Worker 
Pause()121*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::Pause() {
122*5a923131SAndroid Build Coastguard Worker   CHECK(!paused_);
123*5a923131SAndroid Build Coastguard Worker   paused_ = true;
124*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->CancelTask(timeout_id_);
125*5a923131SAndroid Build Coastguard Worker   timeout_id_ = MessageLoop::kTaskIdNull;
126*5a923131SAndroid Build Coastguard Worker }
127*5a923131SAndroid Build Coastguard Worker 
Unpause()128*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::Unpause() {
129*5a923131SAndroid Build Coastguard Worker   CHECK(paused_) << "You must pause before unpause.";
130*5a923131SAndroid Build Coastguard Worker   paused_ = false;
131*5a923131SAndroid Build Coastguard Worker   SendData(false);
132*5a923131SAndroid Build Coastguard Worker }
133*5a923131SAndroid Build Coastguard Worker 
FailTransfer(int http_response_code)134*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::FailTransfer(int http_response_code) {
135*5a923131SAndroid Build Coastguard Worker   fail_transfer_ = true;
136*5a923131SAndroid Build Coastguard Worker   http_response_code_ = http_response_code;
137*5a923131SAndroid Build Coastguard Worker }
138*5a923131SAndroid Build Coastguard Worker 
SignalTransferComplete()139*5a923131SAndroid Build Coastguard Worker void MockHttpFetcher::SignalTransferComplete() {
140*5a923131SAndroid Build Coastguard Worker   // If the transfer has been failed, the HTTP response code should be set
141*5a923131SAndroid Build Coastguard Worker   // already.
142*5a923131SAndroid Build Coastguard Worker   if (!fail_transfer_) {
143*5a923131SAndroid Build Coastguard Worker     http_response_code_ = 200;
144*5a923131SAndroid Build Coastguard Worker   }
145*5a923131SAndroid Build Coastguard Worker   delegate_->TransferComplete(this, !fail_transfer_);
146*5a923131SAndroid Build Coastguard Worker }
147*5a923131SAndroid Build Coastguard Worker 
148*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
149