[SyncFS] Add completion callback to PromoteDemotedChanges
[chromium-blink-merge.git] / net / http / http_response_body_drainer_unittest.cc
blob42efa57f919e1923042c95188f34a76202c70bd1
1 // Copyright (c) 2012 The Chromium 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.
5 #include "net/http/http_response_body_drainer.h"
7 #include <cstring>
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_completion_callback.h"
16 #include "net/http/http_network_session.h"
17 #include "net/http/http_server_properties_impl.h"
18 #include "net/http/http_stream.h"
19 #include "net/proxy/proxy_service.h"
20 #include "net/ssl/ssl_config_service_defaults.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace net {
25 namespace {
27 const int kMagicChunkSize = 1024;
28 COMPILE_ASSERT(
29 (HttpResponseBodyDrainer::kDrainBodyBufferSize % kMagicChunkSize) == 0,
30 chunk_size_needs_to_divide_evenly_into_buffer_size);
32 class CloseResultWaiter {
33 public:
34 CloseResultWaiter()
35 : result_(false),
36 have_result_(false),
37 waiting_for_result_(false) {}
39 int WaitForResult() {
40 CHECK(!waiting_for_result_);
41 while (!have_result_) {
42 waiting_for_result_ = true;
43 base::MessageLoop::current()->Run();
44 waiting_for_result_ = false;
46 return result_;
49 void set_result(bool result) {
50 result_ = result;
51 have_result_ = true;
52 if (waiting_for_result_)
53 base::MessageLoop::current()->Quit();
56 private:
57 int result_;
58 bool have_result_;
59 bool waiting_for_result_;
61 DISALLOW_COPY_AND_ASSIGN(CloseResultWaiter);
64 class MockHttpStream : public HttpStream {
65 public:
66 MockHttpStream(CloseResultWaiter* result_waiter)
67 : result_waiter_(result_waiter),
68 buf_len_(0),
69 closed_(false),
70 stall_reads_forever_(false),
71 num_chunks_(0),
72 is_sync_(false),
73 is_last_chunk_zero_size_(false),
74 is_complete_(false),
75 weak_factory_(this) {}
76 virtual ~MockHttpStream() {}
78 // HttpStream implementation.
79 virtual int InitializeStream(const HttpRequestInfo* request_info,
80 RequestPriority priority,
81 const BoundNetLog& net_log,
82 const CompletionCallback& callback) OVERRIDE {
83 return ERR_UNEXPECTED;
85 virtual int SendRequest(const HttpRequestHeaders& request_headers,
86 HttpResponseInfo* response,
87 const CompletionCallback& callback) OVERRIDE {
88 return ERR_UNEXPECTED;
90 virtual UploadProgress GetUploadProgress() const OVERRIDE {
91 return UploadProgress();
93 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
94 return ERR_UNEXPECTED;
97 virtual bool CanFindEndOfResponse() const OVERRIDE { return true; }
98 virtual bool IsConnectionReused() const OVERRIDE { return false; }
99 virtual void SetConnectionReused() OVERRIDE {}
100 virtual bool IsConnectionReusable() const OVERRIDE { return false; }
101 virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; }
102 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {}
103 virtual void GetSSLCertRequestInfo(
104 SSLCertRequestInfo* cert_request_info) OVERRIDE {}
106 // Mocked API
107 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
108 const CompletionCallback& callback) OVERRIDE;
109 virtual void Close(bool not_reusable) OVERRIDE {
110 CHECK(!closed_);
111 closed_ = true;
112 result_waiter_->set_result(not_reusable);
115 virtual HttpStream* RenewStreamForAuth() OVERRIDE {
116 return NULL;
119 virtual bool IsResponseBodyComplete() const OVERRIDE { return is_complete_; }
121 virtual bool IsSpdyHttpStream() const OVERRIDE { return false; }
123 virtual bool GetLoadTimingInfo(
124 LoadTimingInfo* load_timing_info) const OVERRIDE { return false; }
126 virtual void Drain(HttpNetworkSession*) OVERRIDE {}
128 virtual void SetPriority(RequestPriority priority) OVERRIDE {}
130 // Methods to tweak/observer mock behavior:
131 void set_stall_reads_forever() { stall_reads_forever_ = true; }
133 void set_num_chunks(int num_chunks) { num_chunks_ = num_chunks; }
135 void set_sync() { is_sync_ = true; }
137 void set_is_last_chunk_zero_size() { is_last_chunk_zero_size_ = true; }
139 private:
140 int ReadResponseBodyImpl(IOBuffer* buf, int buf_len);
141 void CompleteRead();
143 bool closed() const { return closed_; }
145 CloseResultWaiter* const result_waiter_;
146 scoped_refptr<IOBuffer> user_buf_;
147 CompletionCallback callback_;
148 int buf_len_;
149 bool closed_;
150 bool stall_reads_forever_;
151 int num_chunks_;
152 bool is_sync_;
153 bool is_last_chunk_zero_size_;
154 bool is_complete_;
155 base::WeakPtrFactory<MockHttpStream> weak_factory_;
158 int MockHttpStream::ReadResponseBody(IOBuffer* buf,
159 int buf_len,
160 const CompletionCallback& callback) {
161 CHECK(!callback.is_null());
162 CHECK(callback_.is_null());
163 CHECK(buf);
165 if (stall_reads_forever_)
166 return ERR_IO_PENDING;
168 if (is_complete_)
169 return ERR_UNEXPECTED;
171 if (!is_sync_) {
172 user_buf_ = buf;
173 buf_len_ = buf_len;
174 callback_ = callback;
175 base::MessageLoop::current()->PostTask(
176 FROM_HERE,
177 base::Bind(&MockHttpStream::CompleteRead, weak_factory_.GetWeakPtr()));
178 return ERR_IO_PENDING;
179 } else {
180 return ReadResponseBodyImpl(buf, buf_len);
184 int MockHttpStream::ReadResponseBodyImpl(IOBuffer* buf, int buf_len) {
185 if (is_last_chunk_zero_size_ && num_chunks_ == 1) {
186 buf_len = 0;
187 } else {
188 if (buf_len > kMagicChunkSize)
189 buf_len = kMagicChunkSize;
190 std::memset(buf->data(), 1, buf_len);
192 num_chunks_--;
193 if (!num_chunks_)
194 is_complete_ = true;
196 return buf_len;
199 void MockHttpStream::CompleteRead() {
200 int result = ReadResponseBodyImpl(user_buf_.get(), buf_len_);
201 user_buf_ = NULL;
202 CompletionCallback callback = callback_;
203 callback_.Reset();
204 callback.Run(result);
207 class HttpResponseBodyDrainerTest : public testing::Test {
208 protected:
209 HttpResponseBodyDrainerTest()
210 : proxy_service_(ProxyService::CreateDirect()),
211 ssl_config_service_(new SSLConfigServiceDefaults),
212 http_server_properties_(new HttpServerPropertiesImpl()),
213 session_(CreateNetworkSession()),
214 mock_stream_(new MockHttpStream(&result_waiter_)),
215 drainer_(new HttpResponseBodyDrainer(mock_stream_)) {}
217 virtual ~HttpResponseBodyDrainerTest() {}
219 HttpNetworkSession* CreateNetworkSession() const {
220 HttpNetworkSession::Params params;
221 params.proxy_service = proxy_service_.get();
222 params.ssl_config_service = ssl_config_service_.get();
223 params.http_server_properties = http_server_properties_->GetWeakPtr();
224 return new HttpNetworkSession(params);
227 scoped_ptr<ProxyService> proxy_service_;
228 scoped_refptr<SSLConfigService> ssl_config_service_;
229 scoped_ptr<HttpServerPropertiesImpl> http_server_properties_;
230 const scoped_refptr<HttpNetworkSession> session_;
231 CloseResultWaiter result_waiter_;
232 MockHttpStream* const mock_stream_; // Owned by |drainer_|.
233 HttpResponseBodyDrainer* const drainer_; // Deletes itself.
236 TEST_F(HttpResponseBodyDrainerTest, DrainBodySyncSingleOK) {
237 mock_stream_->set_num_chunks(1);
238 mock_stream_->set_sync();
239 drainer_->Start(session_.get());
240 EXPECT_FALSE(result_waiter_.WaitForResult());
243 TEST_F(HttpResponseBodyDrainerTest, DrainBodySyncOK) {
244 mock_stream_->set_num_chunks(3);
245 mock_stream_->set_sync();
246 drainer_->Start(session_.get());
247 EXPECT_FALSE(result_waiter_.WaitForResult());
250 TEST_F(HttpResponseBodyDrainerTest, DrainBodyAsyncOK) {
251 mock_stream_->set_num_chunks(3);
252 drainer_->Start(session_.get());
253 EXPECT_FALSE(result_waiter_.WaitForResult());
256 // Test the case when the final chunk is 0 bytes. This can happen when
257 // the final 0-byte chunk of a chunk-encoded http response is read in a last
258 // call to ReadResponseBody, after all data were returned from HttpStream.
259 TEST_F(HttpResponseBodyDrainerTest, DrainBodyAsyncEmptyChunk) {
260 mock_stream_->set_num_chunks(4);
261 mock_stream_->set_is_last_chunk_zero_size();
262 drainer_->Start(session_.get());
263 EXPECT_FALSE(result_waiter_.WaitForResult());
266 TEST_F(HttpResponseBodyDrainerTest, DrainBodySyncEmptyChunk) {
267 mock_stream_->set_num_chunks(4);
268 mock_stream_->set_sync();
269 mock_stream_->set_is_last_chunk_zero_size();
270 drainer_->Start(session_.get());
271 EXPECT_FALSE(result_waiter_.WaitForResult());
274 TEST_F(HttpResponseBodyDrainerTest, DrainBodySizeEqualsDrainBuffer) {
275 mock_stream_->set_num_chunks(
276 HttpResponseBodyDrainer::kDrainBodyBufferSize / kMagicChunkSize);
277 drainer_->Start(session_.get());
278 EXPECT_FALSE(result_waiter_.WaitForResult());
281 TEST_F(HttpResponseBodyDrainerTest, DrainBodyTimeOut) {
282 mock_stream_->set_num_chunks(2);
283 mock_stream_->set_stall_reads_forever();
284 drainer_->Start(session_.get());
285 EXPECT_TRUE(result_waiter_.WaitForResult());
288 TEST_F(HttpResponseBodyDrainerTest, CancelledBySession) {
289 mock_stream_->set_num_chunks(2);
290 mock_stream_->set_stall_reads_forever();
291 drainer_->Start(session_.get());
292 // HttpNetworkSession should delete |drainer_|.
295 TEST_F(HttpResponseBodyDrainerTest, DrainBodyTooLarge) {
296 int too_many_chunks =
297 HttpResponseBodyDrainer::kDrainBodyBufferSize / kMagicChunkSize;
298 too_many_chunks += 1; // Now it's too large.
300 mock_stream_->set_num_chunks(too_many_chunks);
301 drainer_->Start(session_.get());
302 EXPECT_TRUE(result_waiter_.WaitForResult());
305 } // namespace
307 } // namespace net