blob: 10e3b9efd28f6d427617e546ead37f5e7ff44b9e [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2009 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
rspangler@google.com49fdf182009-10-10 00:57:34 +000016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/common/mock_http_fetcher.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000018
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070019#include <algorithm>
20
Alex Deymoc1c17b42015-11-23 03:53:15 -030021#include <base/bind.h>
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070022#include <base/logging.h>
Alex Deymofdd6dec2016-03-03 22:35:43 -080023#include <base/strings/string_util.h>
Alex Deymoc1c17b42015-11-23 03:53:15 -030024#include <base/time/time.h>
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070025#include <gtest/gtest.h>
26
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070027// This is a mock implementation of HttpFetcher which is useful for testing.
rspangler@google.com49fdf182009-10-10 00:57:34 +000028
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070029using brillo::MessageLoop;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000030using std::min;
31
rspangler@google.com49fdf182009-10-10 00:57:34 +000032namespace chromeos_update_engine {
33
34MockHttpFetcher::~MockHttpFetcher() {
Amin Hassanib2689592019-01-13 17:04:28 -080035 CHECK(timeout_id_ == MessageLoop::kTaskIdNull)
36 << "Call TerminateTransfer() before dtor.";
rspangler@google.com49fdf182009-10-10 00:57:34 +000037}
38
39void MockHttpFetcher::BeginTransfer(const std::string& url) {
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070040 EXPECT_FALSE(never_use_);
Darin Petkovedc522e2010-11-05 09:35:17 -070041 if (fail_transfer_ || data_.empty()) {
42 // No data to send, just notify of completion..
43 SignalTransferComplete();
44 return;
45 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000046 if (sent_size_ < data_.size())
47 SendData(true);
48}
49
Amin Hassanid3f4bea2018-04-30 14:52:40 -070050void MockHttpFetcher::SendData(bool skip_delivery) {
51 if (fail_transfer_ || sent_size_ == data_.size()) {
Darin Petkovedc522e2010-11-05 09:35:17 -070052 SignalTransferComplete();
Amin Hassanid3f4bea2018-04-30 14:52:40 -070053 return;
rspangler@google.com49fdf182009-10-10 00:57:34 +000054 }
55
56 if (paused_) {
Amin Hassanid3f4bea2018-04-30 14:52:40 -070057 // If we're paused, we should return so no callback is scheduled.
58 return;
rspangler@google.com49fdf182009-10-10 00:57:34 +000059 }
60
Amin Hassanid3f4bea2018-04-30 14:52:40 -070061 // Setup timeout callback even if the transfer is about to be completed in
62 // order to get a call to |TransferComplete|.
63 if (timeout_id_ == MessageLoop::kTaskIdNull) {
Alex Deymo60ca1a72015-06-18 18:19:15 -070064 timeout_id_ = MessageLoop::current()->PostDelayedTask(
65 FROM_HERE,
66 base::Bind(&MockHttpFetcher::TimeoutCallback, base::Unretained(this)),
67 base::TimeDelta::FromMilliseconds(10));
rspangler@google.com49fdf182009-10-10 00:57:34 +000068 }
Amin Hassanid3f4bea2018-04-30 14:52:40 -070069
70 if (!skip_delivery) {
71 const size_t chunk_size =
72 min(kMockHttpFetcherChunkSize, data_.size() - sent_size_);
73 sent_size_ += chunk_size;
74 CHECK(delegate_);
75 delegate_->ReceivedBytes(this, &data_[sent_size_ - chunk_size], chunk_size);
76 }
77 // We may get terminated and deleted right after |ReceivedBytes| call, so we
78 // should not access any class member variable after this call.
rspangler@google.com49fdf182009-10-10 00:57:34 +000079}
80
Alex Deymo60ca1a72015-06-18 18:19:15 -070081void MockHttpFetcher::TimeoutCallback() {
rspangler@google.com49fdf182009-10-10 00:57:34 +000082 CHECK(!paused_);
Amin Hassanid3f4bea2018-04-30 14:52:40 -070083 timeout_id_ = MessageLoop::kTaskIdNull;
84 CHECK_LE(sent_size_, data_.size());
85 // Same here, we should not access any member variable after this call.
86 SendData(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +000087}
88
89// If the transfer is in progress, aborts the transfer early.
90// The transfer cannot be resumed.
91void MockHttpFetcher::TerminateTransfer() {
Darin Petkov9ce452b2010-11-17 14:33:28 -080092 LOG(INFO) << "Terminating transfer.";
Alex Deymo60ca1a72015-06-18 18:19:15 -070093 // Kill any timeout, it is ok to call with kTaskIdNull.
94 MessageLoop::current()->CancelTask(timeout_id_);
95 timeout_id_ = MessageLoop::kTaskIdNull;
Darin Petkov9ce452b2010-11-17 14:33:28 -080096 delegate_->TransferTerminated(this);
rspangler@google.com49fdf182009-10-10 00:57:34 +000097}
98
Alex Deymofdd6dec2016-03-03 22:35:43 -080099void MockHttpFetcher::SetHeader(const std::string& header_name,
100 const std::string& header_value) {
101 extra_headers_[base::ToLowerASCII(header_name)] = header_value;
102}
103
Alex Deymo14ad88e2016-06-29 12:30:14 -0700104std::string MockHttpFetcher::GetHeader(const std::string& header_name) const {
105 const auto it = extra_headers_.find(base::ToLowerASCII(header_name));
106 if (it == extra_headers_.end())
107 return "";
108 return it->second;
109}
110
rspangler@google.com49fdf182009-10-10 00:57:34 +0000111void MockHttpFetcher::Pause() {
112 CHECK(!paused_);
113 paused_ = true;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700114 MessageLoop::current()->CancelTask(timeout_id_);
115 timeout_id_ = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000116}
117
118void MockHttpFetcher::Unpause() {
119 CHECK(paused_) << "You must pause before unpause.";
120 paused_ = false;
Amin Hassanid3f4bea2018-04-30 14:52:40 -0700121 SendData(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000122}
123
Darin Petkovedc522e2010-11-05 09:35:17 -0700124void MockHttpFetcher::FailTransfer(int http_response_code) {
125 fail_transfer_ = true;
126 http_response_code_ = http_response_code;
127}
128
129void MockHttpFetcher::SignalTransferComplete() {
130 // If the transfer has been failed, the HTTP response code should be set
131 // already.
132 if (!fail_transfer_) {
133 http_response_code_ = 200;
134 }
135 delegate_->TransferComplete(this, !fail_transfer_);
136}
137
rspangler@google.com49fdf182009-10-10 00:57:34 +0000138} // namespace chromeos_update_engine