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

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: Threading checks, logging, test improvements 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/single_thread_task_runner.h"
20 #include "base/test/test_simple_task_runner.h"
20 #include "base/thread_task_runner_handle.h" 21 #include "base/thread_task_runner_handle.h"
21 #include "base/time/time.h" 22 #include "base/time/time.h"
22 #include "chrome/browser/chromeos/policy/upload_job_impl.h" 23 #include "chrome/browser/chromeos/policy/upload_job_impl.h"
23 #include "content/public/test/test_browser_thread_bundle.h" 24 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "google_apis/gaia/fake_oauth2_token_service.h" 25 #include "google_apis/gaia/fake_oauth2_token_service.h"
25 #include "google_apis/gaia/google_service_auth_error.h" 26 #include "google_apis/gaia/google_service_auth_error.h"
26 #include "net/http/http_status_code.h" 27 #include "net/http/http_status_code.h"
27 #include "net/test/embedded_test_server/embedded_test_server.h" 28 #include "net/test/embedded_test_server/embedded_test_server.h"
28 #include "net/test/embedded_test_server/http_request.h" 29 #include "net/test/embedded_test_server/http_request.h"
29 #include "net/test/embedded_test_server/http_response.h" 30 #include "net/test/embedded_test_server/http_response.h"
30 #include "net/url_request/url_request_test_util.h" 31 #include "net/url_request/url_request_test_util.h"
32 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
32 34
33 namespace policy { 35 namespace policy {
34 36
35 namespace { 37 namespace {
36 38
37 const char kUploadPath[] = "/upload"; 39 const char kUploadPath[] = "/upload";
38 const char kRobotAccountId[] = "robot@gmail.com"; 40 const char kRobotAccountId[] = "robot@gmail.com";
39 const char kCustomField1[] = "customfield1"; 41 const char kCustomField1[] = "customfield1";
40 const char kCustomField2[] = "customfield2"; 42 const char kCustomField2[] = "customfield2";
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 void MockOAuth2TokenService::InvalidateAccessTokenImpl( 145 void MockOAuth2TokenService::InvalidateAccessTokenImpl(
144 const std::string& account_id, 146 const std::string& account_id,
145 const std::string& client_id, 147 const std::string& client_id,
146 const ScopeSet& scopes, 148 const ScopeSet& scopes,
147 const std::string& access_token) { 149 const std::string& access_token) {
148 SetTokenInvalid(access_token); 150 SetTokenInvalid(access_token);
149 } 151 }
150 152
151 } // namespace 153 } // namespace
152 154
155 // Mock thread runner which runs each tasks immediately.
156 class ImmediateThreadTaskRunner : public base::SingleThreadTaskRunner {
Andrew T Wilson (Slow) 2016/05/10 22:00:42 I still don't understand why this is required (why
Marton Hunyady 2016/05/11 12:55:31 I removed it and made it possible to set the delay
157 const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
Andrew T Wilson (Slow) 2016/05/10 22:00:42 What is the intended scope of this member variable
158
159 public:
160 ImmediateThreadTaskRunner()
161 : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
162
163 bool PostDelayedTask(const tracked_objects::Location& from_here,
164 const base::Closure& task,
165 base::TimeDelta delay) override {
166 return task_runner_->PostTask(from_here, task);
167 }
168
169 bool RunsTasksOnCurrentThread() const override {
170 return task_runner_->RunsTasksOnCurrentThread();
171 }
172
173 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
174 const base::Closure& task,
175 base::TimeDelta delay) override {
176 return task_runner_->PostTask(from_here, task);
177 }
178
179 protected:
180 ~ImmediateThreadTaskRunner() override {}
181
182 DISALLOW_COPY_AND_ASSIGN(ImmediateThreadTaskRunner);
183 };
184
153 class UploadJobTestBase : public testing::Test, public UploadJob::Delegate { 185 class UploadJobTestBase : public testing::Test, public UploadJob::Delegate {
154 public: 186 public:
155 UploadJobTestBase() 187 UploadJobTestBase()
156 : test_browser_thread_bundle_( 188 : test_browser_thread_bundle_(
157 content::TestBrowserThreadBundle::IO_MAINLOOP) {} 189 content::TestBrowserThreadBundle::IO_MAINLOOP),
190 task_runner_(new ImmediateThreadTaskRunner) {}
158 191
159 // policy::UploadJob::Delegate: 192 // policy::UploadJob::Delegate:
160 void OnSuccess() override { 193 void OnSuccess() override {
161 if (!expected_error_) 194 if (!expected_error_)
162 run_loop_.Quit(); 195 run_loop_.Quit();
163 else 196 else
164 FAIL(); 197 FAIL();
165 } 198 }
166 199
167 // policy::UploadJob::Delegate: 200 // policy::UploadJob::Delegate:
(...skipping 23 matching lines...) Expand all
191 ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); 224 ASSERT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
192 } 225 }
193 226
194 protected: 227 protected:
195 std::unique_ptr<UploadJob> PrepareUploadJob( 228 std::unique_ptr<UploadJob> PrepareUploadJob(
196 std::unique_ptr<UploadJobImpl::MimeBoundaryGenerator> 229 std::unique_ptr<UploadJobImpl::MimeBoundaryGenerator>
197 mime_boundary_generator) { 230 mime_boundary_generator) {
198 std::unique_ptr<UploadJob> upload_job( 231 std::unique_ptr<UploadJob> upload_job(
199 new UploadJobImpl(GetServerURL(), kRobotAccountId, &oauth2_service_, 232 new UploadJobImpl(GetServerURL(), kRobotAccountId, &oauth2_service_,
200 request_context_getter_.get(), this, 233 request_context_getter_.get(), this,
201 std::move(mime_boundary_generator))); 234 std::move(mime_boundary_generator), task_runner_));
202 235
203 std::map<std::string, std::string> header_entries; 236 std::map<std::string, std::string> header_entries;
204 header_entries.insert(std::make_pair(kCustomField1, "CUSTOM1")); 237 header_entries.insert(std::make_pair(kCustomField1, "CUSTOM1"));
205 std::unique_ptr<std::string> data(new std::string(kTestPayload1)); 238 std::unique_ptr<std::string> data(new std::string(kTestPayload1));
206 upload_job->AddDataSegment("Name1", "file1.ext", header_entries, 239 upload_job->AddDataSegment("Name1", "file1.ext", header_entries,
207 std::move(data)); 240 std::move(data));
208 241
209 header_entries.insert(std::make_pair(kCustomField2, "CUSTOM2")); 242 header_entries.insert(std::make_pair(kCustomField2, "CUSTOM2"));
210 std::unique_ptr<std::string> data2(new std::string(kTestPayload2)); 243 std::unique_ptr<std::string> data2(new std::string(kTestPayload2));
211 upload_job->AddDataSegment("Name2", "", header_entries, std::move(data2)); 244 upload_job->AddDataSegment("Name2", "", header_entries, std::move(data2));
212 return upload_job; 245 return upload_job;
213 } 246 }
214 247
215 content::TestBrowserThreadBundle test_browser_thread_bundle_; 248 content::TestBrowserThreadBundle test_browser_thread_bundle_;
216 base::RunLoop run_loop_; 249 base::RunLoop run_loop_;
217 net::EmbeddedTestServer test_server_; 250 net::EmbeddedTestServer test_server_;
218 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 251 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
219 MockOAuth2TokenService oauth2_service_; 252 MockOAuth2TokenService oauth2_service_;
220 253
221 std::unique_ptr<UploadJob::ErrorCode> expected_error_; 254 std::unique_ptr<UploadJob::ErrorCode> expected_error_;
255
256 // TaskRunner used to run individual tests.
257 scoped_refptr<ImmediateThreadTaskRunner> task_runner_;
222 }; 258 };
223 259
224 class UploadFlowTest : public UploadJobTestBase { 260 class UploadFlowTest : public UploadJobTestBase {
225 public: 261 public:
226 UploadFlowTest() {} 262 UploadFlowTest() {}
227 263
228 // UploadJobTestBase: 264 // UploadJobTestBase:
229 void SetUp() override { 265 void SetUp() override {
230 UploadJobTestBase::SetUp(); 266 UploadJobTestBase::SetUp();
231 test_server_.RegisterRequestHandler( 267 test_server_.RegisterRequestHandler(
232 base::Bind(&UploadFlowTest::HandlePostRequest, base::Unretained(this))); 268 base::Bind(&UploadFlowTest::HandlePostRequest, base::Unretained(this)));
269 upload_attempt_count_ = 0;
233 } 270 }
234 271
235 std::unique_ptr<net::test_server::HttpResponse> HandlePostRequest( 272 std::unique_ptr<net::test_server::HttpResponse> HandlePostRequest(
236 const net::test_server::HttpRequest& request) { 273 const net::test_server::HttpRequest& request) {
274 upload_attempt_count_++;
237 EXPECT_TRUE(request.headers.find("Authorization") != request.headers.end()); 275 EXPECT_TRUE(request.headers.find("Authorization") != request.headers.end());
238 const std::string authorization_header = 276 const std::string authorization_header =
239 request.headers.at("Authorization"); 277 request.headers.at("Authorization");
240 std::unique_ptr<net::test_server::BasicHttpResponse> response( 278 std::unique_ptr<net::test_server::BasicHttpResponse> response(
241 new net::test_server::BasicHttpResponse); 279 new net::test_server::BasicHttpResponse);
242 const size_t pos = authorization_header.find(" "); 280 const size_t pos = authorization_header.find(" ");
243 if (pos == std::string::npos) { 281 if (pos == std::string::npos) {
244 response->set_code(net::HTTP_UNAUTHORIZED); 282 response->set_code(net::HTTP_UNAUTHORIZED);
245 return std::move(response); 283 return std::move(response);
246 } 284 }
247 285
248 const std::string token = authorization_header.substr(pos + 1); 286 const std::string token = authorization_header.substr(pos + 1);
249 response->set_code(oauth2_service_.IsTokenValid(token) 287 response->set_code(oauth2_service_.IsTokenValid(token)
250 ? net::HTTP_OK 288 ? net::HTTP_OK
251 : net::HTTP_UNAUTHORIZED); 289 : net::HTTP_UNAUTHORIZED);
252 return std::move(response); 290 return std::move(response);
253 } 291 }
292
293 protected:
294 int upload_attempt_count_;
254 }; 295 };
255 296
256 TEST_F(UploadFlowTest, SuccessfulUpload) { 297 TEST_F(UploadFlowTest, SuccessfulUpload) {
257 oauth2_service_.SetTokenValid(kTokenValid); 298 oauth2_service_.SetTokenValid(kTokenValid);
258 oauth2_service_.AddTokenToQueue(kTokenValid); 299 oauth2_service_.AddTokenToQueue(kTokenValid);
259 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 300 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
260 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 301 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
261 upload_job->Start(); 302 upload_job->Start();
262 run_loop_.Run(); 303 run_loop_.Run();
304 ASSERT_EQ(1, upload_attempt_count_);
263 } 305 }
264 306
265 TEST_F(UploadFlowTest, TokenExpired) { 307 TEST_F(UploadFlowTest, TokenExpired) {
266 oauth2_service_.SetTokenValid(kTokenValid); 308 oauth2_service_.SetTokenValid(kTokenValid);
267 oauth2_service_.AddTokenToQueue(kTokenExpired); 309 oauth2_service_.AddTokenToQueue(kTokenExpired);
268 oauth2_service_.AddTokenToQueue(kTokenValid); 310 oauth2_service_.AddTokenToQueue(kTokenValid);
269 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 311 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
270 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 312 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
271 upload_job->Start(); 313 upload_job->Start();
272 run_loop_.Run(); 314 run_loop_.Run();
315 ASSERT_EQ(2, upload_attempt_count_);
273 } 316 }
274 317
275 TEST_F(UploadFlowTest, TokenInvalid) { 318 TEST_F(UploadFlowTest, TokenInvalid) {
276 oauth2_service_.AddTokenToQueue(kTokenInvalid); 319 oauth2_service_.AddTokenToQueue(kTokenInvalid);
277 oauth2_service_.AddTokenToQueue(kTokenInvalid); 320 oauth2_service_.AddTokenToQueue(kTokenInvalid);
321 oauth2_service_.AddTokenToQueue(kTokenInvalid);
322 oauth2_service_.AddTokenToQueue(kTokenInvalid);
278 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>( 323 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
279 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR))); 324 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR)));
280 325
281 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 326 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
282 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 327 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
283 upload_job->Start(); 328 upload_job->Start();
284 run_loop_.Run(); 329 run_loop_.Run();
330 ASSERT_EQ(4, upload_attempt_count_);
331 }
332
333 TEST_F(UploadFlowTest, TokenMultipleTries) {
334 oauth2_service_.SetTokenValid(kTokenValid);
335 oauth2_service_.AddTokenToQueue(kTokenInvalid);
336 oauth2_service_.AddTokenToQueue(kTokenInvalid);
337 oauth2_service_.AddTokenToQueue(kTokenValid);
338
339 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
340 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
341 upload_job->Start();
342 run_loop_.Run();
343 ASSERT_EQ(3, upload_attempt_count_);
285 } 344 }
286 345
287 TEST_F(UploadFlowTest, TokenFetchFailure) { 346 TEST_F(UploadFlowTest, TokenFetchFailure) {
288 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>( 347 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
289 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR))); 348 new UploadJob::ErrorCode(UploadJob::AUTHENTICATION_ERROR)));
290 349
291 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob( 350 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
292 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator)); 351 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
293 upload_job->Start(); 352 upload_job->Start();
294 run_loop_.Run(); 353 run_loop_.Run();
354 // Without a token we don't try to upload
355 ASSERT_EQ(0, upload_attempt_count_);
356 }
357
358 class UploadServerErrorTest : public UploadJobTestBase {
Andrew T Wilson (Slow) 2016/05/10 22:00:42 Could you use UploadFlowTest() but have some membe
Marton Hunyady 2016/05/11 12:55:31 Done, removed it.
359 public:
360 UploadServerErrorTest() {}
361
362 // UploadJobTestBase:
363 void SetUp() override {
364 UploadJobTestBase::SetUp();
365 test_server_.RegisterRequestHandler(base::Bind(
366 &UploadServerErrorTest::HandlePostRequest, base::Unretained(this)));
367 upload_attempt_count_ = 0;
368 }
369
370 std::unique_ptr<net::test_server::HttpResponse> HandlePostRequest(
371 const net::test_server::HttpRequest& request) {
372 upload_attempt_count_++;
373 std::unique_ptr<net::test_server::BasicHttpResponse> response(
374 new net::test_server::BasicHttpResponse);
375 response->set_code(net::HTTP_INTERNAL_SERVER_ERROR);
376 return std::move(response);
377 }
378
379 protected:
380 int upload_attempt_count_;
381 };
382
383 TEST_F(UploadServerErrorTest, InternalServerError) {
384 oauth2_service_.SetTokenValid(kTokenValid);
385 oauth2_service_.AddTokenToQueue(kTokenValid);
386
387 SetExpectedError(std::unique_ptr<UploadJob::ErrorCode>(
388 new UploadJob::ErrorCode(UploadJob::SERVER_ERROR)));
389
390 std::unique_ptr<UploadJob> upload_job = PrepareUploadJob(
391 base::WrapUnique(new UploadJobImpl::RandomMimeBoundaryGenerator));
392 upload_job->Start();
393 run_loop_.Run();
394
395 // kMaxAttempts
396 ASSERT_EQ(4, upload_attempt_count_);
295 } 397 }
296 398
297 class UploadRequestTest : public UploadJobTestBase { 399 class UploadRequestTest : public UploadJobTestBase {
298 public: 400 public:
299 UploadRequestTest() {} 401 UploadRequestTest() {}
300 402
301 // UploadJobTestBase: 403 // UploadJobTestBase:
302 void SetUp() override { 404 void SetUp() override {
303 UploadJobTestBase::SetUp(); 405 UploadJobTestBase::SetUp();
304 test_server_.RegisterRequestHandler(base::Bind( 406 test_server_.RegisterRequestHandler(base::Bind(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 "customfield2: CUSTOM2\r\n" 442 "customfield2: CUSTOM2\r\n"
341 "\r\n" 443 "\r\n"
342 "**||--||PAYLOAD2||--||**\r\n--" 444 "**||--||PAYLOAD2||--||**\r\n--"
343 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA--\r\n"); 445 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA--\r\n");
344 446
345 upload_job->Start(); 447 upload_job->Start();
346 run_loop_.Run(); 448 run_loop_.Run();
347 } 449 }
348 450
349 } // namespace policy 451 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698