blob: eec550f6f49765af1d831b5d4388f322c205cc38 [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"
adlr@google.comc98a7ed2009-12-04 18:54:03 +00006#include <algorithm>
Chris Masone790e62e2010-08-12 10:41:18 -07007#include "base/logging.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +00008
9// This is a mac implementation of HttpFetcher which is useful for testing.
10
adlr@google.comc98a7ed2009-12-04 18:54:03 +000011using std::min;
12
rspangler@google.com49fdf182009-10-10 00:57:34 +000013namespace chromeos_update_engine {
14
15MockHttpFetcher::~MockHttpFetcher() {
16 CHECK(!timeout_source_) << "Call TerminateTransfer() before dtor.";
17}
18
19void MockHttpFetcher::BeginTransfer(const std::string& url) {
Darin Petkovedc522e2010-11-05 09:35:17 -070020 if (fail_transfer_ || data_.empty()) {
21 // No data to send, just notify of completion..
22 SignalTransferComplete();
23 return;
24 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000025 if (sent_size_ < data_.size())
26 SendData(true);
27}
28
29// Returns false on one condition: If timeout_source_ was already set
30// and it needs to be deleted by the caller. If timeout_source_ is NULL
31// when this function is called, this function will always return true.
32bool MockHttpFetcher::SendData(bool skip_delivery) {
Darin Petkovedc522e2010-11-05 09:35:17 -070033 if (fail_transfer_) {
34 SignalTransferComplete();
35 return timeout_source_;
36 }
37
rspangler@google.com49fdf182009-10-10 00:57:34 +000038 CHECK_LT(sent_size_, data_.size());
39 if (!skip_delivery) {
40 const size_t chunk_size = min(kMockHttpFetcherChunkSize,
41 data_.size() - sent_size_);
42 CHECK(delegate_);
43 delegate_->ReceivedBytes(this, &data_[sent_size_], chunk_size);
44 sent_size_ += chunk_size;
45 CHECK_LE(sent_size_, data_.size());
46 if (sent_size_ == data_.size()) {
Darin Petkovcb466212010-08-26 09:40:11 -070047 // We've sent all the data. Notify of success.
Darin Petkovedc522e2010-11-05 09:35:17 -070048 SignalTransferComplete();
rspangler@google.com49fdf182009-10-10 00:57:34 +000049 }
50 }
51
52 if (paused_) {
53 // If we're paused, we should return true if timeout_source_ is set,
54 // since we need the caller to delete it.
55 return timeout_source_;
56 }
57
58 if (timeout_source_) {
59 // we still need a timeout if there's more data to send
60 return sent_size_ < data_.size();
61 } else if (sent_size_ < data_.size()) {
62 // we don't have a timeout source and we need one
63 timeout_source_ = g_timeout_source_new(10);
64 CHECK(timeout_source_);
65 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this,
66 NULL);
67 timout_tag_ = g_source_attach(timeout_source_, NULL);
68 }
69 return true;
70}
71
72bool MockHttpFetcher::TimeoutCallback() {
73 CHECK(!paused_);
74 bool ret = SendData(false);
75 if (false == ret) {
76 timeout_source_ = NULL;
77 }
78 return ret;
79}
80
81// If the transfer is in progress, aborts the transfer early.
82// The transfer cannot be resumed.
83void MockHttpFetcher::TerminateTransfer() {
84 sent_size_ = data_.size();
85 // kill any timeout
86 if (timeout_source_) {
87 g_source_remove(timout_tag_);
88 g_source_destroy(timeout_source_);
89 timeout_source_ = NULL;
90 }
91}
92
93void MockHttpFetcher::Pause() {
94 CHECK(!paused_);
95 paused_ = true;
96 if (timeout_source_) {
97 g_source_remove(timout_tag_);
98 g_source_destroy(timeout_source_);
99 timeout_source_ = NULL;
100 }
101
102}
103
104void MockHttpFetcher::Unpause() {
105 CHECK(paused_) << "You must pause before unpause.";
106 paused_ = false;
107 if (sent_size_ < data_.size()) {
108 SendData(false);
109 }
110}
111
Darin Petkovedc522e2010-11-05 09:35:17 -0700112void MockHttpFetcher::FailTransfer(int http_response_code) {
113 fail_transfer_ = true;
114 http_response_code_ = http_response_code;
115}
116
117void MockHttpFetcher::SignalTransferComplete() {
118 // If the transfer has been failed, the HTTP response code should be set
119 // already.
120 if (!fail_transfer_) {
121 http_response_code_ = 200;
122 }
123 delegate_->TransferComplete(this, !fail_transfer_);
124}
125
rspangler@google.com49fdf182009-10-10 00:57:34 +0000126} // namespace chromeos_update_engine