blob: 5452d5d46da70cfae54709b2b29cbf776136bb99 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS 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.
4
rspangler@google.com49fdf182009-10-10 00:57:34 +00005#include "update_engine/mock_http_fetcher.h"
6
Andrew de los Reyes173e63c2011-04-04 17:19:57 -07007#include <algorithm>
8
9#include <base/logging.h>
10#include <gtest/gtest.h>
11
12
13// This is a mock implementation of HttpFetcher which is useful for testing.
rspangler@google.com49fdf182009-10-10 00:57:34 +000014
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015using std::min;
16
rspangler@google.com49fdf182009-10-10 00:57:34 +000017namespace chromeos_update_engine {
18
19MockHttpFetcher::~MockHttpFetcher() {
20 CHECK(!timeout_source_) << "Call TerminateTransfer() before dtor.";
21}
22
23void MockHttpFetcher::BeginTransfer(const std::string& url) {
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070024 EXPECT_FALSE(never_use_);
Darin Petkovedc522e2010-11-05 09:35:17 -070025 if (fail_transfer_ || data_.empty()) {
26 // No data to send, just notify of completion..
27 SignalTransferComplete();
28 return;
29 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000030 if (sent_size_ < data_.size())
31 SendData(true);
32}
33
34// Returns false on one condition: If timeout_source_ was already set
35// and it needs to be deleted by the caller. If timeout_source_ is NULL
36// when this function is called, this function will always return true.
37bool MockHttpFetcher::SendData(bool skip_delivery) {
Darin Petkovedc522e2010-11-05 09:35:17 -070038 if (fail_transfer_) {
39 SignalTransferComplete();
40 return timeout_source_;
41 }
42
rspangler@google.com49fdf182009-10-10 00:57:34 +000043 CHECK_LT(sent_size_, data_.size());
44 if (!skip_delivery) {
45 const size_t chunk_size = min(kMockHttpFetcherChunkSize,
46 data_.size() - sent_size_);
47 CHECK(delegate_);
48 delegate_->ReceivedBytes(this, &data_[sent_size_], chunk_size);
Darin Petkov9ce452b2010-11-17 14:33:28 -080049 // We may get terminated in the callback.
50 if (sent_size_ == data_.size()) {
51 LOG(INFO) << "Terminated in the ReceivedBytes callback.";
52 return timeout_source_;
53 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000054 sent_size_ += chunk_size;
55 CHECK_LE(sent_size_, data_.size());
56 if (sent_size_ == data_.size()) {
Darin Petkovcb466212010-08-26 09:40:11 -070057 // We've sent all the data. Notify of success.
Darin Petkovedc522e2010-11-05 09:35:17 -070058 SignalTransferComplete();
rspangler@google.com49fdf182009-10-10 00:57:34 +000059 }
60 }
61
62 if (paused_) {
63 // If we're paused, we should return true if timeout_source_ is set,
64 // since we need the caller to delete it.
65 return timeout_source_;
66 }
67
68 if (timeout_source_) {
69 // we still need a timeout if there's more data to send
70 return sent_size_ < data_.size();
71 } else if (sent_size_ < data_.size()) {
72 // we don't have a timeout source and we need one
73 timeout_source_ = g_timeout_source_new(10);
74 CHECK(timeout_source_);
75 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this,
76 NULL);
77 timout_tag_ = g_source_attach(timeout_source_, NULL);
78 }
79 return true;
80}
81
82bool MockHttpFetcher::TimeoutCallback() {
83 CHECK(!paused_);
84 bool ret = SendData(false);
85 if (false == ret) {
86 timeout_source_ = NULL;
87 }
88 return ret;
89}
90
91// If the transfer is in progress, aborts the transfer early.
92// The transfer cannot be resumed.
93void MockHttpFetcher::TerminateTransfer() {
Darin Petkov9ce452b2010-11-17 14:33:28 -080094 LOG(INFO) << "Terminating transfer.";
rspangler@google.com49fdf182009-10-10 00:57:34 +000095 sent_size_ = data_.size();
96 // kill any timeout
97 if (timeout_source_) {
98 g_source_remove(timout_tag_);
99 g_source_destroy(timeout_source_);
100 timeout_source_ = NULL;
101 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800102 delegate_->TransferTerminated(this);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000103}
104
105void MockHttpFetcher::Pause() {
106 CHECK(!paused_);
107 paused_ = true;
108 if (timeout_source_) {
109 g_source_remove(timout_tag_);
110 g_source_destroy(timeout_source_);
111 timeout_source_ = NULL;
112 }
113
114}
115
116void MockHttpFetcher::Unpause() {
117 CHECK(paused_) << "You must pause before unpause.";
118 paused_ = false;
119 if (sent_size_ < data_.size()) {
120 SendData(false);
121 }
122}
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