Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 5 | #include "components/feedback/feedback_uploader.h" |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 6 | |
asvitkine | 9a27983 | 2015-12-18 02:35:50 | [diff] [blame] | 7 | #include <string> |
| 8 | |
avi | bc5337b | 2015-12-25 23:16:33 | [diff] [blame] | 9 | #include "base/macros.h" |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 10 | #include "base/metrics/field_trial.h" |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 11 | #include "base/run_loop.h" |
Gabriel Charette | 44db142 | 2018-08-06 11:19:33 | [diff] [blame] | 12 | #include "base/task/post_task.h" |
| 13 | #include "base/task/task_traits.h" |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 14 | #include "base/test/bind_test_util.h" |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 15 | #include "components/feedback/feedback_uploader_factory.h" |
Takashi Toyoshima | f3ceca9 | 2019-02-04 07:49:05 | [diff] [blame] | 16 | #include "components/variations/net/variations_http_headers.h" |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 17 | #include "components/variations/variations_associated_data.h" |
asvitkine | 9a27983 | 2015-12-18 02:35:50 | [diff] [blame] | 18 | #include "components/variations/variations_http_header_provider.h" |
Gabriel Charette | c710874 | 2019-08-23 03:31:40 | [diff] [blame] | 19 | #include "content/public/test/browser_task_environment.h" |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 20 | #include "content/public/test/test_browser_context.h" |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 21 | #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" |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 25 | #include "testing/gtest/include/gtest/gtest.h" |
| 26 | |
| 27 | namespace feedback { |
| 28 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 29 | namespace { |
| 30 | |
| 31 | constexpr base::TimeDelta kTestRetryDelay = |
| 32 | base::TimeDelta::FromMilliseconds(1); |
| 33 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 34 | constexpr char kFeedbackPostUrl[] = |
| 35 | "https://www.google.com/tools/feedback/chrome/__submit"; |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 36 | |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 37 | void QueueReport(FeedbackUploader* uploader, const std::string& report_data) { |
| 38 | uploader->QueueReport(std::make_unique<std::string>(report_data)); |
| 39 | } |
| 40 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 41 | } // namespace |
| 42 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 43 | class FeedbackUploaderDispatchTest : public ::testing::Test { |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 44 | protected: |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 45 | FeedbackUploaderDispatchTest() |
Gabriel Charette | 798fde7 | 2019-08-20 22:24:04 | [diff] [blame] | 46 | : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 47 | shared_url_loader_factory_( |
| 48 | base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( |
| 49 | &test_url_loader_factory_)) {} |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 50 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 51 | ~FeedbackUploaderDispatchTest() override { |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 52 | // 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 McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 67 | 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 Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 75 | content::BrowserContext* context() { return &context_; } |
| 76 | |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 77 | private: |
Gabriel Charette | 798fde7 | 2019-08-20 22:24:04 | [diff] [blame] | 78 | content::BrowserTaskEnvironment task_environment_; |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 79 | content::TestBrowserContext context_; |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 80 | network::TestURLLoaderFactory test_url_loader_factory_; |
| 81 | scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 82 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 83 | DISALLOW_COPY_AND_ASSIGN(FeedbackUploaderDispatchTest); |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 84 | }; |
| 85 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 86 | TEST_F(FeedbackUploaderDispatchTest, VariationHeaders) { |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 87 | // Register a trial and variation id, so that there is data in variations |
asvitkine | b4ed7868 | 2015-03-12 18:18:54 | [diff] [blame] | 88 | // 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(); |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 91 | CreateFieldTrialWithId("Test", "Group1", 123); |
| 92 | |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 93 | FeedbackUploader uploader( |
Evan Stade | c34903a | 2019-10-09 01:15:36 | [diff] [blame] | 94 | context(), FeedbackUploaderFactory::CreateUploaderTaskRunner()); |
| 95 | uploader.set_url_loader_factory_for_test(shared_url_loader_factory()); |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 96 | |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 97 | net::HttpRequestHeaders headers; |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 98 | test_url_loader_factory()->SetInterceptor( |
| 99 | base::BindLambdaForTesting([&](const network::ResourceRequest& request) { |
Takashi Toyoshima | f3ceca9 | 2019-02-04 07:49:05 | [diff] [blame] | 100 | EXPECT_TRUE(variations::HasVariationsHeader(request)); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 101 | })); |
| 102 | |
| 103 | QueueReport(&uploader, "test"); |
| 104 | base::RunLoop().RunUntilIdle(); |
| 105 | |
asvitkine | b4ed7868 | 2015-03-12 18:18:54 | [diff] [blame] | 106 | variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 107 | } |
| 108 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 109 | TEST_F(FeedbackUploaderDispatchTest, 204Response) { |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 110 | FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay); |
Ahmed Fakhry | 7ff0cdb | 2017-08-22 20:11:45 | [diff] [blame] | 111 | FeedbackUploader uploader( |
Evan Stade | c34903a | 2019-10-09 01:15:36 | [diff] [blame] | 112 | context(), FeedbackUploaderFactory::CreateUploaderTaskRunner()); |
| 113 | uploader.set_url_loader_factory_for_test(shared_url_loader_factory()); |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 114 | |
| 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 Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 118 | auto head = network::mojom::URLResponseHead::New(); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 119 | std::string headers("HTTP/1.1 204 No Content\n\n"); |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 120 | head->headers = base::MakeRefCounted<net::HttpResponseHeaders>( |
David Benjamin | 1384c040 | 2019-04-29 18:55:52 | [diff] [blame] | 121 | net::HttpUtil::AssembleRawHeaders(headers)); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 122 | network::URLLoaderCompletionStatus status; |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 123 | test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl), |
| 124 | std::move(head), "", status); |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 125 | QueueReport(&uploader, "Successful report"); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 126 | base::RunLoop().RunUntilIdle(); |
| 127 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 128 | EXPECT_EQ(kTestRetryDelay, uploader.retry_delay()); |
| 129 | EXPECT_TRUE(uploader.QueueEmpty()); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 130 | } |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 131 | |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 132 | TEST_F(FeedbackUploaderDispatchTest, 400Response) { |
| 133 | FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay); |
| 134 | FeedbackUploader uploader( |
Evan Stade | c34903a | 2019-10-09 01:15:36 | [diff] [blame] | 135 | context(), FeedbackUploaderFactory::CreateUploaderTaskRunner()); |
| 136 | uploader.set_url_loader_factory_for_test(shared_url_loader_factory()); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 137 | |
| 138 | EXPECT_EQ(kTestRetryDelay, uploader.retry_delay()); |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 139 | // Failed reports due to client errors are not retried. No backoff delay |
| 140 | // should be doubled. |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 141 | auto head = network::mojom::URLResponseHead::New(); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 142 | std::string headers("HTTP/1.1 400 Bad Request\n\n"); |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 143 | head->headers = base::MakeRefCounted<net::HttpResponseHeaders>( |
David Benjamin | 1384c040 | 2019-04-29 18:55:52 | [diff] [blame] | 144 | net::HttpUtil::AssembleRawHeaders(headers)); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 145 | network::URLLoaderCompletionStatus status; |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 146 | test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl), |
| 147 | std::move(head), "", status); |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 148 | QueueReport(&uploader, "Client error failed report"); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 149 | base::RunLoop().RunUntilIdle(); |
| 150 | |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 151 | EXPECT_EQ(kTestRetryDelay, uploader.retry_delay()); |
| 152 | EXPECT_TRUE(uploader.QueueEmpty()); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 153 | } |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 154 | |
Robbie McElrath | 3da795c | 2018-07-18 17:56:08 | [diff] [blame] | 155 | TEST_F(FeedbackUploaderDispatchTest, 500Response) { |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 156 | FeedbackUploader::SetMinimumRetryDelayForTesting(kTestRetryDelay); |
| 157 | FeedbackUploader uploader( |
Evan Stade | c34903a | 2019-10-09 01:15:36 | [diff] [blame] | 158 | context(), FeedbackUploaderFactory::CreateUploaderTaskRunner()); |
| 159 | uploader.set_url_loader_factory_for_test(shared_url_loader_factory()); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 160 | |
| 161 | EXPECT_EQ(kTestRetryDelay, uploader.retry_delay()); |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 162 | // Failed reports due to server errors are retried. |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 163 | auto head = network::mojom::URLResponseHead::New(); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 164 | std::string headers("HTTP/1.1 500 Server Error\n\n"); |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 165 | head->headers = base::MakeRefCounted<net::HttpResponseHeaders>( |
David Benjamin | 1384c040 | 2019-04-29 18:55:52 | [diff] [blame] | 166 | net::HttpUtil::AssembleRawHeaders(headers)); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 167 | network::URLLoaderCompletionStatus status; |
Lucas Furukawa Gadani | 0690260 | 2019-09-27 20:44:27 | [diff] [blame] | 168 | test_url_loader_factory()->AddResponse(GURL(kFeedbackPostUrl), |
| 169 | std::move(head), "", status); |
Ahmed Fakhry | daa7d423 | 2018-07-02 18:11:36 | [diff] [blame] | 170 | QueueReport(&uploader, "Server error failed report"); |
Robbie McElrath | d956f86 | 2018-07-09 22:01:02 | [diff] [blame] | 171 | base::RunLoop().RunUntilIdle(); |
| 172 | |
Robbie McElrath | 3da795c | 2018-07-18 17:56:08 | [diff] [blame] | 173 | EXPECT_LT(kTestRetryDelay, uploader.retry_delay()); |
Ahmed Fakhry | af8ab05 | 2017-07-21 21:39:07 | [diff] [blame] | 174 | EXPECT_FALSE(uploader.QueueEmpty()); |
| 175 | } |
| 176 | |
asvitkine | e6f7a58b1 | 2015-02-23 21:24:53 | [diff] [blame] | 177 | } // namespace feedback |