blob: 81f9225a95ac7a7b5cef1b0620f2d1211d190238 [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
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070012// This is a mock implementation of HttpFetcher which is useful for testing.
rspangler@google.com49fdf182009-10-10 00:57:34 +000013
adlr@google.comc98a7ed2009-12-04 18:54:03 +000014using std::min;
15
rspangler@google.com49fdf182009-10-10 00:57:34 +000016namespace chromeos_update_engine {
17
18MockHttpFetcher::~MockHttpFetcher() {
19 CHECK(!timeout_source_) << "Call TerminateTransfer() before dtor.";
20}
21
22void MockHttpFetcher::BeginTransfer(const std::string& url) {
Andrew de los Reyes173e63c2011-04-04 17:19:57 -070023 EXPECT_FALSE(never_use_);
Darin Petkovedc522e2010-11-05 09:35:17 -070024 if (fail_transfer_ || data_.empty()) {
25 // No data to send, just notify of completion..
26 SignalTransferComplete();
27 return;
28 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000029 if (sent_size_ < data_.size())
30 SendData(true);
31}
32
33// Returns false on one condition: If timeout_source_ was already set
34// and it needs to be deleted by the caller. If timeout_source_ is NULL
35// when this function is called, this function will always return true.
36bool MockHttpFetcher::SendData(bool skip_delivery) {
Darin Petkovedc522e2010-11-05 09:35:17 -070037 if (fail_transfer_) {
38 SignalTransferComplete();
39 return timeout_source_;
40 }
41
rspangler@google.com49fdf182009-10-10 00:57:34 +000042 CHECK_LT(sent_size_, data_.size());
43 if (!skip_delivery) {
44 const size_t chunk_size = min(kMockHttpFetcherChunkSize,
45 data_.size() - sent_size_);
46 CHECK(delegate_);
47 delegate_->ReceivedBytes(this, &data_[sent_size_], chunk_size);
Darin Petkov9ce452b2010-11-17 14:33:28 -080048 // We may get terminated in the callback.
49 if (sent_size_ == data_.size()) {
50 LOG(INFO) << "Terminated in the ReceivedBytes callback.";
51 return timeout_source_;
52 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000053 sent_size_ += chunk_size;
54 CHECK_LE(sent_size_, data_.size());
55 if (sent_size_ == data_.size()) {
Darin Petkovcb466212010-08-26 09:40:11 -070056 // We've sent all the data. Notify of success.
Darin Petkovedc522e2010-11-05 09:35:17 -070057 SignalTransferComplete();
rspangler@google.com49fdf182009-10-10 00:57:34 +000058 }
59 }
60
61 if (paused_) {
62 // If we're paused, we should return true if timeout_source_ is set,
63 // since we need the caller to delete it.
64 return timeout_source_;
65 }
66
67 if (timeout_source_) {
68 // we still need a timeout if there's more data to send
69 return sent_size_ < data_.size();
70 } else if (sent_size_ < data_.size()) {
71 // we don't have a timeout source and we need one
72 timeout_source_ = g_timeout_source_new(10);
73 CHECK(timeout_source_);
74 g_source_set_callback(timeout_source_, StaticTimeoutCallback, this,
75 NULL);
76 timout_tag_ = g_source_attach(timeout_source_, NULL);
77 }
78 return true;
79}
80
81bool MockHttpFetcher::TimeoutCallback() {
82 CHECK(!paused_);
83 bool ret = SendData(false);
84 if (false == ret) {
85 timeout_source_ = NULL;
86 }
87 return ret;
88}
89
90// If the transfer is in progress, aborts the transfer early.
91// The transfer cannot be resumed.
92void MockHttpFetcher::TerminateTransfer() {
Darin Petkov9ce452b2010-11-17 14:33:28 -080093 LOG(INFO) << "Terminating transfer.";
rspangler@google.com49fdf182009-10-10 00:57:34 +000094 sent_size_ = data_.size();
95 // kill any timeout
96 if (timeout_source_) {
97 g_source_remove(timout_tag_);
98 g_source_destroy(timeout_source_);
99 timeout_source_ = NULL;
100 }
Darin Petkov9ce452b2010-11-17 14:33:28 -0800101 delegate_->TransferTerminated(this);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000102}
103
104void MockHttpFetcher::Pause() {
105 CHECK(!paused_);
106 paused_ = true;
107 if (timeout_source_) {
108 g_source_remove(timout_tag_);
109 g_source_destroy(timeout_source_);
110 timeout_source_ = NULL;
111 }
112
113}
114
115void MockHttpFetcher::Unpause() {
116 CHECK(paused_) << "You must pause before unpause.";
117 paused_ = false;
118 if (sent_size_ < data_.size()) {
119 SendData(false);
120 }
121}
122
Darin Petkovedc522e2010-11-05 09:35:17 -0700123void MockHttpFetcher::FailTransfer(int http_response_code) {
124 fail_transfer_ = true;
125 http_response_code_ = http_response_code;
126}
127
128void MockHttpFetcher::SignalTransferComplete() {
129 // If the transfer has been failed, the HTTP response code should be set
130 // already.
131 if (!fail_transfer_) {
132 http_response_code_ = 200;
133 }
134 delegate_->TransferComplete(this, !fail_transfer_);
135}
136
rspangler@google.com49fdf182009-10-10 00:57:34 +0000137} // namespace chromeos_update_engine