blob: 8a3068a27a075e0272a9f2ba87b51e44dff6f8f1 [file] [log] [blame]
Ahmed Fakhry7ff0cdb2017-08-22 20:11:451// Copyright 2017 The Chromium Authors. All rights reserved.
asvitkinee6f7a58b12015-02-23 21:24:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ahmed Fakhry7ff0cdb2017-08-22 20:11:455#include "components/feedback/feedback_uploader.h"
asvitkinee6f7a58b12015-02-23 21:24:536
asvitkine9a279832015-12-18 02:35:507#include <string>
8
avibc5337b2015-12-25 23:16:339#include "base/macros.h"
asvitkinee6f7a58b12015-02-23 21:24:5310#include "base/metrics/field_trial.h"
Ahmed Fakhryaf8ab052017-07-21 21:39:0711#include "base/run_loop.h"
Gabriel Charette44db1422018-08-06 11:19:3312#include "base/task/post_task.h"
13#include "base/task/task_traits.h"
Robbie McElrathd956f862018-07-09 22:01:0214#include "base/test/bind_test_util.h"
Ahmed Fakhryaf8ab052017-07-21 21:39:0715#include "components/feedback/feedback_uploader_factory.h"
Takashi Toyoshimaf3ceca92019-02-04 07:49:0516#include "components/variations/net/variations_http_headers.h"
asvitkinee6f7a58b12015-02-23 21:24:5317#include "components/variations/variations_associated_data.h"
asvitkine9a279832015-12-18 02:35:5018#include "components/variations/variations_http_header_provider.h"
Gabriel Charettec7108742019-08-23 03:31:4019#include "content/public/test/browser_task_environment.h"
asvitkinee6f7a58b12015-02-23 21:24:5320#include "content/public/test/test_browser_context.h"
Robbie McElrathd956f862018-07-09 22:01:0221#include "net/http/http_util.h"
22#include "services/network/public/cpp/shared_url_loader_factory.h"
23#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
24#include "services/network/test/test_url_loader_factory.h"
asvitkinee6f7a58b12015-02-23 21:24:5325#include "testing/gtest/include/gtest/gtest.h"
26
27namespace feedback {
28
Ahmed Fakhryaf8ab052017-07-21 21:39:0729namespace {
30
31constexpr base::TimeDelta kTestRetryDelay =
32 base::TimeDelta::FromMilliseconds(1);
33
Robbie McElrathd956f862018-07-09 22:01:0234constexpr char kFeedbackPostUrl[] =
35 "https://www.google.com/tools/feedback/chrome/__submit";
Ahmed Fakhryaf8ab052017-07-21 21:39:0736
Ahmed Fakhrydaa7d4232018-07-02 18:11:3637void QueueReport(FeedbackUploader* uploader, const std::string& report_data) {
38 uploader->QueueReport(std::make_unique<std::string>(report_data));
39}
40
Ahmed Fakhryaf8ab052017-07-21 21:39:0741} // namespace
42
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4543class FeedbackUploaderDispatchTest : public ::testing::Test {
asvitkinee6f7a58b12015-02-23 21:24:5344 protected:
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4545 FeedbackUploaderDispatchTest()
Gabriel Charette798fde72019-08-20 22:24:0446 : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
Robbie McElrathd956f862018-07-09 22:01:0247 shared_url_loader_factory_(
48 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
49 &test_url_loader_factory_)) {}
asvitkinee6f7a58b12015-02-23 21:24:5350
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4551 ~FeedbackUploaderDispatchTest() override {
asvitkinee6f7a58b12015-02-23 21:24:5352 // Clean up registered ids.
53 variations::testing::ClearAllVariationIDs();
54 }
55
56 // Registers a field trial with the specified name and group and an associated
57 // google web property variation id.
58 void CreateFieldTrialWithId(const std::string& trial_name,
59 const std::string& group_name,
60 int variation_id) {
61 variations::AssociateGoogleVariationID(
62 variations::GOOGLE_WEB_PROPERTIES, trial_name, group_name,
63 static_cast<variations::VariationID>(variation_id));
64 base::FieldTrialList::CreateFieldTrial(trial_name, group_name)->group();
65 }
66
Robbie McElrathd956f862018-07-09 22:01:0267 scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory() {
68 return shared_url_loader_factory_;
69 }
70
71 network::TestURLLoaderFactory* test_url_loader_factory() {
72 return &test_url_loader_factory_;
73 }
74
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4575 content::BrowserContext* context() { return &context_; }
76
asvitkinee6f7a58b12015-02-23 21:24:5377 private:
Gabriel Charette798fde72019-08-20 22:24:0478 content::BrowserTaskEnvironment task_environment_;
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4579 content::TestBrowserContext context_;
Robbie McElrathd956f862018-07-09 22:01:0280 network::TestURLLoaderFactory test_url_loader_factory_;
81 scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
asvitkinee6f7a58b12015-02-23 21:24:5382
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4583 DISALLOW_COPY_AND_ASSIGN(FeedbackUploaderDispatchTest);
asvitkinee6f7a58b12015-02-23 21:24:5384};
85
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4586TEST_F(FeedbackUploaderDispatchTest, VariationHeaders) {
asvitkinee6f7a58b12015-02-23 21:24:5387 // Register a trial and variation id, so that there is data in variations
asvitkineb4ed78682015-03-12 18:18:5488 // headers. Also, the variations header provider may have been registered to
89 // observe some other field trial list, so reset it.
90 variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
asvitkinee6f7a58b12015-02-23 21:24:5391 CreateFieldTrialWithId("Test", "Group1", 123);
92
Ahmed Fakhry7ff0cdb2017-08-22 20:11:4593 FeedbackUploader uploader(
Evan Stadec34903a2019-10-09 01:15:3694 context(), FeedbackUploaderFactory::CreateUploaderTaskRunner());
95 uploader.set_url_loader_factory_for_test(shared_url_loader_factory());
asvitkinee6f7a58b12015-02-23 21:24:5396
asvitkinee6f7a58b12015-02-23 21:24:5397 net::HttpRequestHeaders headers;
Robbie McElrathd956f862018-07-09 22:01:0298 test_url_loader_factory()->SetInterceptor(
99 base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
Takashi Toyoshimaf3ceca92019-02-04 07:49:05100 EXPECT_TRUE(variations::HasVariationsHeader(request));
Robbie McElrathd956f862018-07-09 22:01:02101 }));
102
103 QueueReport(&uploader, "test");
104 base::RunLoop().RunUntilIdle();
105
asvitkineb4ed78682015-03-12 18:18:54106 variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
asvitkinee6f7a58b12015-02-23 21:24:53107}
108
Robbie McElrathd956f862018-07-09 22:01:02109TEST_F(FeedbackUploaderDispatchTest, 204Response) {
Ahmed Fakhryaf8ab052017-07-21 21:39:07110 FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay);
Ahmed Fakhry7ff0cdb2017-08-22 20:11:45111 FeedbackUploader uploader(
Evan Stadec34903a2019-10-09 01:15:36112 context(), FeedbackUploaderFactory::CreateUploaderTaskRunner());
113 uploader.set_url_loader_factory_for_test(shared_url_loader_factory());
Ahmed Fakhryaf8ab052017-07-21 21:39:07114
115 EXPECT_EQ(kTestRetryDelay, uploader.retry_delay());
116 // Successful reports should not introduce any retries, and should not
117 // increase the backoff delay.
Lucas Furukawa Gadani06902602019-09-27 20:44:27118 auto head = network::mojom::URLResponseHead::New();
Robbie McElrathd956f862018-07-09 22:01:02119 std::string headers("HTTP/1.1 204 No Content\n\n");
Lucas Furukawa Gadani06902602019-09-27 20:44:27120 head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
David Benjamin1384c0402019-04-29 18:55:52121 net::HttpUtil::AssembleRawHeaders(headers));
Robbie McElrathd956f862018-07-09 22:01:02122 network::URLLoaderCompletionStatus status;
Lucas Furukawa Gadani06902602019-09-27 20:44:27123 test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl),
124 std::move(head), "", status);
Ahmed Fakhrydaa7d4232018-07-02 18:11:36125 QueueReport(&uploader, "Successful report");
Robbie McElrathd956f862018-07-09 22:01:02126 base::RunLoop().RunUntilIdle();
127
Ahmed Fakhryaf8ab052017-07-21 21:39:07128 EXPECT_EQ(kTestRetryDelay, uploader.retry_delay());
129 EXPECT_TRUE(uploader.QueueEmpty());
Robbie McElrathd956f862018-07-09 22:01:02130}
Ahmed Fakhryaf8ab052017-07-21 21:39:07131
Robbie McElrathd956f862018-07-09 22:01:02132TEST_F(FeedbackUploaderDispatchTest, 400Response) {
133 FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay);
134 FeedbackUploader uploader(
Evan Stadec34903a2019-10-09 01:15:36135 context(), FeedbackUploaderFactory::CreateUploaderTaskRunner());
136 uploader.set_url_loader_factory_for_test(shared_url_loader_factory());
Robbie McElrathd956f862018-07-09 22:01:02137
138 EXPECT_EQ(kTestRetryDelay, uploader.retry_delay());
Ahmed Fakhryaf8ab052017-07-21 21:39:07139 // Failed reports due to client errors are not retried. No backoff delay
140 // should be doubled.
Lucas Furukawa Gadani06902602019-09-27 20:44:27141 auto head = network::mojom::URLResponseHead::New();
Robbie McElrathd956f862018-07-09 22:01:02142 std::string headers("HTTP/1.1 400 Bad Request\n\n");
Lucas Furukawa Gadani06902602019-09-27 20:44:27143 head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
David Benjamin1384c0402019-04-29 18:55:52144 net::HttpUtil::AssembleRawHeaders(headers));
Robbie McElrathd956f862018-07-09 22:01:02145 network::URLLoaderCompletionStatus status;
Lucas Furukawa Gadani06902602019-09-27 20:44:27146 test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl),
147 std::move(head), "", status);
Ahmed Fakhrydaa7d4232018-07-02 18:11:36148 QueueReport(&uploader, "Client error failed report");
Robbie McElrathd956f862018-07-09 22:01:02149 base::RunLoop().RunUntilIdle();
150
Ahmed Fakhryaf8ab052017-07-21 21:39:07151 EXPECT_EQ(kTestRetryDelay, uploader.retry_delay());
152 EXPECT_TRUE(uploader.QueueEmpty());
Robbie McElrathd956f862018-07-09 22:01:02153}
Ahmed Fakhryaf8ab052017-07-21 21:39:07154
Robbie McElrath3da795c2018-07-18 17:56:08155TEST_F(FeedbackUploaderDispatchTest, 500Response) {
Robbie McElrathd956f862018-07-09 22:01:02156 FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay);
157 FeedbackUploader uploader(
Evan Stadec34903a2019-10-09 01:15:36158 context(), FeedbackUploaderFactory::CreateUploaderTaskRunner());
159 uploader.set_url_loader_factory_for_test(shared_url_loader_factory());
Robbie McElrathd956f862018-07-09 22:01:02160
161 EXPECT_EQ(kTestRetryDelay, uploader.retry_delay());
Ahmed Fakhryaf8ab052017-07-21 21:39:07162 // Failed reports due to server errors are retried.
Lucas Furukawa Gadani06902602019-09-27 20:44:27163 auto head = network::mojom::URLResponseHead::New();
Robbie McElrathd956f862018-07-09 22:01:02164 std::string headers("HTTP/1.1 500 Server Error\n\n");
Lucas Furukawa Gadani06902602019-09-27 20:44:27165 head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
David Benjamin1384c0402019-04-29 18:55:52166 net::HttpUtil::AssembleRawHeaders(headers));
Robbie McElrathd956f862018-07-09 22:01:02167 network::URLLoaderCompletionStatus status;
Lucas Furukawa Gadani06902602019-09-27 20:44:27168 test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl),
169 std::move(head), "", status);
Ahmed Fakhrydaa7d4232018-07-02 18:11:36170 QueueReport(&uploader, "Server error failed report");
Robbie McElrathd956f862018-07-09 22:01:02171 base::RunLoop().RunUntilIdle();
172
Robbie McElrath3da795c2018-07-18 17:56:08173 EXPECT_LT(kTestRetryDelay, uploader.retry_delay());
Ahmed Fakhryaf8ab052017-07-21 21:39:07174 EXPECT_FALSE(uploader.QueueEmpty());
175}
176
asvitkinee6f7a58b12015-02-23 21:24:53177} // namespace feedback