X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fsync%2Finternal_api%2Fattachments%2Fattachment_service_impl_unittest.cc;h=85bbb6a9a8d2671919e06a1db6d80779ff64bc2c;hb=3545e9f2671f595d2a2f3ee75ca0393b01e35ef6;hp=d8bf6b20dd5616c2f27b8ac09d0462237f19dced;hpb=7d210d4c7e9ba36e635eabc5b5780495f8a63292;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/sync/internal_api/attachments/attachment_service_impl_unittest.cc b/src/sync/internal_api/attachments/attachment_service_impl_unittest.cc index d8bf6b2..85bbb6a 100644 --- a/src/sync/internal_api/attachments/attachment_service_impl_unittest.cc +++ b/src/sync/internal_api/attachments/attachment_service_impl_unittest.cc @@ -8,8 +8,10 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/timer/mock_timer.h" #include "sync/internal_api/public/attachments/fake_attachment_downloader.h" #include "sync/internal_api/public/attachments/fake_attachment_uploader.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { @@ -83,6 +85,9 @@ class MockAttachmentStore : public AttachmentStore, std::vector write_attachments; std::vector write_callbacks; + private: + virtual ~MockAttachmentStore() {} + DISALLOW_COPY_AND_ASSIGN(MockAttachmentStore); }; @@ -151,6 +156,7 @@ class AttachmentServiceImplTest : public testing::Test, AttachmentServiceImplTest() {} virtual void SetUp() OVERRIDE { + network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()), make_scoped_ptr(new MockAttachmentDownloader()), this); @@ -173,7 +179,8 @@ class AttachmentServiceImplTest : public testing::Test, scoped_ptr uploader, scoped_ptr downloader, AttachmentService::Delegate* delegate) { - scoped_ptr attachment_store(new MockAttachmentStore()); + scoped_refptr attachment_store( + new MockAttachmentStore()); attachment_store_ = attachment_store->AsWeakPtr(); if (uploader.get()) { @@ -183,39 +190,47 @@ class AttachmentServiceImplTest : public testing::Test, attachment_downloader_ = downloader->AsWeakPtr(); } attachment_service_.reset( - new AttachmentServiceImpl(attachment_store.PassAs(), + new AttachmentServiceImpl(attachment_store, uploader.PassAs(), downloader.PassAs(), - delegate)); + delegate, + base::TimeDelta::FromMinutes(1), + base::TimeDelta::FromMinutes(8))); + + scoped_ptr timer_to_pass( + new base::MockTimer(false, false)); + mock_timer_ = timer_to_pass.get(); + attachment_service_->SetTimerForTest(timer_to_pass.PassAs()); } AttachmentService* attachment_service() { return attachment_service_.get(); } + base::MockTimer* mock_timer() { return mock_timer_; } + AttachmentService::GetOrDownloadCallback download_callback() { return base::Bind(&AttachmentServiceImplTest::DownloadDone, base::Unretained(this)); } - AttachmentService::StoreCallback store_callback() { - return base::Bind(&AttachmentServiceImplTest::StoreDone, - base::Unretained(this)); - } - void DownloadDone(const AttachmentService::GetOrDownloadResult& result, scoped_ptr attachments) { download_results_.push_back(result); last_download_attachments_ = attachments.Pass(); } - void StoreDone(const AttachmentService::StoreResult& result) { - store_results_.push_back(result); - } - void RunLoop() { base::RunLoop run_loop; run_loop.RunUntilIdle(); } + void RunLoopAndFireTimer() { + RunLoop(); + if (mock_timer()->IsRunning()) { + mock_timer()->Fire(); + } + RunLoop(); + } + const std::vector& download_results() const { return download_results_; @@ -225,8 +240,8 @@ class AttachmentServiceImplTest : public testing::Test, return *last_download_attachments_.get(); } - const std::vector& store_results() const { - return store_results_; + net::NetworkChangeNotifier* network_change_notifier() { + return network_change_notifier_.get(); } MockAttachmentStore* store() { return attachment_store_.get(); } @@ -245,18 +260,22 @@ class AttachmentServiceImplTest : public testing::Test, private: base::MessageLoop message_loop_; + scoped_ptr network_change_notifier_; base::WeakPtr attachment_store_; base::WeakPtr attachment_downloader_; base::WeakPtr attachment_uploader_; - scoped_ptr attachment_service_; + scoped_ptr attachment_service_; + base::MockTimer* mock_timer_; // not owned std::vector download_results_; scoped_ptr last_download_attachments_; std::vector on_attachment_uploaded_list_; - - std::vector store_results_; }; +TEST_F(AttachmentServiceImplTest, GetStore) { + EXPECT_EQ(store(), attachment_service()->GetStore()); +} + TEST_F(AttachmentServiceImplTest, GetOrDownload_EmptyAttachmentList) { AttachmentIdList attachment_ids; attachment_service()->GetOrDownloadAttachments(attachment_ids, @@ -348,105 +367,188 @@ TEST_F(AttachmentServiceImplTest, GetOrDownload_NoDownloader) { EXPECT_TRUE(last_download_attachments().empty()); } -TEST_F(AttachmentServiceImplTest, StoreAttachments_Success) { - scoped_refptr data = new base::RefCountedString(); - Attachment attachment(Attachment::Create(data)); - AttachmentList attachments; - attachments.push_back(attachment); - attachment_service()->StoreAttachments(attachments, store_callback()); - EXPECT_EQ(1U, store()->write_attachments.size()); - EXPECT_EQ(1U, uploader()->upload_requests.size()); - - store()->RespondToWrite(AttachmentStore::SUCCESS); - uploader()->RespondToUpload(attachment.GetId(), - AttachmentUploader::UPLOAD_SUCCESS); +TEST_F(AttachmentServiceImplTest, UploadAttachments_Success) { + AttachmentIdSet attachment_ids; + const unsigned num_attachments = 3; + for (unsigned i = 0; i < num_attachments; ++i) { + attachment_ids.insert(AttachmentId::Create()); + } + attachment_service()->UploadAttachments(attachment_ids); + + for (unsigned i = 0; i < num_attachments; ++i) { + RunLoopAndFireTimer(); + // See that the service has issued a read for at least one of the + // attachments. + ASSERT_GE(store()->read_ids.size(), 1U); + store()->RespondToRead(attachment_ids); + RunLoop(); + ASSERT_GE(uploader()->upload_requests.size(), 1U); + uploader()->RespondToUpload(uploader()->upload_requests.begin()->first, + AttachmentUploader::UPLOAD_SUCCESS); + } RunLoop(); - ASSERT_EQ(1U, store_results().size()); - EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]); - ASSERT_EQ(1U, on_attachment_uploaded_list().size()); - EXPECT_EQ(attachment.GetId(), on_attachment_uploaded_list()[0]); + ASSERT_EQ(0U, store()->read_ids.size()); + ASSERT_EQ(0U, uploader()->upload_requests.size()); + + // See that all the attachments were uploaded. + ASSERT_EQ(attachment_ids.size(), on_attachment_uploaded_list().size()); + AttachmentIdSet::const_iterator iter = attachment_ids.begin(); + const AttachmentIdSet::const_iterator end = attachment_ids.end(); + for (iter = attachment_ids.begin(); iter != end; ++iter) { + EXPECT_THAT(on_attachment_uploaded_list(), testing::Contains(*iter)); + } } -TEST_F(AttachmentServiceImplTest, - StoreAttachments_StoreFailsWithUnspecifiedError) { - scoped_refptr data = new base::RefCountedString(); - Attachment attachment(Attachment::Create(data)); - AttachmentList attachments; - attachments.push_back(attachment); - attachment_service()->StoreAttachments(attachments, store_callback()); - EXPECT_EQ(1U, store()->write_attachments.size()); - EXPECT_EQ(1U, uploader()->upload_requests.size()); - - store()->RespondToWrite(AttachmentStore::UNSPECIFIED_ERROR); - uploader()->RespondToUpload(attachment.GetId(), +TEST_F(AttachmentServiceImplTest, UploadAttachments_Success_NoDelegate) { + InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()), + make_scoped_ptr(new MockAttachmentDownloader()), + NULL); // No delegate. + + AttachmentIdSet attachment_ids; + attachment_ids.insert(AttachmentId::Create()); + attachment_service()->UploadAttachments(attachment_ids); + RunLoopAndFireTimer(); + ASSERT_EQ(1U, store()->read_ids.size()); + ASSERT_EQ(0U, uploader()->upload_requests.size()); + store()->RespondToRead(attachment_ids); + RunLoop(); + ASSERT_EQ(0U, store()->read_ids.size()); + ASSERT_EQ(1U, uploader()->upload_requests.size()); + uploader()->RespondToUpload(*attachment_ids.begin(), AttachmentUploader::UPLOAD_SUCCESS); RunLoop(); - ASSERT_EQ(1U, store_results().size()); - EXPECT_EQ(AttachmentService::STORE_UNSPECIFIED_ERROR, store_results()[0]); - ASSERT_EQ(1U, on_attachment_uploaded_list().size()); - EXPECT_EQ(attachment.GetId(), on_attachment_uploaded_list()[0]); + ASSERT_TRUE(on_attachment_uploaded_list().empty()); } -TEST_F(AttachmentServiceImplTest, - StoreAttachments_UploadFailsWithUnspecifiedError) { - scoped_refptr data = new base::RefCountedString(); - Attachment attachment(Attachment::Create(data)); - AttachmentList attachments; - attachments.push_back(attachment); - attachment_service()->StoreAttachments(attachments, store_callback()); - EXPECT_EQ(1U, store()->write_attachments.size()); - EXPECT_EQ(1U, uploader()->upload_requests.size()); - - store()->RespondToWrite(AttachmentStore::SUCCESS); - uploader()->RespondToUpload(attachment.GetId(), - AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR); +TEST_F(AttachmentServiceImplTest, UploadAttachments_SomeMissingFromStore) { + AttachmentIdSet attachment_ids; + attachment_ids.insert(AttachmentId::Create()); + attachment_ids.insert(AttachmentId::Create()); + attachment_service()->UploadAttachments(attachment_ids); + RunLoopAndFireTimer(); + ASSERT_GE(store()->read_ids.size(), 1U); + + ASSERT_EQ(0U, uploader()->upload_requests.size()); + store()->RespondToRead(attachment_ids); RunLoop(); - ASSERT_EQ(1U, store_results().size()); - // Even though the upload failed, the Store operation is successful. - EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]); - EXPECT_TRUE(on_attachment_uploaded_list().empty()); -} + ASSERT_EQ(1U, uploader()->upload_requests.size()); -TEST_F(AttachmentServiceImplTest, StoreAttachments_NoDelegate) { - InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()), - make_scoped_ptr(new MockAttachmentDownloader()), - NULL); // No delegate. + uploader()->RespondToUpload(uploader()->upload_requests.begin()->first, + AttachmentUploader::UPLOAD_SUCCESS); + RunLoopAndFireTimer(); + ASSERT_EQ(1U, on_attachment_uploaded_list().size()); + ASSERT_GE(store()->read_ids.size(), 1U); + // Not found! + store()->RespondToRead(AttachmentIdSet()); + RunLoop(); + // No upload requests since the read failed. + ASSERT_EQ(0U, uploader()->upload_requests.size()); +} - scoped_refptr data = new base::RefCountedString(); - Attachment attachment(Attachment::Create(data)); - AttachmentList attachments; - attachments.push_back(attachment); - attachment_service()->StoreAttachments(attachments, store_callback()); - EXPECT_EQ(1U, store()->write_attachments.size()); - EXPECT_EQ(1U, uploader()->upload_requests.size()); +TEST_F(AttachmentServiceImplTest, UploadAttachments_AllMissingFromStore) { + AttachmentIdSet attachment_ids; + const unsigned num_attachments = 2; + for (unsigned i = 0; i < num_attachments; ++i) { + attachment_ids.insert(AttachmentId::Create()); + } + attachment_service()->UploadAttachments(attachment_ids); - store()->RespondToWrite(AttachmentStore::SUCCESS); - uploader()->RespondToUpload(attachment.GetId(), - AttachmentUploader::UPLOAD_SUCCESS); + for (unsigned i = 0; i < num_attachments; ++i) { + RunLoopAndFireTimer(); + ASSERT_GE(store()->read_ids.size(), 1U); + // None found! + store()->RespondToRead(AttachmentIdSet()); + } RunLoop(); - ASSERT_EQ(1U, store_results().size()); - EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]); - EXPECT_TRUE(on_attachment_uploaded_list().empty()); + + // Nothing uploaded. + EXPECT_EQ(0U, uploader()->upload_requests.size()); + // See that the delegate was never called. + ASSERT_EQ(0U, on_attachment_uploaded_list().size()); } -TEST_F(AttachmentServiceImplTest, StoreAttachments_NoUploader) { - // No uploader. +TEST_F(AttachmentServiceImplTest, UploadAttachments_NoUploader) { InitializeAttachmentService(make_scoped_ptr(NULL), make_scoped_ptr(new MockAttachmentDownloader()), this); - scoped_refptr data = new base::RefCountedString(); - Attachment attachment(Attachment::Create(data)); - AttachmentList attachments; - attachments.push_back(attachment); - attachment_service()->StoreAttachments(attachments, store_callback()); - EXPECT_EQ(1U, store()->write_attachments.size()); + AttachmentIdSet attachment_ids; + attachment_ids.insert(AttachmentId::Create()); + attachment_service()->UploadAttachments(attachment_ids); + RunLoop(); + EXPECT_EQ(0U, store()->read_ids.size()); + ASSERT_EQ(0U, on_attachment_uploaded_list().size()); +} - store()->RespondToWrite(AttachmentStore::SUCCESS); +// Upload three attachments. For one of them, server responds with error. +TEST_F(AttachmentServiceImplTest, UploadAttachments_OneUploadFails) { + AttachmentIdSet attachment_ids; + const unsigned num_attachments = 3; + for (unsigned i = 0; i < num_attachments; ++i) { + attachment_ids.insert(AttachmentId::Create()); + } + attachment_service()->UploadAttachments(attachment_ids); + + for (unsigned i = 0; i < 3; ++i) { + RunLoopAndFireTimer(); + ASSERT_GE(store()->read_ids.size(), 1U); + store()->RespondToRead(attachment_ids); + RunLoop(); + ASSERT_EQ(1U, uploader()->upload_requests.size()); + AttachmentUploader::UploadResult result = + AttachmentUploader::UPLOAD_SUCCESS; + // Fail the 2nd one. + if (i == 2U) { + result = AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR; + } else { + result = AttachmentUploader::UPLOAD_SUCCESS; + } + uploader()->RespondToUpload(uploader()->upload_requests.begin()->first, + result); + RunLoop(); + } + ASSERT_EQ(2U, on_attachment_uploaded_list().size()); +} + +// Attempt an upload, respond with transient error to trigger backoff, issue +// network disconnect/connect events and see that backoff is cleared. +TEST_F(AttachmentServiceImplTest, + UploadAttachments_ResetBackoffAfterNetworkChange) { + AttachmentIdSet attachment_ids; + attachment_ids.insert(AttachmentId::Create()); + attachment_service()->UploadAttachments(attachment_ids); + + RunLoopAndFireTimer(); + ASSERT_EQ(1U, store()->read_ids.size()); + store()->RespondToRead(attachment_ids); + RunLoop(); + ASSERT_EQ(1U, uploader()->upload_requests.size()); + + uploader()->RespondToUpload(uploader()->upload_requests.begin()->first, + AttachmentUploader::UPLOAD_TRANSIENT_ERROR); RunLoop(); - ASSERT_EQ(1U, store_results().size()); - EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]); - EXPECT_TRUE(on_attachment_uploaded_list().empty()); + + // See that we are in backoff. + ASSERT_TRUE(mock_timer()->IsRunning()); + ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta()); + + // Issue a network disconnect event. + network_change_notifier()->NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_NONE); + RunLoop(); + + // Still in backoff. + ASSERT_TRUE(mock_timer()->IsRunning()); + ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta()); + + // Issue a network connect event. + net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( + net::NetworkChangeNotifier::CONNECTION_WIFI); + RunLoop(); + + // No longer in backoff. + ASSERT_TRUE(mock_timer()->IsRunning()); + ASSERT_EQ(base::TimeDelta(), mock_timer()->GetCurrentDelay()); } } // namespace syncer