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