blob: 1a88b94ef88d3a113d8d4ea36efa48890202b434 [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);
Darin Petkov9ce452b2010-11-17 14:33:28 -080044 // We may get terminated in the callback.
45 if (sent_size_ == data_.size()) {
46 LOG(INFO) << "Terminated in the ReceivedBytes callback.";
47 return timeout_source_;
48 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000049 sent_size_ += chunk_size;
50 CHECK_LE(sent_size_, data_.size());
51 if (sent_size_ == data_.size()) {
Darin Petkovcb466212010-08-26 09:40:11 -070052 // We've sent all the data. Notify of success.
Darin Petkovedc522e2010-11-05 09:35:17 -070053 SignalTransferComplete();
rspangler@google.com49fdf182009-10-10 00:57:34 +000054 }
55 }
56
57 if (paused_) {
58 // If we're paused, we should return true if timeout_source_ is set,
59 // since we need the caller to delete it.
60 return timeout_source_;
61 }
62
63 if (timeout_source_) {
64 // we still need a timeout if there's more data to send
65 return sent_size_ < data_.size();
66 } else if (sent_size_ < data_.size()) {
67 // we don't have a timeout source and we need one
68 timeout_source_ = g_timeout_source_new(10);
69 CHECK(timeout_source_);
70 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this,
71 NULL);
72 timout_tag_ = g_source_attach(timeout_source_, NULL);
73 }
74 return true;
75}
76
77bool MockHttpFetcher::TimeoutCallback() {
78 CHECK(!paused_);
79 bool ret = SendData(false);
80 if (false == ret) {
81 timeout_source_ = NULL;
82 }
83 return ret;
84}
85
86// If the transfer is in progress, aborts the transfer early.
87// The transfer cannot be resumed.
88void MockHttpFetcher::TerminateTransfer() {
Darin Petkov9ce452b2010-11-17 14:33:28 -080089 LOG(INFO) << "Terminating transfer.";
rspangler@google.com49fdf182009-10-10 00:57:34 +000090 sent_size_ = data_.size();
91 // kill any timeout
92 if (timeout_source_) {
93 g_source_remove(timout_tag_);
94 g_source_destroy(timeout_source_);
95 timeout_source_ = NULL;
96 }
Darin Petkov9ce452b2010-11-17 14:33:28 -080097 delegate_->TransferTerminated(this);
rspangler@google.com49fdf182009-10-10 00:57:34 +000098}
99
100void MockHttpFetcher::Pause() {
101 CHECK(!paused_);
102 paused_ = true;
103 if (timeout_source_) {
104 g_source_remove(timout_tag_);
105 g_source_destroy(timeout_source_);
106 timeout_source_ = NULL;
107 }
108
109}
110
111void MockHttpFetcher::Unpause() {
112 CHECK(paused_) << "You must pause before unpause.";
113 paused_ = false;
114 if (sent_size_ < data_.size()) {
115 SendData(false);
116 }
117}
118
Darin Petkovedc522e2010-11-05 09:35:17 -0700119void MockHttpFetcher::FailTransfer(int http_response_code) {
120 fail_transfer_ = true;
121 http_response_code_ = http_response_code;
122}
123
124void MockHttpFetcher::SignalTransferComplete() {
125 // If the transfer has been failed, the HTTP response code should be set
126 // already.
127 if (!fail_transfer_) {
128 http_response_code_ = 200;
129 }
130 delegate_->TransferComplete(this, !fail_transfer_);
131}
132
rspangler@google.com49fdf182009-10-10 00:57:34 +0000133} // namespace chromeos_update_engine