Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: chrome/browser/chromeos/policy/upload_job_unittest.cc

Issue 1875443003: Retry uploading in UploadJobImpl when error occurs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unused include Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/policy/upload_job.h" 5 #include "chrome/browser/chromeos/policy/upload_job.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <queue> 9 #include <queue>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/run_loop.h" 18 #include "base/run_loop.h"
19 #include "base/single_thread_task_runner.h" 19 #include "base/sequenced_task_runner.h"
20 #include "base/thread_task_runner_handle.h" 20 #include "base/thread_task_runner_handle.h"
21 #include "base/time/time.h" 21 #include "base/time/time.h"
22 #include "chrome/browser/chromeos/policy/upload_job_impl.h" 22 #include "chrome/browser/chromeos/policy/upload_job_impl.h"
23 #include "content/public/test/test_browser_thread_bundle.h" 23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "google_apis/gaia/fake_oauth2_token_service.h" 24 #include "google_apis/gaia/fake_oauth2_token_service.h"
25 #include "google_apis/gaia/google_service_auth_error.h" 25 #include "google_apis/gaia/google_service_auth_error.h"
26 #include "net/http/http_status_code.h" 26 #include "net/http/http_status_code.h"
27 #include "net/test/embedded_test_server/embedded_test_server.h" 27 #include "net/test/embedded_test_server/embedded_test_server.h"
28 #include "net/test/embedded_test_server/http_request.h" 28 #include "net/test/embedded_test_server/http_request.h"
29 #include "net/test/embedded_test_server/http_response.h" 29 #include "net/test/embedded_test_server/http_response.h"
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 const std::string& access_token) { 147 const std::string& access_token) {
148 SetTokenInvalid(access_token); 148 SetTokenInvalid(access_token);
149 } 149 }
150 150
151 } // namespace 151 } // namespace
152 152
153 class UploadJobTestBase : public testing::Test, public UploadJob::Delegate { 153 class UploadJobTestBase : public testing::Test, public UploadJob::Delegate {
154 public: 154 public:
155 UploadJobTestBase() 155 UploadJobTestBase()
156 : test_browser_thread_bundle_( 156 : test_browser_thread_bundle_(
157 content::TestBrowserThreadBundle::IO_MAINLOOP) {} 157 content::TestBrowserThreadBundle::IO_MAINLOOP),
158 task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
158 159
159 // policy::UploadJob::Delegate: 160 // policy::UploadJob::Delegate:
160 void OnSuccess() override { 161 void OnSuccess() override {
161 if (!expected_error_) 162 if (!expected_error_)
162 run_loop_.Quit(); 163 run_loop_.Quit();
163 else 164 else
164 FAIL(); 165 FAIL();
165 } 166 }
166 167
167 // policy::UploadJob::Delegate: 168 // policy::UploadJob::Delegate:
168 void OnFailure(UploadJob::ErrorCode error_code) override { 169 void OnFailure(UploadJob::ErrorCode error_code) override {
169 if (expected_error_ && *expected_error_.get() == error_code) 170 if (expected_error_ && *expected_error_.get() == error_code)
170 run_loop_.Quit(); 171 run_loop_.Quit();
171 else 172 else
172 FAIL(); 173 FAIL();
173 } 174 }
174 175
175 const GURL GetServerURL() const { return test_server_.GetURL(kUploadPath); } 176 const GURL GetServerURL() const { return test_server_.GetURL(kUploadPath); }
176 177
177 void SetExpectedError(std::unique_ptr<UploadJob::ErrorCode> expected_error) { 178 void SetExpectedError(std::unique_ptr<UploadJob::ErrorCode> expected_error) {
178 expected_error_ = std::move(expected_error); 179 expected_error_ = std::move(expected_error);
179 } 180 }
180 181
181 // testing::Test: 182 // testing::Test:
182 void SetUp() override { 183 void SetUp() override {
183 request_context_getter_ = new net::TestURLRequestContextGetter( 184 request_context_getter_ = new net::TestURLRequestContextGetter(
184 base::ThreadTaskRunnerHandle::Get()); 185 base::ThreadTaskRunnerHandle::Get());
185 oauth2_service_.AddAccount("robot@gmail.com"); 186 oauth2_service_.AddAccount("robot@gmail.com");
186 ASSERT_TRUE(test_server_.Start()); 187 ASSERT_TRUE(test_server_.Start());
188 // Set retry delay to prevent timeouts
189 policy::UploadJobImpl::SetRetryDelayForTesting(0);
187 } 190 }
188 191
189 // testing::Test: 192 // testing::Test:
190 void TearDown() override { 193 void TearDown() override {
191 ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); 194 ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
192 } 195 }
193 196
194 protected: 197 protected:
195 std::unique_ptr<UploadJob> PrepareUploadJob( 198 std::unique_ptr<UploadJob> PrepareUploadJob(
196 std::unique_ptr<UploadJobImpl::MimeBoundaryGenerator> 199 std::unique_ptr<UploadJobImpl::MimeBoundaryGenerator>
197 mime_boundary_generator) { 200 mime_boundary_generator) {
198 std::unique_ptr<UploadJob> upload_job( 201 std::unique_ptr<UploadJob> upload_job(
199 new UploadJobImpl(GetServerURL(), kRobotAccountId, &oauth2_service_, 202 new UploadJobImpl(GetServerURL(), kRobotAccountId, &oauth2_service_,
200 request_context_getter_.get(), this, 203 request_context_getter_.get(), this,
201 std::move(mime_boundary_generator))); 204 std::move(mime_boundary_generator), task_runner_));
202 205
203 std::map<std::string, std::string> header_entries; 206 std::map<std::string, std::string> header_entries;
204 header_entries.insert(std::make_pair(kCustomField1, "CUSTOM1")); 207 header_entries.insert(std::make_pair(kCustomField1, "CUSTOM1"));
205 std::unique_ptr<std::string> data(new std::string(kTestPayload1)); 208 std::unique_ptr<std::string> data(new std::string(kTestPayload1));
206 upload_job->AddDataSegment("Name1", "file1.ext", header_entries, 209 upload_job->AddDataSegment("Name1", "file1.ext", header_entries,
207 std::move(data)); 210 std::move(data));
208 211
209 header_entries.insert(std::make_pair(kCustomField2, "CUSTOM2")); 212 header_entries.insert(std::make_pair(kCustomField2, "CUSTOM2"));
210 std::unique_ptr<std::string> data2(new std::string(kTestPayload2)); 213 std::unique_ptr<std::string> data2(new std::string(kTestPayload2));
211 upload_job->AddDataSegment("Name2", "", header_entries, std::move(data2)); 214 upload_job->AddDataSegment("Name2", "", header_entries, std::move(data2));
212 return upload_job; 215 return upload_job;
213 } 216 }
214 217
215 content::TestBrowserThreadBundle test_browser_thread_bundle_; 218 content::TestBrowserThreadBundle test_browser_thread_bundle_;
216 base::RunLoop run_loop_; 219 base::RunLoop run_loop_;
217 net::EmbeddedTestServer test_server_; 220 net::EmbeddedTestServer test_server_;
218 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 221 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
219 MockOAuth2TokenService oauth2_service_; 222 MockOAuth2TokenService oauth2_service_;
220 223
221 std::unique_ptr<UploadJob::ErrorCode> expected_error_; 224 std::unique_ptr<UploadJob::ErrorCode> expected_error_;
225
226 // TaskRunner used to run individual tests.
227 scoped_refptr<base::SequencedTaskRunner> task_runner_;
Andrew T Wilson (Slow) 2016/05/18 11:59:38 Why do we need to track this in a member variable?
Marton Hunyady 2016/05/18 12:27:03 Done.
222 }; 228 };
223 229
224 class UploadFlowTest : public UploadJobTestBase { 230 class UploadFlowTest : public UploadJobTestBase {
225 public: 231 public:
226 UploadFlowTest() {} 232 UploadFlowTest() {}
227 233
228 // UploadJobTestBase: 234 // UploadJobTestBase:
229 void SetUp() override { 235 void SetUp() override {
230 UploadJobTestBase::SetUp(); 236 UploadJobTestBase::SetUp();
231 test_server_.RegisterRequestHandler( 237 test_server_.RegisterRequestHandler(
232 base::Bind(&UploadFlowTest::HandlePostRequest, base::Unretained(this))); 238 base::Bind(&UploadFlowTest::HandlePostRequest, base::Unretained(this)));
239 upload_attempt_count_ = 0;
240 }
241
242 // Sets the response code which will be returned when no other problems occur.
243 // Default is |net::HTTP_OK|
244 void SetResponseDefaultStatusCode(net::HttpStatusCode code) {
245 default_status_code_ = code;
233 } 246 }
234 247
235 std::unique_ptr<net::test_server::HttpResponse> HandlePostRequest( 248 std::unique_ptr<net::test_server::HttpResponse> HandlePostRequest(
236 const net::test_server::HttpRequest& request) { 249 const net::test_server::HttpRequest& request) {
250 upload_attempt_count_++;
237 EXPECT_TRUE(request.headers.find("Authorization") != request.headers.end()); 251 EXPECT_TRUE(request.headers.find("Authorization") != request.headers.end());
238 const std::string authorization_header = 252 const std::string authorization_header =
239 request.headers.at("Authorization"); 253 request.headers.at("Authorization");
240 std::unique_ptr<net::test_server::BasicHttpResponse> response( 254 std::unique_ptr<net::test_server::BasicHttpResponse> response(
241 new net::test_server::BasicHttpResponse); 255 new net::test_server::BasicHttpResponse);
242 const size_t pos = authorization_header.find(" "); 256 const size_t pos = authorization_header.find(" ");
243 if (pos == std::string::npos) { 257 if (pos == std::string::npos) {
244 response->set_code(net::HTTP_UNAUTHORIZED); 258 response->set_code(net::HTTP_UNAUTHORIZED);
245 return std::move(response); 259 return std::move(response);
246 } 260 }
247 261
248 const std::string token = authorization_header.substr(pos + 1); 262 const std::string token = authorization_header.substr(pos + 1);
249 response->set_code(oauth2_service_.IsTokenValid(token) 263 response->set_code(oauth2_service_.IsTokenValid(token)
250 ? net::HTTP_OK 264 ? default_status_code_
251 : net::HTTP_UNAUTHORIZED); 265 : net::HTTP_UNAUTHORIZED);
252 return std::move(response); 266 return std::move(response);
253 } 267 }
268
269 protected:
270 int upload_attempt_count_;
271 net::HttpStatusCode default_status_code_ = net::HTTP_OK;
254 }; 272 };
255 273
256 TEST_F(UploadFlowTest, SuccessfulUpload) { 274 TEST_F(UploadFlowTest, SuccessfulUpload) {
257 oauth2_service_.SetTokenValid(kTokenValid); 275 oauth2_service_.SetTokenValid(kTokenValid);
258 oauth2_service_.AddTokenToQueue(kTokenValid); 276 oauth2_service_.AddTokenToQueue(kTokenValid);
259 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 277 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
260 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 278 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
261 upload_job->Start(); 279 upload_job->Start();
262 run_loop_.Run(); 280 run_loop_.Run();
281 ASSERT_EQ(1, upload_attempt_count_);
263 } 282 }
264 283
265 TEST_F(UploadFlowTest, TokenExpired) { 284 TEST_F(UploadFlowTest, TokenExpired) {
266 oauth2_service_.SetTokenValid(kTokenValid); 285 oauth2_service_.SetTokenValid(kTokenValid);
267 oauth2_service_.AddTokenToQueue(kTokenExpired); 286 oauth2_service_.AddTokenToQueue(kTokenExpired);
268 oauth2_service_.AddTokenToQueue(kTokenValid); 287 oauth2_service_.AddTokenToQueue(kTokenValid);
269 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 288 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
270 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 289 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
271 upload_job->Start(); 290 upload_job->Start();
272 run_loop_.Run(); 291 run_loop_.Run();
292 ASSERT_EQ(2, upload_attempt_count_);
273 } 293 }
274 294
275 TEST_F(UploadFlowTest, TokenInvalid) { 295 TEST_F(UploadFlowTest, TokenInvalid) {
276 oauth2_service_.AddTokenToQueue(kTokenInvalid); 296 oauth2_service_.AddTokenToQueue(kTokenInvalid);
277 oauth2_service_.AddTokenToQueue(kTokenInvalid); 297 oauth2_service_.AddTokenToQueue(kTokenInvalid);
298 oauth2_service_.AddTokenToQueue(kTokenInvalid);
299 oauth2_service_.AddTokenToQueue(kTokenInvalid);
278 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>( 300 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
279 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR))); 301 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR)));
280 302
281 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 303 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
282 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 304 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
283 upload_job->Start(); 305 upload_job->Start();
284 run_loop_.Run(); 306 run_loop_.Run();
307 ASSERT_EQ(4, upload_attempt_count_);
308 }
309
310 TEST_F(UploadFlowTest, TokenMultipleTries) {
311 oauth2_service_.SetTokenValid(kTokenValid);
312 oauth2_service_.AddTokenToQueue(kTokenInvalid);
313 oauth2_service_.AddTokenToQueue(kTokenInvalid);
314 oauth2_service_.AddTokenToQueue(kTokenValid);
315
316 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
317 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
318 upload_job->Start();
319 run_loop_.Run();
320 ASSERT_EQ(3, upload_attempt_count_);
285 } 321 }
286 322
287 TEST_F(UploadFlowTest, TokenFetchFailure) { 323 TEST_F(UploadFlowTest, TokenFetchFailure) {
288 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>( 324 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
289 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR))); 325 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR)));
290 326
291 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 327 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
292 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 328 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
293 upload_job->Start(); 329 upload_job->Start();
294 run_loop_.Run(); 330 run_loop_.Run();
331 // Without a token we don't try to upload
332 ASSERT_EQ(0, upload_attempt_count_);
333 }
334
335 TEST_F(UploadFlowTest, InternalServerError) {
336 SetResponseDefaultStatusCode(net::HTTP_INTERNAL_SERVER_ERROR);
337 oauth2_service_.SetTokenValid(kTokenValid);
338 oauth2_service_.AddTokenToQueue(kTokenValid);
339
340 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
341 new UploadJob::ErrorCode(UploadJob::SERVER_ERROR)));
342
343 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
344 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
345 upload_job->Start();
346 run_loop_.Run();
347 // kMaxAttempts
Andrew T Wilson (Slow) 2016/05/18 11:59:38 This is fine. Alternative would have been to expos
348 ASSERT_EQ(4, upload_attempt_count_);
295 } 349 }
296 350
297 class UploadRequestTest : public UploadJobTestBase { 351 class UploadRequestTest : public UploadJobTestBase {
298 public: 352 public:
299 UploadRequestTest() {} 353 UploadRequestTest() {}
300 354
301 // UploadJobTestBase: 355 // UploadJobTestBase:
302 void SetUp() override { 356 void SetUp() override {
303 UploadJobTestBase::SetUp(); 357 UploadJobTestBase::SetUp();
304 test_server_.RegisterRequestHandler(base::Bind( 358 test_server_.RegisterRequestHandler(base::Bind(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 "customfield2: CUSTOM2\r\n" 394 "customfield2: CUSTOM2\r\n"
341 "\r\n" 395 "\r\n"
342 "**||--||PAYLOAD2||--||**\r\n--" 396 "**||--||PAYLOAD2||--||**\r\n--"
343 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA--\r\n"); 397 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA--\r\n");
344 398
345 upload_job->Start(); 399 upload_job->Start();
346 run_loop_.Run(); 400 run_loop_.Run();
347 } 401 }
348 402
349 } // namespace policy 403 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698