blob: 4de4c67cf9afba6a846d3a47e3513e2f038f4f2d [file] [log] [blame]
[email protected]1eab4e92014-05-09 02:17:191// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]48372252013-12-20 12:18:012// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]1eab4e92014-05-09 02:17:195#include "components/feedback/feedback_uploader.h"
[email protected]48372252013-12-20 12:18:016
dcheng84c358e2016-04-26 07:05:537#include <memory>
[email protected]90cc2a9a2014-02-28 22:05:558#include <set>
9
[email protected]48372252013-12-20 12:18:0110#include "base/bind.h"
[email protected]48372252013-12-20 12:18:0111#include "base/run_loop.h"
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4512#include "base/single_thread_task_runner.h"
[email protected]1eab4e92014-05-09 02:17:1913#include "base/stl_util.h"
Gabriel Charette44db1422018-08-06 11:19:3314#include "base/task/post_task.h"
15#include "base/task/task_traits.h"
Ahmed Fakhry225aa5c2018-06-14 03:22:0216#include "base/threading/sequenced_task_runner_handle.h"
Ahmed Fakhryaf8ab052017-07-21 21:39:0717#include "components/feedback/feedback_report.h"
[email protected]1eab4e92014-05-09 02:17:1918#include "components/feedback/feedback_uploader_factory.h"
Gabriel Charettec7108742019-08-23 03:31:4019#include "content/public/test/browser_task_environment.h"
[email protected]1eab4e92014-05-09 02:17:1920#include "content/public/test/test_browser_context.h"
Robbie McElrathd956f862018-07-09 22:01:0221#include "services/network/public/cpp/shared_url_loader_factory.h"
22#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
23#include "services/network/test/test_url_loader_factory.h"
[email protected]48372252013-12-20 12:18:0124#include "testing/gtest/include/gtest/gtest.h"
25
Ahmed Fakhryaf8ab052017-07-21 21:39:0726namespace feedback {
27
[email protected]48372252013-12-20 12:18:0128namespace {
29
Ahmed Fakhryaf8ab052017-07-21 21:39:0730constexpr char kReportOne[] = "one";
31constexpr char kReportTwo[] = "two";
32constexpr char kReportThree[] = "three";
33constexpr char kReportFour[] = "four";
34constexpr char kReportFive[] = "five";
[email protected]48372252013-12-20 12:18:0135
Ahmed Fakhryaf8ab052017-07-21 21:39:0736constexpr base::TimeDelta kRetryDelayForTest =
[email protected]48372252013-12-20 12:18:0137 base::TimeDelta::FromMilliseconds(100);
38
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4539class MockFeedbackUploader : public FeedbackUploader {
Ahmed Fakhryaf8ab052017-07-21 21:39:0740 public:
Robbie McElrathd956f862018-07-09 22:01:0241 MockFeedbackUploader(
42 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
43 content::BrowserContext* context)
Evan Stadec34903a2019-10-09 01:15:3644 : FeedbackUploader(context,
45 FeedbackUploaderFactory::CreateUploaderTaskRunner()) {
46 set_url_loader_factory_for_test(url_loader_factory);
47 }
Ahmed Fakhryaf8ab052017-07-21 21:39:0748 ~MockFeedbackUploader() override {}
49
50 void RunMessageLoop() {
51 if (ProcessingComplete())
52 return;
Gyuyoung Kim6afb5082018-01-19 13:35:5753 run_loop_ = std::make_unique<base::RunLoop>();
Ahmed Fakhryaf8ab052017-07-21 21:39:0754 run_loop_->Run();
55 }
56
Ahmed Fakhry225aa5c2018-06-14 03:22:0257 void SimulateLoadingOfflineReports() {
58 task_runner()->PostTask(
59 FROM_HERE,
60 base::BindOnce(
61 &FeedbackReport::LoadReportsAndQueue, feedback_reports_path(),
Ahmed Fakhrydaa7d4232018-07-02 18:11:3662 base::BindRepeating(&MockFeedbackUploader::QueueSingleReport,
Jeffrey Kardatzkebe95a7112019-08-29 19:38:3063 base::SequencedTaskRunnerHandle::Get(),
64 AsWeakPtr())));
Ahmed Fakhry225aa5c2018-06-14 03:22:0265 }
66
Ahmed Fakhryaf8ab052017-07-21 21:39:0767 const std::map<std::string, unsigned int>& dispatched_reports() const {
68 return dispatched_reports_;
69 }
70 void set_expected_reports(size_t value) { expected_reports_ = value; }
71 void set_simulate_failure(bool value) { simulate_failure_ = value; }
72
73 private:
Ahmed Fakhry225aa5c2018-06-14 03:22:0274 static void QueueSingleReport(
75 scoped_refptr<base::SequencedTaskRunner> main_task_runner,
Jeffrey Kardatzkebe95a7112019-08-29 19:38:3076 base::WeakPtr<FeedbackUploader> uploader,
77 scoped_refptr<FeedbackReport> report) {
Ahmed Fakhry225aa5c2018-06-14 03:22:0278 main_task_runner->PostTask(
Jeffrey Kardatzkebe95a7112019-08-29 19:38:3079 FROM_HERE, base::BindOnce(&MockFeedbackUploader::RequeueReport,
80 std::move(uploader), std::move(report)));
Ahmed Fakhry225aa5c2018-06-14 03:22:0281 }
82
Ahmed Fakhryaf8ab052017-07-21 21:39:0783 // FeedbackUploaderChrome:
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4584 void StartDispatchingReport() override {
Jan Wilken Dörrie45d34f42019-06-08 09:40:5485 if (base::Contains(dispatched_reports_, report_being_dispatched()->data()))
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4586 dispatched_reports_[report_being_dispatched()->data()]++;
Ahmed Fakhryaf8ab052017-07-21 21:39:0787 else
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4588 dispatched_reports_[report_being_dispatched()->data()] = 1;
Ahmed Fakhryaf8ab052017-07-21 21:39:0789
90 dispatched_reports_count_++;
91
92 if (simulate_failure_)
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4593 OnReportUploadFailure(true /* should_retry */);
Ahmed Fakhryaf8ab052017-07-21 21:39:0794 else
95 OnReportUploadSuccess();
96
97 if (ProcessingComplete()) {
98 if (run_loop_)
99 run_loop_->Quit();
100 }
101 }
102
103 bool ProcessingComplete() {
104 return (dispatched_reports_count_ >= expected_reports_);
105 }
106
107 std::unique_ptr<base::RunLoop> run_loop_;
108 std::map<std::string, unsigned int> dispatched_reports_;
109 size_t dispatched_reports_count_ = 0;
110 size_t expected_reports_ = 0;
111 bool simulate_failure_ = false;
112
113 DISALLOW_COPY_AND_ASSIGN(MockFeedbackUploader);
114};
115
[email protected]48372252013-12-20 12:18:01116} // namespace
117
[email protected]48372252013-12-20 12:18:01118class FeedbackUploaderTest : public testing::Test {
Ahmed Fakhryaf8ab052017-07-21 21:39:07119 public:
Ahmed Fakhry7ff0cdb2017-08-22 20:11:45120 FeedbackUploaderTest() {
Ahmed Fakhryaf8ab052017-07-21 21:39:07121 FeedbackUploader::SetMinimumRetryDelayForTesting(kRetryDelayForTest);
Robbie McElrathd956f862018-07-09 22:01:02122 test_shared_loader_factory_ =
123 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
124 &test_url_loader_factory_);
Ahmed Fakhry225aa5c2018-06-14 03:22:02125 RecreateUploader();
[email protected]48372252013-12-20 12:18:01126 }
127
Ahmed Fakhry7ff0cdb2017-08-22 20:11:45128 ~FeedbackUploaderTest() override = default;
[email protected]48372252013-12-20 12:18:01129
Ahmed Fakhry225aa5c2018-06-14 03:22:02130 void RecreateUploader() {
Robbie McElrathd956f862018-07-09 22:01:02131 uploader_ = std::make_unique<MockFeedbackUploader>(
132 test_shared_loader_factory_, &context_);
Ahmed Fakhry225aa5c2018-06-14 03:22:02133 }
134
[email protected]48372252013-12-20 12:18:01135 void QueueReport(const std::string& data) {
Ahmed Fakhrydaa7d4232018-07-02 18:11:36136 uploader_->QueueReport(std::make_unique<std::string>(data));
[email protected]48372252013-12-20 12:18:01137 }
138
Ahmed Fakhry7ff0cdb2017-08-22 20:11:45139 MockFeedbackUploader* uploader() const { return uploader_.get(); }
[email protected]48372252013-12-20 12:18:01140
Ahmed Fakhryaf8ab052017-07-21 21:39:07141 private:
Robbie McElrathd956f862018-07-09 22:01:02142 network::TestURLLoaderFactory test_url_loader_factory_;
143 scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
Gabriel Charette798fde72019-08-20 22:24:04144 content::BrowserTaskEnvironment task_environment_;
Ahmed Fakhry7ff0cdb2017-08-22 20:11:45145 content::TestBrowserContext context_;
146 std::unique_ptr<MockFeedbackUploader> uploader_;
[email protected]48372252013-12-20 12:18:01147
Ahmed Fakhryaf8ab052017-07-21 21:39:07148 DISALLOW_COPY_AND_ASSIGN(FeedbackUploaderTest);
[email protected]48372252013-12-20 12:18:01149};
150
Ahmed Fakhryaf8ab052017-07-21 21:39:07151TEST_F(FeedbackUploaderTest, QueueMultiple) {
[email protected]48372252013-12-20 12:18:01152 QueueReport(kReportOne);
153 QueueReport(kReportTwo);
154 QueueReport(kReportThree);
155 QueueReport(kReportFour);
156
Ahmed Fakhryaf8ab052017-07-21 21:39:07157 EXPECT_EQ(uploader()->dispatched_reports().size(), 4u);
158 EXPECT_EQ(uploader()->dispatched_reports().at(kReportOne), 1u);
159 EXPECT_EQ(uploader()->dispatched_reports().at(kReportTwo), 1u);
160 EXPECT_EQ(uploader()->dispatched_reports().at(kReportThree), 1u);
161 EXPECT_EQ(uploader()->dispatched_reports().at(kReportFour), 1u);
[email protected]48372252013-12-20 12:18:01162}
163
Ahmed Fakhryaf8ab052017-07-21 21:39:07164TEST_F(FeedbackUploaderTest, QueueMultipleWithFailures) {
165 EXPECT_EQ(kRetryDelayForTest, uploader()->retry_delay());
[email protected]48372252013-12-20 12:18:01166 QueueReport(kReportOne);
[email protected]48372252013-12-20 12:18:01167
Ahmed Fakhryaf8ab052017-07-21 21:39:07168 // Simulate a failure in reports two and three. Make sure the backoff delay
169 // will be applied twice, and the reports will eventually be sent.
170 uploader()->set_simulate_failure(true);
171 QueueReport(kReportTwo);
172 EXPECT_EQ(kRetryDelayForTest * 2, uploader()->retry_delay());
173 QueueReport(kReportThree);
174 EXPECT_EQ(kRetryDelayForTest * 4, uploader()->retry_delay());
175 uploader()->set_simulate_failure(false);
176
177 // Once a successful report is sent, the backoff delay is reset back to its
178 // minimum value.
179 QueueReport(kReportFour);
180 EXPECT_EQ(kRetryDelayForTest, uploader()->retry_delay());
[email protected]48372252013-12-20 12:18:01181 QueueReport(kReportFive);
182
Ahmed Fakhryaf8ab052017-07-21 21:39:07183 // Wait for the pending two failed reports to be sent.
184 uploader()->set_expected_reports(7);
185 uploader()->RunMessageLoop();
[email protected]48372252013-12-20 12:18:01186
Ahmed Fakhryaf8ab052017-07-21 21:39:07187 EXPECT_EQ(uploader()->dispatched_reports().size(), 5u);
188 EXPECT_EQ(uploader()->dispatched_reports().at(kReportOne), 1u);
189 EXPECT_EQ(uploader()->dispatched_reports().at(kReportTwo), 2u);
190 EXPECT_EQ(uploader()->dispatched_reports().at(kReportThree), 2u);
191 EXPECT_EQ(uploader()->dispatched_reports().at(kReportFour), 1u);
192 EXPECT_EQ(uploader()->dispatched_reports().at(kReportFive), 1u);
[email protected]48372252013-12-20 12:18:01193}
194
Ahmed Fakhry225aa5c2018-06-14 03:22:02195TEST_F(FeedbackUploaderTest, SimulateOfflineReports) {
196 // Simulate offline reports by failing to upload three reports.
197 uploader()->set_simulate_failure(true);
198 QueueReport(kReportOne);
199 QueueReport(kReportTwo);
200 QueueReport(kReportThree);
201
202 // All three reports will be attempted to be uploaded, but the uploader queue
203 // will remain having three reports since they all failed.
204 uploader()->set_expected_reports(3);
205 uploader()->RunMessageLoop();
206 EXPECT_EQ(uploader()->dispatched_reports().size(), 3u);
207 EXPECT_FALSE(uploader()->QueueEmpty());
208
209 // Simulate a sign out / resign in by recreating the uploader. This should not
210 // clear any pending feedback report files on disk, and hence they can be
211 // reloaded.
212 RecreateUploader();
213 uploader()->SimulateLoadingOfflineReports();
214 uploader()->set_expected_reports(3);
215 uploader()->RunMessageLoop();
216
217 // The three reports were loaded, successfully uploaded, and the uploader
218 // queue is now empty.
219 EXPECT_EQ(uploader()->dispatched_reports().size(), 3u);
220 EXPECT_TRUE(uploader()->QueueEmpty());
221}
222
[email protected]48372252013-12-20 12:18:01223} // namespace feedback