drive: Rename DriveSyncClient to SyncClient
As part of an effort to remove 'drive' prefix from c/b/chromeos/drive.
BUG=231807
TEST=none
Review URL: https://chromiumcodereview.appspot.com/14224011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195893 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/drive/sync_client_unittest.cc b/chrome/browser/chromeos/drive/sync_client_unittest.cc
new file mode 100644
index 0000000..3947fe7
--- /dev/null
+++ b/chrome/browser/chromeos/drive/sync_client_unittest.cc
@@ -0,0 +1,299 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/sync_client.h"
+
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/drive_cache.h"
+#include "chrome/browser/chromeos/drive/drive_file_system_util.h"
+#include "chrome/browser/chromeos/drive/drive_test_util.h"
+#include "chrome/browser/chromeos/drive/mock_drive_file_system.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::StrictMock;
+using ::testing::_;
+
+namespace drive {
+
+namespace {
+
+// Action used to set mock expectations for GetFileByResourceId().
+ACTION_P4(MockGetFileByResourceId, error, local_path, mime_type, file_type) {
+ arg2.Run(error, local_path, mime_type, file_type);
+}
+
+// Action used to set mock expectations for UpdateFileByResourceId().
+ACTION_P(MockUpdateFileByResourceId, error) {
+ arg2.Run(error);
+}
+
+// Action used to set mock expectations for GetFileInfoByResourceId().
+ACTION_P2(MockUpdateFileByResourceId, error, md5) {
+ scoped_ptr<DriveEntryProto> entry_proto(new DriveEntryProto);
+ entry_proto->mutable_file_specific_info()->set_file_md5(md5);
+ arg1.Run(error, base::FilePath(), entry_proto.Pass());
+}
+
+} // namespace
+
+class SyncClientTest : public testing::Test {
+ public:
+ SyncClientTest()
+ : ui_thread_(content::BrowserThread::UI, &message_loop_),
+ mock_file_system_(new StrictMock<MockDriveFileSystem>) {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ // Create a temporary directory.
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ // Initialize the cache.
+ scoped_refptr<base::SequencedWorkerPool> pool =
+ content::BrowserThread::GetBlockingPool();
+ cache_.reset(new DriveCache(
+ temp_dir_.path(),
+ pool->GetSequencedTaskRunner(pool->GetSequenceToken()),
+ NULL /* free_disk_space_getter */));
+ bool success = false;
+ cache_->RequestInitialize(
+ google_apis::test_util::CreateCopyResultCallback(&success));
+ google_apis::test_util::RunBlockingPoolTask();
+ ASSERT_TRUE(success);
+ SetUpCache();
+
+ // Initialize the sync client.
+ EXPECT_CALL(*mock_file_system_, AddObserver(_)).Times(1);
+ EXPECT_CALL(*mock_file_system_, RemoveObserver(_)).Times(1);
+ sync_client_.reset(new SyncClient(mock_file_system_.get(), cache_.get()));
+
+ // Disable delaying so that DoSyncLoop() starts immediately.
+ sync_client_->set_delay_for_testing(base::TimeDelta::FromSeconds(0));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ sync_client_.reset();
+ cache_.reset();
+ }
+
+ // Sets up cache for tests.
+ void SetUpCache() {
+ // Prepare a temp file.
+ base::FilePath temp_file;
+ EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file));
+ const std::string content = "hello";
+ EXPECT_EQ(static_cast<int>(content.size()),
+ file_util::WriteFile(temp_file, content.data(), content.size()));
+
+ // Prepare 3 pinned-but-not-present files.
+ FileError error = FILE_ERROR_OK;
+ cache_->Pin("resource_id_not_fetched_foo", "",
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ cache_->Pin("resource_id_not_fetched_bar", "",
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ cache_->Pin("resource_id_not_fetched_baz", "",
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ // Prepare a pinned-and-fetched file.
+ const std::string resource_id_fetched = "resource_id_fetched";
+ const std::string md5_fetched = "md5";
+ base::FilePath cache_file_path;
+ cache_->Store(resource_id_fetched, md5_fetched, temp_file,
+ DriveCache::FILE_OPERATION_COPY,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ cache_->Pin(resource_id_fetched, md5_fetched,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+
+ // Prepare a pinned-and-fetched-and-dirty file.
+ const std::string resource_id_dirty = "resource_id_dirty";
+ const std::string md5_dirty = ""; // Don't care.
+ cache_->Store(resource_id_dirty, md5_dirty, temp_file,
+ DriveCache::FILE_OPERATION_COPY,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ cache_->Pin(resource_id_dirty, md5_dirty,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ cache_->MarkDirty(
+ resource_id_dirty, md5_dirty,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ cache_->CommitDirty(
+ resource_id_dirty, md5_dirty,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ google_apis::test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ }
+
+ // Sets the expectation for MockDriveFileSystem::GetFileByResourceId(),
+ // that simulates successful retrieval of a file for the given resource ID.
+ void SetExpectationForGetFileByResourceId(const std::string& resource_id) {
+ EXPECT_CALL(*mock_file_system_,
+ GetFileByResourceId(resource_id, _, _, _))
+ .WillOnce(
+ MockGetFileByResourceId(
+ FILE_ERROR_OK,
+ base::FilePath::FromUTF8Unsafe("local_path_does_not_matter"),
+ std::string("mime_type_does_not_matter"),
+ REGULAR_FILE));
+ }
+
+ // Sets the expectation for MockDriveFileSystem::UpdateFileByResourceId(),
+ // that simulates successful uploading of a file for the given resource ID.
+ void SetExpectationForUpdateFileByResourceId(
+ const std::string& resource_id) {
+ EXPECT_CALL(*mock_file_system_,
+ UpdateFileByResourceId(resource_id, _, _))
+ .WillOnce(MockUpdateFileByResourceId(FILE_ERROR_OK));
+ }
+
+ // Sets the expectation for MockDriveFileSystem::GetFileInfoByResourceId(),
+ // that simulates successful retrieval of file info for the given resource
+ // ID.
+ //
+ // This is used for testing StartCheckingExistingPinnedFiles(), hence we
+ // are only interested in the MD5 value in DriveEntryProto.
+ void SetExpectationForGetFileInfoByResourceId(
+ const std::string& resource_id,
+ const std::string& new_md5) {
+ EXPECT_CALL(*mock_file_system_,
+ GetEntryInfoByResourceId(resource_id, _))
+ .WillOnce(MockUpdateFileByResourceId(
+ FILE_ERROR_OK,
+ new_md5));
+ }
+
+ // Returns the resource IDs in the queue to be fetched.
+ std::vector<std::string> GetResourceIdsToBeFetched() {
+ return sync_client_->GetResourceIdsForTesting(SyncClient::FETCH);
+ }
+
+ // Returns the resource IDs in the queue to be uploaded.
+ std::vector<std::string> GetResourceIdsToBeUploaded() {
+ return sync_client_->GetResourceIdsForTesting(SyncClient::UPLOAD);
+ }
+
+ // Adds a resource ID of a file to fetch.
+ void AddResourceIdToFetch(const std::string& resource_id) {
+ sync_client_->AddResourceIdForTesting(SyncClient::FETCH, resource_id);
+ }
+
+ // Adds a resource ID of a file to upload.
+ void AddResourceIdToUpload(const std::string& resource_id) {
+ sync_client_->AddResourceIdForTesting(SyncClient::UPLOAD, resource_id);
+ }
+
+ protected:
+ MessageLoopForUI message_loop_;
+ content::TestBrowserThread ui_thread_;
+ base::ScopedTempDir temp_dir_;
+ scoped_ptr<StrictMock<MockDriveFileSystem> > mock_file_system_;
+ scoped_ptr<DriveCache, test_util::DestroyHelperForTests> cache_;
+ scoped_ptr<SyncClient> sync_client_;
+};
+
+TEST_F(SyncClientTest, StartInitialScan) {
+ // Start processing the files in the backlog. This will collect the
+ // resource IDs of these files.
+ sync_client_->StartProcessingBacklog();
+
+ // Check the contents of the queue for fetching.
+ SetExpectationForGetFileByResourceId("resource_id_not_fetched_bar");
+ SetExpectationForGetFileByResourceId("resource_id_not_fetched_baz");
+ SetExpectationForGetFileByResourceId("resource_id_not_fetched_foo");
+
+ // Check the contents of the queue for uploading.
+ SetExpectationForUpdateFileByResourceId("resource_id_dirty");
+
+ google_apis::test_util::RunBlockingPoolTask();
+}
+
+TEST_F(SyncClientTest, OnCachePinned) {
+ // This file will be fetched by GetFileByResourceId() as OnCachePinned()
+ // will kick off the sync loop.
+ SetExpectationForGetFileByResourceId("resource_id_not_fetched_foo");
+
+ sync_client_->OnCachePinned("resource_id_not_fetched_foo", "md5");
+
+ google_apis::test_util::RunBlockingPoolTask();
+}
+
+TEST_F(SyncClientTest, OnCacheUnpinned) {
+ AddResourceIdToFetch("resource_id_not_fetched_foo");
+ AddResourceIdToFetch("resource_id_not_fetched_bar");
+ AddResourceIdToFetch("resource_id_not_fetched_baz");
+ ASSERT_EQ(3U, GetResourceIdsToBeFetched().size());
+
+ sync_client_->OnCacheUnpinned("resource_id_not_fetched_foo", "md5");
+ sync_client_->OnCacheUnpinned("resource_id_not_fetched_baz", "md5");
+
+ // Only resource_id_not_fetched_foo should be fetched.
+ SetExpectationForGetFileByResourceId("resource_id_not_fetched_bar");
+
+ google_apis::test_util::RunBlockingPoolTask();
+}
+
+TEST_F(SyncClientTest, Deduplication) {
+ AddResourceIdToFetch("resource_id_not_fetched_foo");
+
+ // Set the delay so that DoSyncLoop() is delayed.
+ sync_client_->set_delay_for_testing(TestTimeouts::action_max_timeout());
+ // Raise OnCachePinned() event. This shouldn't result in adding the second
+ // task, as tasks are de-duplicated.
+ sync_client_->OnCachePinned("resource_id_not_fetched_foo", "md5");
+
+ ASSERT_EQ(1U, GetResourceIdsToBeFetched().size());
+}
+
+TEST_F(SyncClientTest, ExistingPinnedFiles) {
+ // Set the expectation so that the MockDriveFileSystem returns "new_md5"
+ // for "resource_id_fetched". This simulates that the file is updated on
+ // the server side, and the new MD5 is obtained from the server (i.e. the
+ // local cache file is stale).
+ SetExpectationForGetFileInfoByResourceId("resource_id_fetched",
+ "new_md5");
+ // Set the expectation so that the MockDriveFileSystem returns "some_md5"
+ // for "resource_id_dirty". The MD5 on the server is always different from
+ // the MD5 of a dirty file, which is set to "local". We should not collect
+ // this by StartCheckingExistingPinnedFiles().
+ SetExpectationForGetFileInfoByResourceId("resource_id_dirty",
+ "some_md5");
+
+ // Start checking the existing pinned files. This will collect the resource
+ // IDs of pinned files, with stale local cache files.
+ sync_client_->StartCheckingExistingPinnedFiles();
+
+ SetExpectationForGetFileByResourceId("resource_id_fetched");
+
+ google_apis::test_util::RunBlockingPoolTask();
+}
+
+} // namespace drive