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

Side by Side Diff: sync/internal_api/attachments/attachment_uploader_impl_unittest.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sync/internal_api/public/attachments/attachment_uploader_impl.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/location.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/ref_counted_memory.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/synchronization/lock.h"
22 #include "base/test/histogram_tester.h"
23 #include "base/threading/non_thread_safe.h"
24 #include "base/threading/thread.h"
25 #include "base/threading/thread_task_runner_handle.h"
26 #include "google_apis/gaia/fake_oauth2_token_service.h"
27 #include "google_apis/gaia/gaia_constants.h"
28 #include "google_apis/gaia/oauth2_token_service_request.h"
29 #include "net/http/http_status_code.h"
30 #include "net/test/embedded_test_server/embedded_test_server.h"
31 #include "net/test/embedded_test_server/http_request.h"
32 #include "net/test/embedded_test_server/http_response.h"
33 #include "net/url_request/url_request_test_util.h"
34 #include "sync/api/attachments/attachment.h"
35 #include "sync/internal_api/public/attachments/attachment_util.h"
36 #include "sync/internal_api/public/base/model_type.h"
37 #include "sync/protocol/sync.pb.h"
38 #include "testing/gmock/include/gmock/gmock-matchers.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40
41 namespace {
42
43 const char kAttachmentData[] = "some data";
44 const char kAccountId[] = "some-account-id";
45 const char kAccessToken[] = "some-access-token";
46 const char kContentTypeValue[] = "application/octet-stream";
47 const char kXGoogHash[] = "X-Goog-Hash";
48 const char kAttachments[] = "/attachments/";
49 const char kStoreBirthday[] =
50 "\x46\xFF\xDD\xE0\x74\x3A\x48\xFD\x9D\x06\x93\x3C\x61\x8E\xA5\x70\x09\x59"
51 "\x99\x05\x61\x46\x21\x61\x1B\x03\xD3\x02\x60\xCD\x41\x55\xFE\x26\x15\xD7"
52 "\x0C";
53 const char kBase64URLSafeStoreBirthday[] =
54 "Rv_d4HQ6SP2dBpM8YY6lcAlZmQVhRiFhGwPTAmDNQVX-JhXXDA";
55 const char kSyncStoreBirthdayHeader[] = "X-Sync-Store-Birthday";
56 const char kSyncDataTypeIdHeader[] = "X-Sync-Data-Type-Id";
57 const syncer::ModelType kModelType = syncer::ModelType::ARTICLES;
58
59 } // namespace
60
61 namespace syncer {
62
63 using net::test_server::BasicHttpResponse;
64 using net::test_server::HttpRequest;
65 using net::test_server::HttpResponse;
66
67 class RequestHandler;
68
69 // A mock implementation of an OAuth2TokenService.
70 //
71 // Use |SetResponse| to vary the response to token requests.
72 //
73 // Use |num_invalidate_token| and |last_token_invalidated| to check the number
74 // of invalidate token operations performed and the last token invalidated.
75 class MockOAuth2TokenService : public FakeOAuth2TokenService {
76 public:
77 MockOAuth2TokenService();
78 ~MockOAuth2TokenService() override;
79
80 void SetResponse(const GoogleServiceAuthError& error,
81 const std::string& access_token,
82 const base::Time& expiration);
83
84 int num_invalidate_token() const { return num_invalidate_token_; }
85
86 const std::string& last_token_invalidated() const {
87 return last_token_invalidated_;
88 }
89
90 protected:
91 void FetchOAuth2Token(RequestImpl* request,
92 const std::string& account_id,
93 net::URLRequestContextGetter* getter,
94 const std::string& client_id,
95 const std::string& client_secret,
96 const ScopeSet& scopes) override;
97
98 void InvalidateAccessTokenImpl(const std::string& account_id,
99 const std::string& client_id,
100 const ScopeSet& scopes,
101 const std::string& access_token) override;
102
103 private:
104 GoogleServiceAuthError response_error_;
105 std::string response_access_token_;
106 base::Time response_expiration_;
107 int num_invalidate_token_;
108 std::string last_token_invalidated_;
109 };
110
111 MockOAuth2TokenService::MockOAuth2TokenService()
112 : response_error_(GoogleServiceAuthError::AuthErrorNone()),
113 response_access_token_(kAccessToken),
114 response_expiration_(base::Time::Max()),
115 num_invalidate_token_(0) {
116 }
117
118 MockOAuth2TokenService::~MockOAuth2TokenService() {
119 }
120
121 void MockOAuth2TokenService::SetResponse(const GoogleServiceAuthError& error,
122 const std::string& access_token,
123 const base::Time& expiration) {
124 response_error_ = error;
125 response_access_token_ = access_token;
126 response_expiration_ = expiration;
127 }
128
129 void MockOAuth2TokenService::FetchOAuth2Token(
130 RequestImpl* request,
131 const std::string& account_id,
132 net::URLRequestContextGetter* getter,
133 const std::string& client_id,
134 const std::string& client_secret,
135 const ScopeSet& scopes) {
136 base::ThreadTaskRunnerHandle::Get()->PostTask(
137 FROM_HERE, base::Bind(&OAuth2TokenService::RequestImpl::InformConsumer,
138 request->AsWeakPtr(), response_error_,
139 response_access_token_, response_expiration_));
140 }
141
142 void MockOAuth2TokenService::InvalidateAccessTokenImpl(
143 const std::string& account_id,
144 const std::string& client_id,
145 const ScopeSet& scopes,
146 const std::string& access_token) {
147 ++num_invalidate_token_;
148 last_token_invalidated_ = access_token;
149 }
150
151 class TokenServiceProvider
152 : public OAuth2TokenServiceRequest::TokenServiceProvider,
153 base::NonThreadSafe {
154 public:
155 explicit TokenServiceProvider(OAuth2TokenService* token_service);
156
157 // OAuth2TokenService::TokenServiceProvider implementation.
158 scoped_refptr<base::SingleThreadTaskRunner> GetTokenServiceTaskRunner()
159 override;
160 OAuth2TokenService* GetTokenService() override;
161
162 private:
163 ~TokenServiceProvider() override;
164
165 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
166 OAuth2TokenService* token_service_;
167 };
168
169 TokenServiceProvider::TokenServiceProvider(OAuth2TokenService* token_service)
170 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
171 token_service_(token_service) {
172 DCHECK(token_service_);
173 }
174
175 TokenServiceProvider::~TokenServiceProvider() {
176 }
177
178 scoped_refptr<base::SingleThreadTaskRunner>
179 TokenServiceProvider::GetTokenServiceTaskRunner() {
180 return task_runner_;
181 }
182
183 OAuth2TokenService* TokenServiceProvider::GetTokenService() {
184 DCHECK(task_runner_->BelongsToCurrentThread());
185 return token_service_;
186 }
187
188 // Text fixture for AttachmentUploaderImpl test.
189 //
190 // This fixture provides an embedded HTTP server and a mock OAuth2 token service
191 // for interacting with AttachmentUploaderImpl
192 class AttachmentUploaderImplTest : public testing::Test,
193 public base::NonThreadSafe {
194 public:
195 void OnRequestReceived(const HttpRequest& request);
196
197 protected:
198 AttachmentUploaderImplTest();
199 void SetUp() override;
200 void TearDown() override;
201
202 // Run the message loop until UploadDone has been invoked |num_uploads| times.
203 void RunAndWaitFor(int num_uploads);
204
205 // Upload an attachment and have the server respond with |status_code|.
206 //
207 // Returns the attachment that was uploaded.
208 Attachment UploadAndRespondWith(const net::HttpStatusCode& status_code);
209
210 std::unique_ptr<AttachmentUploader>& uploader();
211 const AttachmentUploader::UploadCallback& upload_callback() const;
212 std::vector<HttpRequest>& http_requests_received();
213 std::vector<AttachmentUploader::UploadResult>& upload_results();
214 std::vector<AttachmentId>& attachment_ids();
215 MockOAuth2TokenService& token_service();
216 base::MessageLoopForIO& message_loop();
217 RequestHandler& request_handler();
218
219 private:
220 // An UploadCallback invoked by AttachmentUploaderImpl.
221 void UploadDone(const AttachmentUploader::UploadResult& result,
222 const AttachmentId& attachment_id);
223
224 base::MessageLoopForIO message_loop_;
225 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
226 std::unique_ptr<RequestHandler> request_handler_;
227 std::unique_ptr<AttachmentUploader> uploader_;
228 AttachmentUploader::UploadCallback upload_callback_;
229 net::EmbeddedTestServer server_;
230 // A closure that signals an upload has finished.
231 base::Closure signal_upload_done_;
232 std::vector<HttpRequest> http_requests_received_;
233 std::vector<AttachmentUploader::UploadResult> upload_results_;
234 std::vector<AttachmentId> attachment_ids_;
235 std::unique_ptr<MockOAuth2TokenService> token_service_;
236
237 // Must be last data member.
238 base::WeakPtrFactory<AttachmentUploaderImplTest> weak_ptr_factory_;
239 };
240
241 // Handles HTTP requests received by the EmbeddedTestServer.
242 //
243 // Responds with HTTP_OK by default. See |SetStatusCode|.
244 class RequestHandler : public base::NonThreadSafe {
245 public:
246 // Construct a RequestHandler that will PostTask to |test| using
247 // |test_task_runner|.
248 RequestHandler(
249 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner,
250 const base::WeakPtr<AttachmentUploaderImplTest>& test);
251
252 ~RequestHandler();
253
254 std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request);
255
256 // Set the HTTP status code to respond with.
257 void SetStatusCode(const net::HttpStatusCode& status_code);
258
259 // Returns the HTTP status code that will be used in responses.
260 net::HttpStatusCode GetStatusCode() const;
261
262 private:
263 // Protects status_code_.
264 mutable base::Lock mutex_;
265 net::HttpStatusCode status_code_;
266
267 scoped_refptr<base::SingleThreadTaskRunner> test_task_runner_;
268 base::WeakPtr<AttachmentUploaderImplTest> test_;
269 };
270
271 AttachmentUploaderImplTest::AttachmentUploaderImplTest()
272 : weak_ptr_factory_(this) {
273 }
274
275 void AttachmentUploaderImplTest::OnRequestReceived(const HttpRequest& request) {
276 DCHECK(CalledOnValidThread());
277 http_requests_received_.push_back(request);
278 }
279
280 void AttachmentUploaderImplTest::SetUp() {
281 DCHECK(CalledOnValidThread());
282 request_handler_.reset(new RequestHandler(message_loop_.task_runner(),
283 weak_ptr_factory_.GetWeakPtr()));
284 url_request_context_getter_ =
285 new net::TestURLRequestContextGetter(message_loop_.task_runner());
286
287 ASSERT_TRUE(server_.Start());
288 server_.RegisterRequestHandler(
289 base::Bind(&RequestHandler::HandleRequest,
290 base::Unretained(request_handler_.get())));
291
292 GURL url(base::StringPrintf("http://localhost:%u/", server_.port()));
293
294 token_service_.reset(new MockOAuth2TokenService);
295 scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>
296 token_service_provider(new TokenServiceProvider(token_service_.get()));
297
298 OAuth2TokenService::ScopeSet scopes;
299 scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
300 uploader().reset(new AttachmentUploaderImpl(
301 url, url_request_context_getter_, kAccountId, scopes,
302 token_service_provider, std::string(kStoreBirthday), kModelType));
303
304 upload_callback_ = base::Bind(&AttachmentUploaderImplTest::UploadDone,
305 base::Unretained(this));
306 }
307
308 void AttachmentUploaderImplTest::TearDown() {
309 base::RunLoop().RunUntilIdle();
310 }
311
312 void AttachmentUploaderImplTest::RunAndWaitFor(int num_uploads) {
313 for (int i = 0; i < num_uploads; ++i) {
314 // Run the loop until one upload completes.
315 base::RunLoop run_loop;
316 signal_upload_done_ = run_loop.QuitClosure();
317 run_loop.Run();
318 }
319 }
320
321 Attachment AttachmentUploaderImplTest::UploadAndRespondWith(
322 const net::HttpStatusCode& status_code) {
323 token_service().AddAccount(kAccountId);
324 request_handler().SetStatusCode(status_code);
325 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString);
326 some_data->data() = kAttachmentData;
327 Attachment attachment = Attachment::Create(some_data);
328 uploader()->UploadAttachment(attachment, upload_callback());
329 return attachment;
330 }
331
332 std::unique_ptr<AttachmentUploader>& AttachmentUploaderImplTest::uploader() {
333 return uploader_;
334 }
335
336 const AttachmentUploader::UploadCallback&
337 AttachmentUploaderImplTest::upload_callback() const {
338 return upload_callback_;
339 }
340
341 std::vector<HttpRequest>& AttachmentUploaderImplTest::http_requests_received() {
342 return http_requests_received_;
343 }
344
345 std::vector<AttachmentUploader::UploadResult>&
346 AttachmentUploaderImplTest::upload_results() {
347 return upload_results_;
348 }
349
350 std::vector<AttachmentId>&
351 AttachmentUploaderImplTest::attachment_ids() {
352 return attachment_ids_;
353 }
354
355 MockOAuth2TokenService& AttachmentUploaderImplTest::token_service() {
356 return *token_service_;
357 }
358
359 base::MessageLoopForIO& AttachmentUploaderImplTest::message_loop() {
360 return message_loop_;
361 }
362
363 RequestHandler& AttachmentUploaderImplTest::request_handler() {
364 return *request_handler_;
365 }
366
367 void AttachmentUploaderImplTest::UploadDone(
368 const AttachmentUploader::UploadResult& result,
369 const AttachmentId& attachment_id) {
370 DCHECK(CalledOnValidThread());
371 upload_results_.push_back(result);
372 attachment_ids_.push_back(attachment_id);
373 DCHECK(!signal_upload_done_.is_null());
374 signal_upload_done_.Run();
375 }
376
377 RequestHandler::RequestHandler(
378 const scoped_refptr<base::SingleThreadTaskRunner>& test_task_runner,
379 const base::WeakPtr<AttachmentUploaderImplTest>& test)
380 : status_code_(net::HTTP_OK),
381 test_task_runner_(test_task_runner),
382 test_(test) {
383 DetachFromThread();
384 }
385
386 RequestHandler::~RequestHandler() {
387 DetachFromThread();
388 }
389
390 std::unique_ptr<HttpResponse> RequestHandler::HandleRequest(
391 const HttpRequest& request) {
392 DCHECK(CalledOnValidThread());
393 test_task_runner_->PostTask(
394 FROM_HERE,
395 base::Bind(
396 &AttachmentUploaderImplTest::OnRequestReceived, test_, request));
397 std::unique_ptr<BasicHttpResponse> response(new BasicHttpResponse);
398 response->set_code(GetStatusCode());
399 response->set_content_type("text/plain");
400 return std::move(response);
401 }
402
403 void RequestHandler::SetStatusCode(const net::HttpStatusCode& status_code) {
404 base::AutoLock lock(mutex_);
405 status_code_ = status_code;
406 }
407
408 net::HttpStatusCode RequestHandler::GetStatusCode() const {
409 base::AutoLock lock(mutex_);
410 return status_code_;
411 }
412
413 TEST_F(AttachmentUploaderImplTest, GetURLForAttachmentId_NoPath) {
414 AttachmentId id = AttachmentId::Create(0, 0);
415 std::string unique_id = id.GetProto().unique_id();
416 GURL sync_service_url("https://example.com");
417 EXPECT_EQ("https://example.com/attachments/" + unique_id,
418 AttachmentUploaderImpl::GetURLForAttachmentId(sync_service_url, id)
419 .spec());
420 }
421
422 TEST_F(AttachmentUploaderImplTest, GetURLForAttachmentId_JustSlash) {
423 AttachmentId id = AttachmentId::Create(0, 0);
424 std::string unique_id = id.GetProto().unique_id();
425 GURL sync_service_url("https://example.com/");
426 EXPECT_EQ("https://example.com/attachments/" + unique_id,
427 AttachmentUploaderImpl::GetURLForAttachmentId(sync_service_url, id)
428 .spec());
429 }
430
431 TEST_F(AttachmentUploaderImplTest, GetURLForAttachmentId_Path) {
432 AttachmentId id = AttachmentId::Create(0, 0);
433 std::string unique_id = id.GetProto().unique_id();
434 GURL sync_service_url("https://example.com/service");
435 EXPECT_EQ("https://example.com/service/attachments/" + unique_id,
436 AttachmentUploaderImpl::GetURLForAttachmentId(sync_service_url, id)
437 .spec());
438 }
439
440 TEST_F(AttachmentUploaderImplTest, GetURLForAttachmentId_PathAndSlash) {
441 AttachmentId id = AttachmentId::Create(0, 0);
442 std::string unique_id = id.GetProto().unique_id();
443 GURL sync_service_url("https://example.com/service/");
444 EXPECT_EQ("https://example.com/service/attachments/" + unique_id,
445 AttachmentUploaderImpl::GetURLForAttachmentId(sync_service_url, id)
446 .spec());
447 }
448
449 // Verify the "happy case" of uploading an attachment.
450 //
451 // Token is requested, token is returned, HTTP request is made, attachment is
452 // received by server.
453 TEST_F(AttachmentUploaderImplTest, UploadAttachment_HappyCase) {
454 Attachment attachment = UploadAndRespondWith(net::HTTP_OK);
455 base::HistogramTester histogram_tester;
456
457 // Run until the done callback is invoked.
458 RunAndWaitFor(1);
459
460 // See that the done callback was invoked with the right arguments.
461 ASSERT_EQ(1U, upload_results().size());
462 EXPECT_EQ(AttachmentUploader::UPLOAD_SUCCESS, upload_results()[0]);
463 ASSERT_EQ(1U, attachment_ids().size());
464 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
465 histogram_tester.ExpectUniqueSample("Sync.Attachments.UploadResponseCode",
466 net::HTTP_OK, 1);
467
468 // See that the HTTP server received one request.
469 ASSERT_EQ(1U, http_requests_received().size());
470 const HttpRequest& http_request = http_requests_received().front();
471 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method);
472 std::string expected_relative_url(kAttachments +
473 attachment.GetId().GetProto().unique_id());
474 EXPECT_EQ(expected_relative_url, http_request.relative_url);
475 EXPECT_TRUE(http_request.has_content);
476 EXPECT_EQ(kAttachmentData, http_request.content);
477 }
478
479 // Verify the request contains the appropriate headers.
480 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Headers) {
481 Attachment attachment = UploadAndRespondWith(net::HTTP_OK);
482
483 // Run until the done callback is invoked.
484 RunAndWaitFor(1);
485
486 // See that the done callback was invoked with the right arguments.
487 ASSERT_EQ(1U, upload_results().size());
488 EXPECT_EQ(AttachmentUploader::UPLOAD_SUCCESS, upload_results()[0]);
489 ASSERT_EQ(1U, attachment_ids().size());
490 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
491
492 // See that the HTTP server received one request.
493 ASSERT_EQ(1U, http_requests_received().size());
494 const HttpRequest& http_request = http_requests_received().front();
495
496 const std::string auth_header_value(std::string("Bearer ") + kAccessToken);
497
498 EXPECT_THAT(http_request.headers,
499 testing::Contains(testing::Pair(
500 net::HttpRequestHeaders::kAuthorization, auth_header_value)));
501 EXPECT_THAT(
502 http_request.headers,
503 testing::Contains(testing::Key(net::HttpRequestHeaders::kContentLength)));
504 EXPECT_THAT(http_request.headers,
505 testing::Contains(testing::Pair(
506 net::HttpRequestHeaders::kContentType, kContentTypeValue)));
507 EXPECT_THAT(http_request.headers,
508 testing::Contains(testing::Key(kXGoogHash)));
509 EXPECT_THAT(
510 http_request.headers,
511 testing::Contains(testing::Key(net::HttpRequestHeaders::kUserAgent)));
512 EXPECT_THAT(http_request.headers,
513 testing::Contains(testing::Pair(kSyncStoreBirthdayHeader,
514 kBase64URLSafeStoreBirthday)));
515 EXPECT_THAT(http_request.headers,
516 testing::Contains(testing::Pair(
517 kSyncDataTypeIdHeader,
518 base::IntToString(
519 GetSpecificsFieldNumberFromModelType(kModelType)))));
520 }
521
522 // Verify two overlapping calls to upload the same attachment result in only one
523 // HTTP request.
524 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Collapse) {
525 Attachment attachment1 = UploadAndRespondWith(net::HTTP_OK);
526 Attachment attachment2 = attachment1;
527 uploader()->UploadAttachment(attachment2, upload_callback());
528
529 // Wait for upload_callback() to be invoked twice.
530 RunAndWaitFor(2);
531 // See there was only one request.
532 EXPECT_EQ(1U, http_requests_received().size());
533 }
534
535 // Verify that the internal state associated with an upload is removed when the
536 // uplaod finishes. We do this by issuing two non-overlapping uploads for the
537 // same attachment and see that it results in two HTTP requests.
538 TEST_F(AttachmentUploaderImplTest, UploadAttachment_CleanUpAfterUpload) {
539 Attachment attachment1 = UploadAndRespondWith(net::HTTP_OK);
540
541 // Wait for upload_callback() to be invoked before starting the second upload.
542 RunAndWaitFor(1);
543
544 Attachment attachment2 = attachment1;
545 uploader()->UploadAttachment(attachment2, upload_callback());
546
547 // Wait for upload_callback() to be invoked a second time.
548 RunAndWaitFor(1);
549 // See there were two requests.
550 ASSERT_EQ(2U, http_requests_received().size());
551 }
552
553 // Verify that we do not issue an HTTP request when we fail to receive an access
554 // token.
555 //
556 // Token is requested, no token is returned, no HTTP request is made
557 TEST_F(AttachmentUploaderImplTest, UploadAttachment_FailToGetToken) {
558 // Note, we won't receive a token because we did not add kAccountId to the
559 // token service.
560 scoped_refptr<base::RefCountedString> some_data(new base::RefCountedString);
561 some_data->data() = kAttachmentData;
562 Attachment attachment = Attachment::Create(some_data);
563 uploader()->UploadAttachment(attachment, upload_callback());
564 base::HistogramTester histogram_tester;
565
566 RunAndWaitFor(1);
567
568 // See that the done callback was invoked.
569 ASSERT_EQ(1U, upload_results().size());
570 EXPECT_EQ(AttachmentUploader::UPLOAD_TRANSIENT_ERROR, upload_results()[0]);
571 ASSERT_EQ(1U, attachment_ids().size());
572 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
573 histogram_tester.ExpectTotalCount("Sync.Attachments.UploadResponseCode", 0);
574
575 // See that no HTTP request was received.
576 ASSERT_EQ(0U, http_requests_received().size());
577 }
578
579 // Verify behavior when the server returns "503 Service Unavailable".
580 TEST_F(AttachmentUploaderImplTest, UploadAttachment_ServiceUnavilable) {
581 Attachment attachment = UploadAndRespondWith(net::HTTP_SERVICE_UNAVAILABLE);
582 base::HistogramTester histogram_tester;
583
584 RunAndWaitFor(1);
585
586 // See that the done callback was invoked.
587 ASSERT_EQ(1U, upload_results().size());
588 EXPECT_EQ(AttachmentUploader::UPLOAD_TRANSIENT_ERROR, upload_results()[0]);
589 ASSERT_EQ(1U, attachment_ids().size());
590 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
591 histogram_tester.ExpectUniqueSample("Sync.Attachments.UploadResponseCode",
592 net::HTTP_SERVICE_UNAVAILABLE, 1);
593
594 // See that the HTTP server received one request.
595 ASSERT_EQ(1U, http_requests_received().size());
596 const HttpRequest& http_request = http_requests_received().front();
597 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method);
598 std::string expected_relative_url(kAttachments +
599 attachment.GetId().GetProto().unique_id());
600 EXPECT_EQ(expected_relative_url, http_request.relative_url);
601 EXPECT_TRUE(http_request.has_content);
602 EXPECT_EQ(kAttachmentData, http_request.content);
603
604 // See that we did not invalidate the token.
605 ASSERT_EQ(0, token_service().num_invalidate_token());
606 }
607
608 // Verify that we "403 Forbidden" as a non-transient error.
609 TEST_F(AttachmentUploaderImplTest, UploadAttachment_Forbidden) {
610 Attachment attachment = UploadAndRespondWith(net::HTTP_FORBIDDEN);
611 base::HistogramTester histogram_tester;
612
613 RunAndWaitFor(1);
614
615 // See that the done callback was invoked.
616 ASSERT_EQ(1U, upload_results().size());
617 EXPECT_EQ(AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR, upload_results()[0]);
618 ASSERT_EQ(1U, attachment_ids().size());
619 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
620 histogram_tester.ExpectUniqueSample("Sync.Attachments.UploadResponseCode",
621 net::HTTP_FORBIDDEN, 1);
622
623 // See that the HTTP server received one request.
624 ASSERT_EQ(1U, http_requests_received().size());
625 const HttpRequest& http_request = http_requests_received().front();
626 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method);
627 std::string expected_relative_url(kAttachments +
628 attachment.GetId().GetProto().unique_id());
629 EXPECT_EQ(expected_relative_url, http_request.relative_url);
630 EXPECT_TRUE(http_request.has_content);
631 EXPECT_EQ(kAttachmentData, http_request.content);
632
633 // See that we did not invalidate the token.
634 ASSERT_EQ(0, token_service().num_invalidate_token());
635 }
636
637 // Verify that when we receive an "401 Unauthorized" we invalidate the access
638 // token.
639 TEST_F(AttachmentUploaderImplTest, UploadAttachment_BadToken) {
640 Attachment attachment = UploadAndRespondWith(net::HTTP_UNAUTHORIZED);
641 base::HistogramTester histogram_tester;
642
643 RunAndWaitFor(1);
644
645 // See that the done callback was invoked.
646 ASSERT_EQ(1U, upload_results().size());
647 EXPECT_EQ(AttachmentUploader::UPLOAD_TRANSIENT_ERROR, upload_results()[0]);
648 ASSERT_EQ(1U, attachment_ids().size());
649 EXPECT_EQ(attachment.GetId(), attachment_ids()[0]);
650 histogram_tester.ExpectUniqueSample("Sync.Attachments.UploadResponseCode",
651 net::HTTP_UNAUTHORIZED, 1);
652
653 // See that the HTTP server received one request.
654 ASSERT_EQ(1U, http_requests_received().size());
655 const HttpRequest& http_request = http_requests_received().front();
656 EXPECT_EQ(net::test_server::METHOD_POST, http_request.method);
657 std::string expected_relative_url(kAttachments +
658 attachment.GetId().GetProto().unique_id());
659 EXPECT_EQ(expected_relative_url, http_request.relative_url);
660 EXPECT_TRUE(http_request.has_content);
661 EXPECT_EQ(kAttachmentData, http_request.content);
662
663 // See that we invalidated the token.
664 ASSERT_EQ(1, token_service().num_invalidate_token());
665 }
666
667 TEST_F(AttachmentUploaderImplTest, FormatCrc32cHash) {
668 scoped_refptr<base::RefCountedString> empty(new base::RefCountedString);
669 empty->data() = "";
670 EXPECT_EQ("AAAAAA==",
671 AttachmentUploaderImpl::FormatCrc32cHash(ComputeCrc32c(empty)));
672
673 scoped_refptr<base::RefCountedString> hello_world(new base::RefCountedString);
674 hello_world->data() = "hello world";
675 EXPECT_EQ("yZRlqg==", AttachmentUploaderImpl::FormatCrc32cHash(
676 ComputeCrc32c(hello_world)));
677 }
678
679 // TODO(maniscalco): Add test case for when we are uploading an attachment that
680 // already exists. 409 Conflict? (bug 379825)
681
682 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/internal_api/attachments/attachment_uploader_impl.cc ('k') | sync/internal_api/attachments/attachment_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698