blob: 708d99792b81c275e1d8b97932900106b6e4c1e1 [file] [log] [blame]
ttuttle42144d8a2015-12-01 23:57:371// Copyright 2015 The Chromium Authors. All rights reserved.
[email protected]bda8e362014-03-24 18:21:032// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/domain_reliability/uploader.h"
6
avibc5337b2015-12-25 23:16:337#include <stddef.h>
8
dcheng04a35cd2016-04-22 15:07:249#include <memory>
mikecironef22f9812016-10-04 03:40:1910#include <string>
dcheng04a35cd2016-04-22 15:07:2411
[email protected]bda8e362014-03-24 18:21:0312#include "base/bind.h"
dcheng04a35cd2016-04-22 15:07:2413#include "base/memory/ptr_util.h"
ttuttle42144d8a2015-12-01 23:57:3714#include "base/message_loop/message_loop.h"
15#include "base/run_loop.h"
[email protected]b5c2b742014-06-14 22:21:4216#include "base/test/test_simple_task_runner.h"
[email protected]bda8e362014-03-24 18:21:0317#include "components/domain_reliability/test_util.h"
[email protected]d7599122014-05-24 03:37:2318#include "net/base/load_flags.h"
ttuttle280a73d2014-11-13 21:38:0419#include "net/http/http_response_headers.h"
ttuttle42144d8a2015-12-01 23:57:3720#include "net/http/http_response_info.h"
mikecironef22f9812016-10-04 03:40:1921#include "net/log/net_log_with_source.h"
ttuttle42144d8a2015-12-01 23:57:3722#include "net/url_request/url_request.h"
23#include "net/url_request/url_request_filter.h"
24#include "net/url_request/url_request_interceptor.h"
25#include "net/url_request/url_request_job.h"
[email protected]bda8e362014-03-24 18:21:0326#include "net/url_request/url_request_test_util.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29namespace domain_reliability {
[email protected]563dc4762014-05-11 00:43:4930namespace {
[email protected]bda8e362014-03-24 18:21:0331
ttuttle42144d8a2015-12-01 23:57:3732const char kUploadURL[] = "https://example/upload";
33
34struct MockUploadResult {
35 int net_error;
ttuttle42144d8a2015-12-01 23:57:3736 scoped_refptr<net::HttpResponseHeaders> response_headers;
37};
38
39class UploadMockURLRequestJob : public net::URLRequestJob {
40 public:
41 UploadMockURLRequestJob(net::URLRequest* request,
42 net::NetworkDelegate* network_delegate,
43 MockUploadResult result)
44 : net::URLRequestJob(request, network_delegate),
45 upload_stream_(nullptr),
46 result_(result) {
47 int load_flags = request->load_flags();
48 EXPECT_TRUE(load_flags & net::LOAD_DO_NOT_SEND_COOKIES);
49 EXPECT_TRUE(load_flags & net::LOAD_DO_NOT_SAVE_COOKIES);
50 }
51
52 protected:
53 void Start() override {
54 int rv = upload_stream_->Init(
tzik2bcf8e42018-07-31 11:22:1555 base::BindOnce(&UploadMockURLRequestJob::OnStreamInitialized,
56 base::Unretained(this)),
tfarina42834112016-09-22 13:38:2057 net::NetLogWithSource());
ttuttle42144d8a2015-12-01 23:57:3758 if (rv == net::ERR_IO_PENDING)
59 return;
60 OnStreamInitialized(rv);
61 }
62
63 void SetUpload(net::UploadDataStream* upload_stream) override {
64 upload_stream_ = upload_stream;
65 }
66
67 private:
68 ~UploadMockURLRequestJob() override {}
69
70 void OnStreamInitialized(int rv) {
71 EXPECT_EQ(net::OK, rv);
72
73 size_t upload_size = upload_stream_->size();
74 upload_buffer_ = new net::IOBufferWithSize(upload_size);
75 rv = upload_stream_->Read(
tzik2bcf8e42018-07-31 11:22:1576 upload_buffer_.get(), upload_size,
77 base::BindOnce(&UploadMockURLRequestJob::OnStreamRead,
78 base::Unretained(this)));
ttuttle42144d8a2015-12-01 23:57:3779 if (rv == net::ERR_IO_PENDING)
80 return;
81 OnStreamRead(rv);
82 }
83
84 void OnStreamRead(int rv) {
85 EXPECT_EQ(upload_buffer_->size(), rv);
86
87 upload_data_ = std::string(upload_buffer_->data(), upload_buffer_->size());
88 upload_buffer_ = nullptr;
89
90 if (result_.net_error == net::OK)
91 NotifyHeadersComplete();
juliatuttle127604ea2016-12-19 19:13:0492 else if (result_.net_error != net::ERR_IO_PENDING)
ttuttle42144d8a2015-12-01 23:57:3793 NotifyStartError(net::URLRequestStatus::FromError(result_.net_error));
94 }
95
ttuttle42144d8a2015-12-01 23:57:3796 void GetResponseInfo(net::HttpResponseInfo* info) override {
97 info->headers = result_.response_headers;
98 }
99
100 net::UploadDataStream* upload_stream_;
101 scoped_refptr<net::IOBufferWithSize> upload_buffer_;
102 std::string upload_data_;
103 MockUploadResult result_;
104};
105
106class UploadInterceptor : public net::URLRequestInterceptor {
107 public:
juliatuttle127604ea2016-12-19 19:13:04108 UploadInterceptor() : request_count_(0), last_upload_depth_(-1) {}
ttuttle42144d8a2015-12-01 23:57:37109
110 ~UploadInterceptor() override {
111 EXPECT_TRUE(results_.empty());
112 }
113
114 net::URLRequestJob* MaybeInterceptRequest(
115 net::URLRequest* request,
116 net::NetworkDelegate* delegate) const override {
117 EXPECT_FALSE(results_.empty());
118 MockUploadResult result = results_.front();
119 results_.pop_front();
120
121 last_upload_depth_ =
122 DomainReliabilityUploader::GetURLRequestUploadDepth(*request);
123
juliatuttle127604ea2016-12-19 19:13:04124 ++request_count_;
125
ttuttle42144d8a2015-12-01 23:57:37126 return new UploadMockURLRequestJob(request, delegate, result);
127 }
128
129 void ExpectRequestAndReturnError(int net_error) {
130 MockUploadResult result;
131 result.net_error = net_error;
ttuttle42144d8a2015-12-01 23:57:37132 results_.push_back(result);
133 }
134
mmenkee0f6ab792017-04-18 18:12:12135 void ExpectRequestAndReturnResponseHeaders(const char* headers) {
ttuttle42144d8a2015-12-01 23:57:37136 MockUploadResult result;
137 result.net_error = net::OK;
ttuttle42144d8a2015-12-01 23:57:37138 result.response_headers = new net::HttpResponseHeaders(
139 net::HttpUtil::AssembleRawHeaders(headers, strlen(headers)));
140 results_.push_back(result);
141 }
142
juliatuttle127604ea2016-12-19 19:13:04143 int request_count() const { return request_count_; }
ttuttle42144d8a2015-12-01 23:57:37144 int last_upload_depth() const { return last_upload_depth_; }
145
146 private:
147 mutable std::list<MockUploadResult> results_;
juliatuttle127604ea2016-12-19 19:13:04148 mutable int request_count_;
ttuttle42144d8a2015-12-01 23:57:37149 mutable int last_upload_depth_;
150};
151
152class TestUploadCallback {
153 public:
154 TestUploadCallback() : called_count_(0u) {}
155
156 DomainReliabilityUploader::UploadCallback callback() {
157 return base::Bind(&TestUploadCallback::OnCalled, base::Unretained(this));
158 }
159
160 unsigned called_count() const { return called_count_; }
161 DomainReliabilityUploader::UploadResult last_result() const {
162 return last_result_;
163 }
164
165 private:
166 void OnCalled(const DomainReliabilityUploader::UploadResult& result) {
167 called_count_++;
168 last_result_ = result;
169 }
170
171 unsigned called_count_;
172 DomainReliabilityUploader::UploadResult last_result_;
173};
ttuttle280a73d2014-11-13 21:38:04174
[email protected]bda8e362014-03-24 18:21:03175class DomainReliabilityUploaderTest : public testing::Test {
176 protected:
177 DomainReliabilityUploaderTest()
ttuttle42144d8a2015-12-01 23:57:37178 : url_request_context_getter_(new net::TestURLRequestContextGetter(
179 message_loop_.task_runner())),
180 interceptor_(new UploadInterceptor()),
[email protected]bda8e362014-03-24 18:21:03181 uploader_(DomainReliabilityUploader::Create(
ttuttle280a73d2014-11-13 21:38:04182 &time_, url_request_context_getter_)) {
ttuttle42144d8a2015-12-01 23:57:37183 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
dcheng04a35cd2016-04-22 15:07:24184 GURL(kUploadURL), base::WrapUnique(interceptor_));
Julia Tuttle30b169652017-10-16 20:19:08185 uploader_->SetDiscardUploads(false);
ttuttlefa8427f92014-08-25 19:38:03186 }
[email protected]bda8e362014-03-24 18:21:03187
ttuttle42144d8a2015-12-01 23:57:37188 ~DomainReliabilityUploaderTest() override {
189 net::URLRequestFilter::GetInstance()->ClearHandlers();
[email protected]bda8e362014-03-24 18:21:03190 }
191
ttuttle42144d8a2015-12-01 23:57:37192 DomainReliabilityUploader* uploader() const { return uploader_.get(); }
193 UploadInterceptor* interceptor() const { return interceptor_; }
juliatuttle127604ea2016-12-19 19:13:04194 scoped_refptr<net::TestURLRequestContextGetter>
195 url_request_context_getter() {
196 return url_request_context_getter_;
197 }
ttuttle280a73d2014-11-13 21:38:04198
ttuttle42144d8a2015-12-01 23:57:37199 private:
200 base::MessageLoopForIO message_loop_;
[email protected]bda8e362014-03-24 18:21:03201 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
ttuttle42144d8a2015-12-01 23:57:37202 UploadInterceptor* interceptor_;
ttuttle280a73d2014-11-13 21:38:04203 MockTime time_;
dcheng04a35cd2016-04-22 15:07:24204 std::unique_ptr<DomainReliabilityUploader> uploader_;
[email protected]bda8e362014-03-24 18:21:03205};
206
ttuttle42144d8a2015-12-01 23:57:37207TEST_F(DomainReliabilityUploaderTest, Null) {
juliatuttle127604ea2016-12-19 19:13:04208 uploader()->Shutdown();
[email protected]bda8e362014-03-24 18:21:03209}
210
211TEST_F(DomainReliabilityUploaderTest, SuccessfulUpload) {
mmenkee0f6ab792017-04-18 18:12:12212 interceptor()->ExpectRequestAndReturnResponseHeaders("HTTP/1.1 200\r\n\r\n");
ttuttle42144d8a2015-12-01 23:57:37213
214 TestUploadCallback c;
215 uploader()->UploadReport("{}", 0, GURL(kUploadURL), c.callback());
216 base::RunLoop().RunUntilIdle();
217 EXPECT_EQ(1u, c.called_count());
218 EXPECT_TRUE(c.last_result().is_success());
juliatuttle127604ea2016-12-19 19:13:04219
220 uploader()->Shutdown();
[email protected]bda8e362014-03-24 18:21:03221}
222
ttuttle42144d8a2015-12-01 23:57:37223TEST_F(DomainReliabilityUploaderTest, NetworkErrorUpload) {
224 interceptor()->ExpectRequestAndReturnError(net::ERR_CONNECTION_REFUSED);
225
226 TestUploadCallback c;
227 uploader()->UploadReport("{}", 0, GURL(kUploadURL), c.callback());
228 base::RunLoop().RunUntilIdle();
229 EXPECT_EQ(1u, c.called_count());
230 EXPECT_TRUE(c.last_result().is_failure());
juliatuttle127604ea2016-12-19 19:13:04231
232 uploader()->Shutdown();
ttuttled42b14632014-11-19 00:40:29233}
234
ttuttle42144d8a2015-12-01 23:57:37235TEST_F(DomainReliabilityUploaderTest, ServerErrorUpload) {
mmenkee0f6ab792017-04-18 18:12:12236 interceptor()->ExpectRequestAndReturnResponseHeaders("HTTP/1.1 500\r\n\r\n");
ttuttle42144d8a2015-12-01 23:57:37237
238 TestUploadCallback c;
239 uploader()->UploadReport("{}", 0, GURL(kUploadURL), c.callback());
240 base::RunLoop().RunUntilIdle();
241 EXPECT_EQ(1u, c.called_count());
242 EXPECT_TRUE(c.last_result().is_failure());
juliatuttle127604ea2016-12-19 19:13:04243
244 uploader()->Shutdown();
ttuttle280a73d2014-11-13 21:38:04245}
246
247TEST_F(DomainReliabilityUploaderTest, RetryAfterUpload) {
mmenkee0f6ab792017-04-18 18:12:12248 interceptor()->ExpectRequestAndReturnResponseHeaders(
ttuttle42144d8a2015-12-01 23:57:37249 "HTTP/1.1 503 Ugh\nRetry-After: 3600\n\n");
250
251 TestUploadCallback c;
252 uploader()->UploadReport("{}", 0, GURL(kUploadURL), c.callback());
253 base::RunLoop().RunUntilIdle();
254 EXPECT_EQ(1u, c.called_count());
255 EXPECT_TRUE(c.last_result().is_retry_after());
juliatuttle127604ea2016-12-19 19:13:04256
257 uploader()->Shutdown();
[email protected]bda8e362014-03-24 18:21:03258}
259
ttuttle42144d8a2015-12-01 23:57:37260TEST_F(DomainReliabilityUploaderTest, UploadDepth1) {
mmenkee0f6ab792017-04-18 18:12:12261 interceptor()->ExpectRequestAndReturnResponseHeaders("HTTP/1.1 200\r\n\r\n");
ttuttle42144d8a2015-12-01 23:57:37262
263 TestUploadCallback c;
264 uploader()->UploadReport("{}", 0, GURL(kUploadURL), c.callback());
265 base::RunLoop().RunUntilIdle();
266 EXPECT_EQ(1u, c.called_count());
267
268 EXPECT_EQ(1, interceptor()->last_upload_depth());
juliatuttle127604ea2016-12-19 19:13:04269
270 uploader()->Shutdown();
ttuttle42144d8a2015-12-01 23:57:37271}
272
273TEST_F(DomainReliabilityUploaderTest, UploadDepth2) {
mmenkee0f6ab792017-04-18 18:12:12274 interceptor()->ExpectRequestAndReturnResponseHeaders("HTTP/1.1 200\r\n\r\n");
ttuttle42144d8a2015-12-01 23:57:37275
276 TestUploadCallback c;
277 uploader()->UploadReport("{}", 1, GURL(kUploadURL), c.callback());
278 base::RunLoop().RunUntilIdle();
279 EXPECT_EQ(1u, c.called_count());
280
281 EXPECT_EQ(2, interceptor()->last_upload_depth());
juliatuttle127604ea2016-12-19 19:13:04282
283 uploader()->Shutdown();
284}
285
286TEST_F(DomainReliabilityUploaderTest, UploadCanceledAtShutdown) {
287 interceptor()->ExpectRequestAndReturnError(net::ERR_IO_PENDING);
288
289 TestUploadCallback c;
290 uploader()->UploadReport("{}", 1, GURL(kUploadURL), c.callback());
291 base::RunLoop().RunUntilIdle();
292 EXPECT_EQ(1, interceptor()->request_count());
293 EXPECT_EQ(0u, c.called_count());
294
295 uploader()->Shutdown();
296
297 EXPECT_EQ(0u, c.called_count());
298
299 url_request_context_getter()->GetURLRequestContext()->AssertNoURLRequests();
300}
301
302TEST_F(DomainReliabilityUploaderTest, NoUploadAfterShutdown) {
303 uploader()->Shutdown();
304
305 TestUploadCallback c;
306 uploader()->UploadReport("{}", 1, GURL(kUploadURL), c.callback());
307 base::RunLoop().RunUntilIdle();
308 EXPECT_EQ(1u, c.called_count());
309 EXPECT_EQ(0, interceptor()->request_count());
ttuttlefa8427f92014-08-25 19:38:03310}
311
[email protected]563dc4762014-05-11 00:43:49312} // namespace
[email protected]bda8e362014-03-24 18:21:03313} // namespace domain_reliability