blob: 56c87cf9e1a9a37190eec46b43c8edb1340f95c4 [file] [log] [blame]
[email protected]2a172e42014-02-21 04:06:101// Copyright 2014 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.
4
5#include "components/rappor/log_uploader.h"
6
[email protected]ccb49262014-03-26 04:10:177#include "base/compiler_specific.h"
avif57136c12015-12-25 23:27:458#include "base/macros.h"
fdoray878014242016-06-10 04:43:549#include "base/run_loop.h"
fdoray66a9a082017-05-01 18:31:2710#include "base/test/scoped_task_environment.h"
gab7966d312016-05-11 20:35:0111#include "base/threading/thread_task_runner_handle.h"
Mark Pilgrimedc1d15632018-05-22 17:38:2312#include "net/http/http_response_headers.h"
13#include "net/http/http_status_code.h"
14#include "net/http/http_util.h"
15#include "services/network/public/cpp/shared_url_loader_factory.h"
16#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
17#include "services/network/test/test_url_loader_factory.h"
[email protected]2a172e42014-02-21 04:06:1018#include "testing/gtest/include/gtest/gtest.h"
19
20namespace rappor {
21
22namespace {
23
24const char kTestServerURL[] = "http://a.com/";
25const char kTestMimeType[] = "text/plain";
26
27class TestLogUploader : public LogUploader {
28 public:
Mark Pilgrimedc1d15632018-05-22 17:38:2329 explicit TestLogUploader(
30 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
31 : LogUploader(GURL(kTestServerURL), kTestMimeType, url_loader_factory) {
holte5a7ed7c2015-01-09 23:52:4632 Start();
[email protected]2a172e42014-02-21 04:06:1033 }
34
thestig550eecbe2016-04-22 23:55:4735 base::TimeDelta last_interval_set() const { return last_interval_set_; }
[email protected]2a172e42014-02-21 04:06:1036
37 void StartUpload() {
38 last_interval_set_ = base::TimeDelta();
39 StartScheduledUpload();
40 }
41
42 static base::TimeDelta BackOff(base::TimeDelta t) {
43 return LogUploader::BackOffUploadInterval(t);
44 }
45
46 protected:
dcheng00ea022b2014-10-21 11:24:5647 bool IsUploadScheduled() const override {
thestig550eecbe2016-04-22 23:55:4748 return !last_interval_set().is_zero();
[email protected]2a172e42014-02-21 04:06:1049 }
50
51 // Schedules a future call to StartScheduledUpload if one isn't already
52 // pending.
dcheng00ea022b2014-10-21 11:24:5653 void ScheduleNextUpload(base::TimeDelta interval) override {
[email protected]2a172e42014-02-21 04:06:1054 EXPECT_EQ(last_interval_set(), base::TimeDelta());
55 last_interval_set_ = interval;
56 }
57
58 base::TimeDelta last_interval_set_;
59
thestig550eecbe2016-04-22 23:55:4760 private:
[email protected]2a172e42014-02-21 04:06:1061 DISALLOW_COPY_AND_ASSIGN(TestLogUploader);
62};
63
64} // namespace
65
66class LogUploaderTest : public testing::Test {
67 public:
68 LogUploaderTest()
fdoray66a9a082017-05-01 18:31:2769 : scoped_task_environment_(
70 base::test::ScopedTaskEnvironment::MainThreadType::UI),
Mark Pilgrimedc1d15632018-05-22 17:38:2371 test_shared_loader_factory_(
72 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
73 &test_url_loader_factory_)) {}
[email protected]2a172e42014-02-21 04:06:1074
75 protected:
skyostilb0daa012015-06-02 19:03:4876 // Required for base::ThreadTaskRunnerHandle::Get().
fdoray66a9a082017-05-01 18:31:2777 base::test::ScopedTaskEnvironment scoped_task_environment_;
Mark Pilgrimedc1d15632018-05-22 17:38:2378 network::TestURLLoaderFactory test_url_loader_factory_;
79 scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
[email protected]2a172e42014-02-21 04:06:1080
thestig550eecbe2016-04-22 23:55:4781 private:
[email protected]2a172e42014-02-21 04:06:1082 DISALLOW_COPY_AND_ASSIGN(LogUploaderTest);
83};
84
85TEST_F(LogUploaderTest, Success) {
Mark Pilgrimedc1d15632018-05-22 17:38:2386 TestLogUploader uploader(test_shared_loader_factory_);
87 test_url_loader_factory_.AddResponse(kTestServerURL, "");
[email protected]2a172e42014-02-21 04:06:1088
89 uploader.QueueLog("log1");
fdoray878014242016-06-10 04:43:5490 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:1091 // Log should be discarded instead of retransmitted.
92 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
93}
94
95TEST_F(LogUploaderTest, Rejection) {
Mark Pilgrimedc1d15632018-05-22 17:38:2396 TestLogUploader uploader(test_shared_loader_factory_);
[email protected]2a172e42014-02-21 04:06:1097
Mark Pilgrimedc1d15632018-05-22 17:38:2398 network::ResourceResponseHead response_head;
99 std::string headers("HTTP/1.1 400 Bad Request\nContent-type: text/html\n\n");
100 response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
101 net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
102 response_head.mime_type = "text/html";
103 test_url_loader_factory_.AddResponse(GURL(kTestServerURL), response_head, "",
104 network::URLLoaderCompletionStatus());
[email protected]2a172e42014-02-21 04:06:10105
106 uploader.QueueLog("log1");
fdoray878014242016-06-10 04:43:54107 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:10108 // Log should be discarded instead of retransmitted.
109 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
110}
111
112TEST_F(LogUploaderTest, Failure) {
Mark Pilgrimedc1d15632018-05-22 17:38:23113 TestLogUploader uploader(test_shared_loader_factory_);
[email protected]2a172e42014-02-21 04:06:10114
Mark Pilgrimedc1d15632018-05-22 17:38:23115 network::ResourceResponseHead response_head;
116 std::string headers(
117 "HTTP/1.1 500 Internal Server Error\nContent-type: text/html\n\n");
118 response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
119 net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
120 response_head.mime_type = "text/html";
121 test_url_loader_factory_.AddResponse(GURL(kTestServerURL), response_head, "",
122 network::URLLoaderCompletionStatus());
[email protected]2a172e42014-02-21 04:06:10123
124 uploader.QueueLog("log1");
fdoray878014242016-06-10 04:43:54125 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:10126 // Log should be scheduled for retransmission.
127 base::TimeDelta error_interval = uploader.last_interval_set();
128 EXPECT_GT(error_interval, base::TimeDelta());
129
130 for (int i = 0; i < 10; i++) {
131 uploader.QueueLog("logX");
132 }
133
134 // A second failure should lead to a longer interval, and the log should
135 // be discarded due to full queue.
136 uploader.StartUpload();
fdoray878014242016-06-10 04:43:54137 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:10138 EXPECT_GT(uploader.last_interval_set(), error_interval);
139
Mark Pilgrimedc1d15632018-05-22 17:38:23140 test_url_loader_factory_.AddResponse(kTestServerURL, "");
[email protected]2a172e42014-02-21 04:06:10141
142 // A success should revert to base interval while queue is not empty.
143 for (int i = 0; i < 9; i++) {
144 uploader.StartUpload();
fdoray878014242016-06-10 04:43:54145 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:10146 EXPECT_LT(uploader.last_interval_set(), error_interval);
147 }
148
149 // Queue should be empty.
150 uploader.StartUpload();
fdoray878014242016-06-10 04:43:54151 base::RunLoop().RunUntilIdle();
[email protected]2a172e42014-02-21 04:06:10152 EXPECT_EQ(uploader.last_interval_set(), base::TimeDelta());
153}
154
155TEST_F(LogUploaderTest, Backoff) {
156 base::TimeDelta current = base::TimeDelta();
157 base::TimeDelta next = base::TimeDelta::FromSeconds(1);
158 // Backoff until the maximum is reached.
159 while (next > current) {
160 current = next;
161 next = TestLogUploader::BackOff(current);
162 }
163 // Maximum backoff should have been reached.
164 EXPECT_EQ(next, current);
165}
166
167} // namespace rappor