blob: 60f9491832690e651fb9b7cce34eec6dc138af70 [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/run_loop.h"
Carlos Caballerod51a9ef132018-12-03 16:15:2715#include "base/test/scoped_task_environment.h"
[email protected]b5c2b742014-06-14 22:21:4216#include "base/test/test_simple_task_runner.h"
Carlos Caballerod51a9ef132018-12-03 16:15:2717#include "base/threading/thread_task_runner_handle.h"
[email protected]bda8e362014-03-24 18:21:0318#include "components/domain_reliability/test_util.h"
[email protected]d7599122014-05-24 03:37:2319#include "net/base/load_flags.h"
ttuttle280a73d2014-11-13 21:38:0420#include "net/http/http_response_headers.h"
ttuttle42144d8a2015-12-01 23:57:3721#include "net/http/http_response_info.h"
mikecironef22f9812016-10-04 03:40:1922#include "net/log/net_log_with_source.h"
ttuttle42144d8a2015-12-01 23:57:3723#include "net/url_request/url_request.h"
24#include "net/url_request/url_request_filter.h"
25#include "net/url_request/url_request_interceptor.h"
26#include "net/url_request/url_request_job.h"
[email protected]bda8e362014-03-24 18:21:0327#include "net/url_request/url_request_test_util.h"
28#include "testing/gtest/include/gtest/gtest.h"
29
30namespace domain_reliability {
[email protected]563dc4762014-05-11 00:43:4931namespace {
[email protected]bda8e362014-03-24 18:21:0332
ttuttle42144d8a2015-12-01 23:57:3733const char kUploadURL[] = "https://example/upload";
34
35struct MockUploadResult {
36 int net_error;
ttuttle42144d8a2015-12-01 23:57:3737 scoped_refptr<net::HttpResponseHeaders> response_headers;
38};
39
40class UploadMockURLRequestJob : public net::URLRequestJob {
41 public:
42 UploadMockURLRequestJob(net::URLRequest* request,
43 net::NetworkDelegate* network_delegate,
44 MockUploadResult result)
45 : net::URLRequestJob(request, network_delegate),
46 upload_stream_(nullptr),
47 result_(result) {
48 int load_flags = request->load_flags();
49 EXPECT_TRUE(load_flags & net::LOAD_DO_NOT_SEND_COOKIES);
50 EXPECT_TRUE(load_flags & net::LOAD_DO_NOT_SAVE_COOKIES);
51 }
52
53 protected:
54 void Start() override {
55 int rv = upload_stream_->Init(
tzik2bcf8e42018-07-31 11:22:1556 base::BindOnce(&UploadMockURLRequestJob::OnStreamInitialized,
57 base::Unretained(this)),
tfarina42834112016-09-22 13:38:2058 net::NetLogWithSource());
ttuttle42144d8a2015-12-01 23:57:3759 if (rv == net::ERR_IO_PENDING)
60 return;
61 OnStreamInitialized(rv);
62 }
63
64 void SetUpload(net::UploadDataStream* upload_stream) override {
65 upload_stream_ = upload_stream;
66 }
67
68 private:
69 ~UploadMockURLRequestJob() override {}
70
71 void OnStreamInitialized(int rv) {
72 EXPECT_EQ(net::OK, rv);
73
74 size_t upload_size = upload_stream_->size();
Victor Costan282536d2018-09-03 22:31:3175 upload_buffer_ = base::MakeRefCounted<net::IOBufferWithSize>(upload_size);
ttuttle42144d8a2015-12-01 23:57:3776 rv = upload_stream_->Read(
tzik2bcf8e42018-07-31 11:22:1577 upload_buffer_.get(), upload_size,
78 base::BindOnce(&UploadMockURLRequestJob::OnStreamRead,
79 base::Unretained(this)));
ttuttle42144d8a2015-12-01 23:57:3780 if (rv == net::ERR_IO_PENDING)
81 return;
82 OnStreamRead(rv);
83 }
84
85 void OnStreamRead(int rv) {
86 EXPECT_EQ(upload_buffer_->size(), rv);
87
88 upload_data_ = std::string(upload_buffer_->data(), upload_buffer_->size());
89 upload_buffer_ = nullptr;
90
91 if (result_.net_error == net::OK)
92 NotifyHeadersComplete();
juliatuttle127604ea2016-12-19 19:13:0493 else if (result_.net_error != net::ERR_IO_PENDING)
ttuttle42144d8a2015-12-01 23:57:3794 NotifyStartError(net::URLRequestStatus::FromError(result_.net_error));
95 }
96
ttuttle42144d8a2015-12-01 23:57:3797 void GetResponseInfo(net::HttpResponseInfo* info) override {
98 info->headers = result_.response_headers;
99 }
100
101 net::UploadDataStream* upload_stream_;
102 scoped_refptr<net::IOBufferWithSize> upload_buffer_;
103 std::string upload_data_;
104 MockUploadResult result_;
105};
106
107class UploadInterceptor : public net::URLRequestInterceptor {
108 public:
juliatuttle127604ea2016-12-19 19:13:04109 UploadInterceptor() : request_count_(0), last_upload_depth_(-1) {}
ttuttle42144d8a2015-12-01 23:57:37110
Carlos Caballerod51a9ef132018-12-03 16:15:27111 ~UploadInterceptor() override { EXPECT_TRUE(results_.empty()); }
ttuttle42144d8a2015-12-01 23:57:37112
113 net::URLRequestJob* MaybeInterceptRequest(
114 net::URLRequest* request,
115 net::NetworkDelegate* delegate) const override {
116 EXPECT_FALSE(results_.empty());
117 MockUploadResult result = results_.front();
118 results_.pop_front();
119
120 last_upload_depth_ =
121 DomainReliabilityUploader::GetURLRequestUploadDepth(*request);
122
juliatuttle127604ea2016-12-19 19:13:04123 ++request_count_;
124
ttuttle42144d8a2015-12-01 23:57:37125 return new UploadMockURLRequestJob(request, delegate, result);
126 }
127
128 void ExpectRequestAndReturnError(int net_error) {
129 MockUploadResult result;
130 result.net_error = net_error;
ttuttle42144d8a2015-12-01 23:57:37131 results_.push_back(result);
132 }
133
mmenkee0f6ab792017-04-18 18:12:12134 void ExpectRequestAndReturnResponseHeaders(const char* headers) {
ttuttle42144d8a2015-12-01 23:57:37135 MockUploadResult result;
136 result.net_error = net::OK;
ttuttle42144d8a2015-12-01 23:57:37137 result.response_headers = new net::HttpResponseHeaders(
138 net::HttpUtil::AssembleRawHeaders(headers, strlen(headers)));
139 results_.push_back(result);
140 }
141
juliatuttle127604ea2016-12-19 19:13:04142 int request_count() const { return request_count_; }
ttuttle42144d8a2015-12-01 23:57:37143 int last_upload_depth() const { return last_upload_depth_; }
144
145 private:
146 mutable std::list<MockUploadResult> results_;
juliatuttle127604ea2016-12-19 19:13:04147 mutable int request_count_;
ttuttle42144d8a2015-12-01 23:57:37148 mutable int last_upload_depth_;
149};
150
151class TestUploadCallback {
152 public:
153 TestUploadCallback() : called_count_(0u) {}
154
155 DomainReliabilityUploader::UploadCallback callback() {
156 return base::Bind(&TestUploadCallback::OnCalled, base::Unretained(this));
157 }
158
159 unsigned called_count() const { return called_count_; }
160 DomainReliabilityUploader::UploadResult last_result() const {
161 return last_result_;
162 }
163
164 private:
165 void OnCalled(const DomainReliabilityUploader::UploadResult& result) {
166 called_count_++;
167 last_result_ = result;
168 }
169
170 unsigned called_count_;
171 DomainReliabilityUploader::UploadResult last_result_;
172};
ttuttle280a73d2014-11-13 21:38:04173
[email protected]bda8e362014-03-24 18:21:03174class DomainReliabilityUploaderTest : public testing::Test {
175 protected:
176 DomainReliabilityUploaderTest()
ttuttle42144d8a2015-12-01 23:57:37177 : url_request_context_getter_(new net::TestURLRequestContextGetter(
Carlos Caballerod51a9ef132018-12-03 16:15:27178 base::ThreadTaskRunnerHandle::Get())),
ttuttle42144d8a2015-12-01 23:57:37179 interceptor_(new UploadInterceptor()),
Carlos Caballerod51a9ef132018-12-03 16:15:27180 uploader_(
181 DomainReliabilityUploader::Create(&time_,
182 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_; }
Carlos Caballerod51a9ef132018-12-03 16:15:27194 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter() {
juliatuttle127604ea2016-12-19 19:13:04195 return url_request_context_getter_;
196 }
ttuttle280a73d2014-11-13 21:38:04197
ttuttle42144d8a2015-12-01 23:57:37198 private:
Carlos Caballerod51a9ef132018-12-03 16:15:27199 base::test::ScopedTaskEnvironment task_environment_{
200 base::test::ScopedTaskEnvironment::MainThreadType::IO};
[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