1//
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//
16
17#ifndef UPDATE_ENGINE_COMMON_MOCK_HTTP_FETCHER_H_
18#define UPDATE_ENGINE_COMMON_MOCK_HTTP_FETCHER_H_
19
20#include <map>
21#include <string>
22#include <vector>
23
24#include <base/logging.h>
25#include <brillo/message_loops/message_loop.h>
26
27#include "update_engine/common/http_fetcher.h"
28
29// This is a mock implementation of HttpFetcher which is useful for testing.
30// All data must be passed into the ctor. When started, MockHttpFetcher will
31// deliver the data in chunks of size kMockHttpFetcherChunkSize. To simulate
32// a network failure, you can call FailTransfer().
33
34namespace chromeos_update_engine {
35
36// MockHttpFetcher will send a chunk of data down in each call to BeginTransfer
37// and Unpause. For the other chunks of data, a callback is put on the run
38// loop and when that's called, another chunk is sent down.
39const size_t kMockHttpFetcherChunkSize(65536);
40
41class MockHttpFetcher : public HttpFetcher {
42 public:
43  // The data passed in here is copied and then passed to the delegate after
44  // the transfer begins.
45  MockHttpFetcher(const uint8_t* data,
46                  size_t size,
47                  ProxyResolver* proxy_resolver)
48      : HttpFetcher(proxy_resolver),
49        sent_size_(0),
50        timeout_id_(brillo::MessageLoop::kTaskIdNull),
51        paused_(false),
52        fail_transfer_(false),
53        never_use_(false) {
54    data_.insert(data_.end(), data, data + size);
55  }
56
57  // Constructor overload for string data.
58  MockHttpFetcher(const char* data, size_t size, ProxyResolver* proxy_resolver)
59      : MockHttpFetcher(reinterpret_cast<const uint8_t*>(data), size,
60                        proxy_resolver) {}
61
62  // Cleans up all internal state. Does not notify delegate
63  ~MockHttpFetcher() override;
64
65  // Ignores this.
66  void SetOffset(off_t offset) override {
67    sent_size_ = offset;
68    if (delegate_)
69      delegate_->SeekToOffset(offset);
70  }
71
72  // Do nothing.
73  void SetLength(size_t length) override {}
74  void UnsetLength() override {}
75  void set_low_speed_limit(int low_speed_bps, int low_speed_sec) override {}
76  void set_connect_timeout(int connect_timeout_seconds) override {}
77  void set_max_retry_count(int max_retry_count) override {}
78
79  // Dummy: no bytes were downloaded.
80  size_t GetBytesDownloaded() override {
81    return sent_size_;
82  }
83
84  // Begins the transfer if it hasn't already begun.
85  void BeginTransfer(const std::string& url) override;
86
87  // If the transfer is in progress, aborts the transfer early.
88  // The transfer cannot be resumed.
89  void TerminateTransfer() override;
90
91  void SetHeader(const std::string& header_name,
92                 const std::string& header_value) override;
93
94  // Suspend the mock transfer.
95  void Pause() override;
96
97  // Resume the mock transfer.
98  void Unpause() override;
99
100  // Fail the transfer. This simulates a network failure.
101  void FailTransfer(int http_response_code);
102
103  // If set to true, this will EXPECT fail on BeginTransfer
104  void set_never_use(bool never_use) { never_use_ = never_use; }
105
106  const brillo::Blob& post_data() const {
107    return post_data_;
108  }
109
110 private:
111  // Sends data to the delegate and sets up a timeout callback if needed.
112  // There must be a delegate and there must be data to send. If there is
113  // already a timeout callback, and it should be deleted by the caller,
114  // this will return false; otherwise true is returned.
115  // If skip_delivery is true, no bytes will be delivered, but the callbacks
116  // still be set if needed.
117  bool SendData(bool skip_delivery);
118
119  // Callback for when our message loop timeout expires.
120  void TimeoutCallback();
121
122  // Sets the HTTP response code and signals to the delegate that the transfer
123  // is complete.
124  void SignalTransferComplete();
125
126  // A full copy of the data we'll return to the delegate
127  brillo::Blob data_;
128
129  // The number of bytes we've sent so far
130  size_t sent_size_;
131
132  // The extra headers set.
133  std::map<std::string, std::string> extra_headers_;
134
135  // The TaskId of the timeout callback. After each chunk of data sent, we
136  // time out for 0s just to make sure that run loop services other clients.
137  brillo::MessageLoop::TaskId timeout_id_;
138
139  // True iff the fetcher is paused.
140  bool paused_;
141
142  // Set to true if the transfer should fail.
143  bool fail_transfer_;
144
145  // Set to true if BeginTransfer should EXPECT fail.
146  bool never_use_;
147
148  DISALLOW_COPY_AND_ASSIGN(MockHttpFetcher);
149};
150
151}  // namespace chromeos_update_engine
152
153#endif  // UPDATE_ENGINE_COMMON_MOCK_HTTP_FETCHER_H_
154