blob: 0797cf75d3ee55389139024c19b080622942c9c3 [file] [log] [blame]
[email protected]92b84f332012-03-21 20:45:211// Copyright (c) 2012 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
[email protected]d876d70b2013-04-23 20:06:155#include "chrome/browser/chromeos/drive/sync_client.h"
[email protected]92b84f332012-03-21 20:45:216
[email protected]92b84f332012-03-21 20:45:217#include "base/file_util.h"
[email protected]57999812013-02-24 05:40:528#include "base/files/file_path.h"
[email protected]ea1a3f62012-11-16 20:34:239#include "base/files/scoped_temp_dir.h"
[email protected]92b84f332012-03-21 20:45:2110#include "base/memory/scoped_ptr.h"
[email protected]b568b882013-06-10 04:38:0711#include "base/run_loop.h"
[email protected]b83e5202012-06-27 07:50:2412#include "base/test/test_timeouts.h"
[email protected]b568b882013-06-10 04:38:0713#include "chrome/browser/chromeos/drive/change_list_loader.h"
[email protected]15de8142012-10-11 06:00:5414#include "chrome/browser/chromeos/drive/drive.pb.h"
[email protected]eca3fc92013-05-01 03:53:4015#include "chrome/browser/chromeos/drive/file_cache.h"
[email protected]b568b882013-06-10 04:38:0716#include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
17#include "chrome/browser/chromeos/drive/job_scheduler.h"
18#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
19#include "chrome/browser/chromeos/drive/resource_metadata.h"
[email protected]92931d72013-04-24 05:16:1520#include "chrome/browser/chromeos/drive/test_util.h"
[email protected]b568b882013-06-10 04:38:0721#include "chrome/browser/google_apis/fake_drive_service.h"
[email protected]7601e182013-03-22 09:38:0222#include "chrome/browser/google_apis/test_util.h"
[email protected]b568b882013-06-10 04:38:0723#include "chrome/test/base/testing_profile.h"
24#include "content/public/test/test_browser_thread_bundle.h"
[email protected]92b84f332012-03-21 20:45:2125#include "testing/gtest/include/gtest/gtest.h"
26
[email protected]d9d04df2012-10-12 07:06:3527namespace drive {
[email protected]4e87c4862013-05-20 04:06:3228namespace internal {
[email protected]92b84f332012-03-21 20:45:2129
[email protected]80199362012-09-09 23:24:2930namespace {
31
[email protected]b568b882013-06-10 04:38:0732// The content of files iniitally stored in the cache.
33const char kLocalContent[] = "Hello!";
[email protected]61a41c12013-06-06 06:23:3634
[email protected]b568b882013-06-10 04:38:0735// The content of files stored in the service.
36const char kRemoteContent[] = "World!";
37
38// SyncClientTestDriveService will return GDATA_CANCELLED when a request is
39// made with the specified resource ID.
40class SyncClientTestDriveService : public google_apis::FakeDriveService {
[email protected]67e264a2013-06-03 05:39:0141 public:
[email protected]b568b882013-06-10 04:38:0742 // FakeDriveService override:
43 virtual void GetResourceEntry(
[email protected]67e264a2013-06-03 05:39:0144 const std::string& resource_id,
[email protected]b568b882013-06-10 04:38:0745 const google_apis::GetResourceEntryCallback& callback) OVERRIDE {
46 if (resource_id == resource_id_to_be_cancelled_) {
47 scoped_ptr<google_apis::ResourceEntry> null;
48 base::MessageLoopProxy::current()->PostTask(
49 FROM_HERE,
50 base::Bind(callback,
51 google_apis::GDATA_CANCELLED,
52 base::Passed(&null)));
[email protected]61a41c12013-06-06 06:23:3653 return;
54 }
[email protected]b568b882013-06-10 04:38:0755 FakeDriveService::GetResourceEntry(resource_id, callback);
[email protected]67e264a2013-06-03 05:39:0156 }
[email protected]aaa70a42012-06-05 22:22:5157
[email protected]b568b882013-06-10 04:38:0758 void set_resource_id_to_be_cancelled(const std::string& resource_id) {
59 resource_id_to_be_cancelled_ = resource_id;
[email protected]67e264a2013-06-03 05:39:0160 }
[email protected]b83e5202012-06-27 07:50:2461
[email protected]67e264a2013-06-03 05:39:0162 private:
[email protected]b568b882013-06-10 04:38:0763 std::string resource_id_to_be_cancelled_;
64};
65
66class DummyOperationObserver : public file_system::OperationObserver {
67 virtual void OnDirectoryChangedByOperation(
68 const base::FilePath& path) OVERRIDE {}
[email protected]67e264a2013-06-03 05:39:0169};
[email protected]85b62192012-06-29 19:56:3870
[email protected]80199362012-09-09 23:24:2971} // namespace
72
[email protected]d876d70b2013-04-23 20:06:1573class SyncClientTest : public testing::Test {
[email protected]ffd60e432012-03-24 20:36:0074 public:
[email protected]92b84f332012-03-21 20:45:2175 virtual void SetUp() OVERRIDE {
[email protected]92b84f332012-03-21 20:45:2176 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
77
[email protected]b568b882013-06-10 04:38:0778 profile_.reset(new TestingProfile);
79
80 drive_service_.reset(new SyncClientTestDriveService);
81 drive_service_->LoadResourceListForWapi("chromeos/gdata/empty_feed.json");
82 drive_service_->LoadAccountMetadataForWapi(
83 "chromeos/gdata/account_metadata.json");
84
85 scheduler_.reset(new JobScheduler(profile_.get(), drive_service_.get()));
86 metadata_.reset(new internal::ResourceMetadata(
87 temp_dir_.path(), base::MessageLoopProxy::current()));
88 FileError error = FILE_ERROR_FAILED;
89 metadata_->Initialize(
90 google_apis::test_util::CreateCopyResultCallback(&error));
91 base::RunLoop().RunUntilIdle();
92 ASSERT_EQ(FILE_ERROR_OK, error);
93
94 cache_.reset(new FileCache(temp_dir_.path(),
95 base::MessageLoopProxy::current(),
96 NULL /* free_disk_space_getter */));
[email protected]e76fd272013-03-25 13:37:1497 bool success = false;
[email protected]e63bdc972012-11-22 12:10:4898 cache_->RequestInitialize(
[email protected]e76fd272013-03-25 13:37:1499 google_apis::test_util::CreateCopyResultCallback(&success));
[email protected]b568b882013-06-10 04:38:07100 base::RunLoop().RunUntilIdle();
[email protected]e76fd272013-03-25 13:37:14101 ASSERT_TRUE(success);
[email protected]e63bdc972012-11-22 12:10:48102
[email protected]b568b882013-06-10 04:38:07103 ASSERT_NO_FATAL_FAILURE(SetUpTestData());
104
105 sync_client_.reset(new SyncClient(base::MessageLoopProxy::current(),
106 &observer_,
107 scheduler_.get(),
108 metadata_.get(),
109 cache_.get()));
[email protected]e0529fc2012-06-12 11:07:58110
[email protected]b83e5202012-06-27 07:50:24111 // Disable delaying so that DoSyncLoop() starts immediately.
112 sync_client_->set_delay_for_testing(base::TimeDelta::FromSeconds(0));
[email protected]92b84f332012-03-21 20:45:21113 }
114
[email protected]a5381772012-04-05 02:20:04115 virtual void TearDown() OVERRIDE {
[email protected]2416a2e2012-05-07 20:58:49116 sync_client_.reset();
[email protected]c0a3b8e82013-03-18 21:07:45117 cache_.reset();
[email protected]b568b882013-06-10 04:38:07118 metadata_.reset();
[email protected]a5381772012-04-05 02:20:04119 }
120
[email protected]b568b882013-06-10 04:38:07121 // Adds a file to the service root and |resource_ids_|.
122 void AddFileEntry(const std::string& title) {
123 google_apis::GDataErrorCode error = google_apis::GDATA_FILE_ERROR;
124 scoped_ptr<google_apis::ResourceEntry> entry;
125 drive_service_->AddNewFile(
126 "text/plain",
127 kRemoteContent,
128 drive_service_->GetRootResourceId(),
129 title,
130 false, // shared_with_me
131 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
132 base::RunLoop().RunUntilIdle();
133 ASSERT_EQ(google_apis::HTTP_CREATED, error);
134 ASSERT_TRUE(entry);
135 resource_ids_[title] = entry->resource_id();
136 }
137
138 // Sets up data for tests.
139 void SetUpTestData() {
[email protected]e63bdc972012-11-22 12:10:48140 // Prepare a temp file.
[email protected]650b2d52013-02-10 03:41:45141 base::FilePath temp_file;
[email protected]e63bdc972012-11-22 12:10:48142 EXPECT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
143 &temp_file));
[email protected]b568b882013-06-10 04:38:07144 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(temp_file,
145 kLocalContent));
[email protected]b83e5202012-06-27 07:50:24146
[email protected]e63bdc972012-11-22 12:10:48147 // Prepare 3 pinned-but-not-present files.
[email protected]b568b882013-06-10 04:38:07148 ASSERT_NO_FATAL_FAILURE(AddFileEntry("foo"));
149 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(resource_ids_["foo"], std::string()));
[email protected]e63bdc972012-11-22 12:10:48150
[email protected]b568b882013-06-10 04:38:07151 ASSERT_NO_FATAL_FAILURE(AddFileEntry("bar"));
152 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(resource_ids_["bar"], std::string()));
[email protected]e63bdc972012-11-22 12:10:48153
[email protected]b568b882013-06-10 04:38:07154 ASSERT_NO_FATAL_FAILURE(AddFileEntry("baz"));
155 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(resource_ids_["baz"], std::string()));
[email protected]e63bdc972012-11-22 12:10:48156
157 // Prepare a pinned-and-fetched file.
[email protected]e63bdc972012-11-22 12:10:48158 const std::string md5_fetched = "md5";
[email protected]b568b882013-06-10 04:38:07159 ASSERT_NO_FATAL_FAILURE(AddFileEntry("fetched"));
160 EXPECT_EQ(FILE_ERROR_OK,
161 cache_->Store(resource_ids_["fetched"], md5_fetched,
162 temp_file, FileCache::FILE_OPERATION_COPY));
163 EXPECT_EQ(FILE_ERROR_OK,
164 cache_->Pin(resource_ids_["fetched"], md5_fetched));
[email protected]e63bdc972012-11-22 12:10:48165
166 // Prepare a pinned-and-fetched-and-dirty file.
[email protected]e63bdc972012-11-22 12:10:48167 const std::string md5_dirty = ""; // Don't care.
[email protected]b568b882013-06-10 04:38:07168 ASSERT_NO_FATAL_FAILURE(AddFileEntry("dirty"));
169 EXPECT_EQ(FILE_ERROR_OK,
170 cache_->Store(resource_ids_["dirty"], md5_dirty,
171 temp_file, FileCache::FILE_OPERATION_COPY));
172 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(resource_ids_["dirty"], md5_dirty));
173 EXPECT_EQ(FILE_ERROR_OK,
174 cache_->MarkDirty(resource_ids_["dirty"], md5_dirty));
[email protected]adf84402012-03-25 21:56:38175
[email protected]b568b882013-06-10 04:38:07176 // Load data from the service to the metadata.
177 FileError error = FILE_ERROR_FAILED;
178 internal::ChangeListLoader change_list_loader(
179 base::MessageLoopProxy::current(), metadata_.get(), scheduler_.get());
180 change_list_loader.LoadIfNeeded(
181 DirectoryFetchInfo(),
182 google_apis::test_util::CreateCopyResultCallback(&error));
183 base::RunLoop().RunUntilIdle();
184 EXPECT_EQ(FILE_ERROR_OK, error);
[email protected]b83e5202012-06-27 07:50:24185 }
186
[email protected]ffd60e432012-03-24 20:36:00187 protected:
[email protected]b568b882013-06-10 04:38:07188 content::TestBrowserThreadBundle thread_bundle_;
[email protected]ea1a3f62012-11-16 20:34:23189 base::ScopedTempDir temp_dir_;
[email protected]b568b882013-06-10 04:38:07190 scoped_ptr<TestingProfile> profile_;
191 scoped_ptr<SyncClientTestDriveService> drive_service_;
192 DummyOperationObserver observer_;
193 scoped_ptr<JobScheduler> scheduler_;
194 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
195 metadata_;
[email protected]4e87c4862013-05-20 04:06:32196 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
[email protected]d876d70b2013-04-23 20:06:15197 scoped_ptr<SyncClient> sync_client_;
[email protected]b568b882013-06-10 04:38:07198
199 std::map<std::string, std::string> resource_ids_; // Name-to-id map.
[email protected]92b84f332012-03-21 20:45:21200};
201
[email protected]b568b882013-06-10 04:38:07202TEST_F(SyncClientTest, StartProcessingBacklog) {
[email protected]b83e5202012-06-27 07:50:24203 sync_client_->StartProcessingBacklog();
[email protected]b568b882013-06-10 04:38:07204 base::RunLoop().RunUntilIdle();
[email protected]92b84f332012-03-21 20:45:21205
[email protected]b568b882013-06-10 04:38:07206 FileCacheEntry cache_entry;
207 // Pinned files get downloaded.
208 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
209 &cache_entry));
210 EXPECT_TRUE(cache_entry.is_present());
[email protected]b83e5202012-06-27 07:50:24211
[email protected]b568b882013-06-10 04:38:07212 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["bar"], std::string(),
213 &cache_entry));
214 EXPECT_TRUE(cache_entry.is_present());
215
216 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["baz"], std::string(),
217 &cache_entry));
218 EXPECT_TRUE(cache_entry.is_present());
219
220 // Dirty file gets uploaded.
221 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["dirty"], std::string(),
222 &cache_entry));
223 EXPECT_FALSE(cache_entry.is_dirty());
[email protected]a5381772012-04-05 02:20:04224}
225
[email protected]d876d70b2013-04-23 20:06:15226TEST_F(SyncClientTest, OnCachePinned) {
[email protected]b83e5202012-06-27 07:50:24227 // This file will be fetched by GetFileByResourceId() as OnCachePinned()
[email protected]b7c5da72012-06-26 05:27:46228 // will kick off the sync loop.
[email protected]b568b882013-06-10 04:38:07229 sync_client_->OnCachePinned(resource_ids_["foo"], std::string());
230 base::RunLoop().RunUntilIdle();
[email protected]67e264a2013-06-03 05:39:01231
[email protected]b568b882013-06-10 04:38:07232 FileCacheEntry cache_entry;
233 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
234 &cache_entry));
235 EXPECT_TRUE(cache_entry.is_present());
[email protected]adf84402012-03-25 21:56:38236}
237
[email protected]61a41c12013-06-06 06:23:36238TEST_F(SyncClientTest, OnCachePinnedAndCancelled) {
[email protected]b568b882013-06-10 04:38:07239 drive_service_->set_resource_id_to_be_cancelled(resource_ids_["foo"]);
[email protected]61a41c12013-06-06 06:23:36240 // Trigger fetching of a file which results in cancellation.
241 FileError error = FILE_ERROR_FAILED;
242 cache_->PinOnUIThread(
[email protected]b568b882013-06-10 04:38:07243 resource_ids_["foo"], std::string(),
[email protected]61a41c12013-06-06 06:23:36244 google_apis::test_util::CreateCopyResultCallback(&error));
[email protected]b568b882013-06-10 04:38:07245 base::RunLoop().RunUntilIdle();
[email protected]61a41c12013-06-06 06:23:36246 EXPECT_EQ(FILE_ERROR_OK, error);
247
248 // The file should be unpinned if the user wants the download to be cancelled.
[email protected]61a41c12013-06-06 06:23:36249 FileCacheEntry cache_entry;
[email protected]b568b882013-06-10 04:38:07250 EXPECT_FALSE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
251 &cache_entry));
[email protected]61a41c12013-06-06 06:23:36252}
253
[email protected]d876d70b2013-04-23 20:06:15254TEST_F(SyncClientTest, OnCacheUnpinned) {
[email protected]b568b882013-06-10 04:38:07255 sync_client_->AddResourceIdForTesting(SyncClient::FETCH,
256 resource_ids_["foo"]);
257 sync_client_->AddResourceIdForTesting(SyncClient::FETCH,
258 resource_ids_["bar"]);
259 sync_client_->AddResourceIdForTesting(SyncClient::FETCH,
260 resource_ids_["baz"]);
261 ASSERT_EQ(3U,
262 sync_client_->GetResourceIdsForTesting(SyncClient::FETCH).size());
[email protected]adf84402012-03-25 21:56:38263
[email protected]b568b882013-06-10 04:38:07264 sync_client_->OnCacheUnpinned(resource_ids_["foo"], std::string());
265 sync_client_->OnCacheUnpinned(resource_ids_["baz"], std::string());
266 base::RunLoop().RunUntilIdle();
[email protected]e07bbd972013-01-23 17:38:42267
[email protected]b568b882013-06-10 04:38:07268 // Only "bar" should be fetched.
269 FileCacheEntry cache_entry;
270 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["foo"], std::string(),
271 &cache_entry));
272 EXPECT_FALSE(cache_entry.is_present());
273
274 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["bar"], std::string(),
275 &cache_entry));
276 EXPECT_TRUE(cache_entry.is_present());
277
278 EXPECT_TRUE(cache_->GetCacheEntry(resource_ids_["baz"], std::string(),
279 &cache_entry));
280 EXPECT_FALSE(cache_entry.is_present());
281
[email protected]adf84402012-03-25 21:56:38282}
283
[email protected]d876d70b2013-04-23 20:06:15284TEST_F(SyncClientTest, Deduplication) {
[email protected]b568b882013-06-10 04:38:07285 sync_client_->AddResourceIdForTesting(SyncClient::FETCH,
286 resource_ids_["foo"]);
[email protected]b83e5202012-06-27 07:50:24287
288 // Set the delay so that DoSyncLoop() is delayed.
289 sync_client_->set_delay_for_testing(TestTimeouts::action_max_timeout());
290 // Raise OnCachePinned() event. This shouldn't result in adding the second
291 // task, as tasks are de-duplicated.
[email protected]b568b882013-06-10 04:38:07292 sync_client_->OnCachePinned(resource_ids_["foo"], std::string());
[email protected]b83e5202012-06-27 07:50:24293
[email protected]b568b882013-06-10 04:38:07294 ASSERT_EQ(1U,
295 sync_client_->GetResourceIdsForTesting(SyncClient::FETCH).size());
[email protected]b83e5202012-06-27 07:50:24296}
297
[email protected]d876d70b2013-04-23 20:06:15298TEST_F(SyncClientTest, ExistingPinnedFiles) {
[email protected]85b62192012-06-29 19:56:38299 // Start checking the existing pinned files. This will collect the resource
300 // IDs of pinned files, with stale local cache files.
301 sync_client_->StartCheckingExistingPinnedFiles();
[email protected]b568b882013-06-10 04:38:07302 base::RunLoop().RunUntilIdle();
[email protected]67e264a2013-06-03 05:39:01303
[email protected]b568b882013-06-10 04:38:07304 // "fetched" and "dirty" are the existing pinned files.
305 // The non-dirty one should be synced, but the dirty one should not.
306 base::FilePath cache_file;
307 std::string content;
308 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_ids_["fetched"],
309 std::string(), &cache_file));
310 EXPECT_TRUE(file_util::ReadFileToString(cache_file, &content));
311 EXPECT_EQ(kRemoteContent, content);
312 content.clear();
313
314 EXPECT_EQ(FILE_ERROR_OK, cache_->GetFile(resource_ids_["dirty"],
315 std::string(), &cache_file));
316 EXPECT_TRUE(file_util::ReadFileToString(cache_file, &content));
317 EXPECT_EQ(kLocalContent, content);
[email protected]189541ba2012-10-24 11:18:15318}
319
[email protected]4e87c4862013-05-20 04:06:32320} // namespace internal
[email protected]d9d04df2012-10-12 07:06:35321} // namespace drive