1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/drive/change_list_loader.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/prefs/testing_pref_service.h"
10 #include "base/run_loop.h"
11 #include "chrome/browser/chromeos/drive/change_list_loader_observer.h"
12 #include "chrome/browser/chromeos/drive/change_list_processor.h"
13 #include "chrome/browser/chromeos/drive/file_cache.h"
14 #include "chrome/browser/chromeos/drive/file_system_util.h"
15 #include "chrome/browser/chromeos/drive/job_scheduler.h"
16 #include "chrome/browser/chromeos/drive/resource_metadata.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/google_apis/test_util.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 class TestChangeListLoaderObserver : public ChangeListLoaderObserver {
28 explicit TestChangeListLoaderObserver(ChangeListLoader* loader)
30 load_from_server_complete_count_(0),
31 initial_load_complete_count_(0) {
32 loader_->AddObserver(this);
35 virtual ~TestChangeListLoaderObserver() {
36 loader_->RemoveObserver(this);
39 const std::set<base::FilePath>& changed_directories() const {
40 return changed_directories_;
42 void clear_changed_directories() { changed_directories_.clear(); }
44 int load_from_server_complete_count() const {
45 return load_from_server_complete_count_;
47 int initial_load_complete_count() const {
48 return initial_load_complete_count_;
51 // ChageListObserver overrides:
52 virtual void OnDirectoryChanged(
53 const base::FilePath& directory_path) OVERRIDE {
54 changed_directories_.insert(directory_path);
56 virtual void OnLoadFromServerComplete() OVERRIDE {
57 ++load_from_server_complete_count_;
59 virtual void OnInitialLoadComplete() OVERRIDE {
60 ++initial_load_complete_count_;
64 ChangeListLoader* loader_;
65 std::set<base::FilePath> changed_directories_;
66 int load_from_server_complete_count_;
67 int initial_load_complete_count_;
69 DISALLOW_COPY_AND_ASSIGN(TestChangeListLoaderObserver);
72 class ChangeListLoaderTest : public testing::Test {
74 virtual void SetUp() OVERRIDE {
75 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
76 pref_service_.reset(new TestingPrefServiceSimple);
77 test_util::RegisterDrivePrefs(pref_service_->registry());
79 drive_service_.reset(new FakeDriveService);
80 ASSERT_TRUE(drive_service_->LoadResourceListForWapi(
81 "gdata/root_feed.json"));
82 ASSERT_TRUE(drive_service_->LoadAccountMetadataForWapi(
83 "gdata/account_metadata.json"));
85 scheduler_.reset(new JobScheduler(pref_service_.get(),
87 base::MessageLoopProxy::current().get()));
88 metadata_storage_.reset(new ResourceMetadataStorage(
89 temp_dir_.path(), base::MessageLoopProxy::current().get()));
90 ASSERT_TRUE(metadata_storage_->Initialize());
92 metadata_.reset(new ResourceMetadata(
93 metadata_storage_.get(), base::MessageLoopProxy::current().get()));
94 ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
96 cache_.reset(new FileCache(metadata_storage_.get(),
98 base::MessageLoopProxy::current().get(),
99 NULL /* free_disk_space_getter */));
100 ASSERT_TRUE(cache_->Initialize());
102 change_list_loader_.reset(
103 new ChangeListLoader(base::MessageLoopProxy::current().get(),
106 drive_service_.get()));
109 // Adds a new file to the root directory of the service.
110 scoped_ptr<google_apis::ResourceEntry> AddNewFile(const std::string& title) {
111 google_apis::GDataErrorCode error = google_apis::GDATA_FILE_ERROR;
112 scoped_ptr<google_apis::ResourceEntry> entry;
113 drive_service_->AddNewFile(
116 drive_service_->GetRootResourceId(),
118 false, // shared_with_me
119 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
120 base::RunLoop().RunUntilIdle();
121 EXPECT_EQ(google_apis::HTTP_CREATED, error);
125 content::TestBrowserThreadBundle thread_bundle_;
126 base::ScopedTempDir temp_dir_;
127 scoped_ptr<TestingPrefServiceSimple> pref_service_;
128 scoped_ptr<FakeDriveService> drive_service_;
129 scoped_ptr<JobScheduler> scheduler_;
130 scoped_ptr<ResourceMetadataStorage,
131 test_util::DestroyHelperForTests> metadata_storage_;
132 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
133 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
134 scoped_ptr<ChangeListLoader> change_list_loader_;
137 TEST_F(ChangeListLoaderTest, LoadIfNeeded) {
138 EXPECT_FALSE(change_list_loader_->IsRefreshing());
140 // Start initial load.
141 TestChangeListLoaderObserver observer(change_list_loader_.get());
143 FileError error = FILE_ERROR_FAILED;
144 change_list_loader_->LoadIfNeeded(
145 DirectoryFetchInfo(),
146 google_apis::test_util::CreateCopyResultCallback(&error));
147 EXPECT_TRUE(change_list_loader_->IsRefreshing());
148 base::RunLoop().RunUntilIdle();
149 EXPECT_EQ(FILE_ERROR_OK, error);
151 EXPECT_FALSE(change_list_loader_->IsRefreshing());
152 EXPECT_LT(0, metadata_->GetLargestChangestamp());
153 EXPECT_EQ(1, drive_service_->resource_list_load_count());
154 EXPECT_EQ(1, observer.initial_load_complete_count());
155 EXPECT_EQ(1, observer.load_from_server_complete_count());
156 EXPECT_TRUE(observer.changed_directories().empty());
158 base::FilePath file_path =
159 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
161 EXPECT_EQ(FILE_ERROR_OK,
162 metadata_->GetResourceEntryByPath(file_path, &entry));
164 // Reload. This should result in no-op.
165 int64 previous_changestamp = metadata_->GetLargestChangestamp();
166 int previous_resource_list_load_count =
167 drive_service_->resource_list_load_count();
168 change_list_loader_->LoadIfNeeded(
169 DirectoryFetchInfo(),
170 google_apis::test_util::CreateCopyResultCallback(&error));
171 EXPECT_FALSE(change_list_loader_->IsRefreshing());
172 base::RunLoop().RunUntilIdle();
173 EXPECT_EQ(FILE_ERROR_OK, error);
175 EXPECT_FALSE(change_list_loader_->IsRefreshing());
176 EXPECT_EQ(previous_changestamp, metadata_->GetLargestChangestamp());
177 EXPECT_EQ(previous_resource_list_load_count,
178 drive_service_->resource_list_load_count());
181 TEST_F(ChangeListLoaderTest, LoadIfNeeded_LocalMetadataAvailable) {
183 FileError error = FILE_ERROR_FAILED;
184 change_list_loader_->LoadIfNeeded(
185 DirectoryFetchInfo(),
186 google_apis::test_util::CreateCopyResultCallback(&error));
187 base::RunLoop().RunUntilIdle();
188 EXPECT_EQ(FILE_ERROR_OK, error);
191 change_list_loader_.reset(
192 new ChangeListLoader(base::MessageLoopProxy::current().get(),
195 drive_service_.get()));
197 // Add a file to the service.
198 scoped_ptr<google_apis::ResourceEntry> gdata_entry = AddNewFile("New File");
199 ASSERT_TRUE(gdata_entry);
201 // Start loading. Because local metadata is available, the load results in
202 // returning FILE_ERROR_OK without fetching full list of resources.
203 const int previous_resource_list_load_count =
204 drive_service_->resource_list_load_count();
205 TestChangeListLoaderObserver observer(change_list_loader_.get());
207 change_list_loader_->LoadIfNeeded(
208 DirectoryFetchInfo(),
209 google_apis::test_util::CreateCopyResultCallback(&error));
210 EXPECT_TRUE(change_list_loader_->IsRefreshing());
211 base::RunLoop().RunUntilIdle();
212 EXPECT_EQ(FILE_ERROR_OK, error);
213 EXPECT_EQ(previous_resource_list_load_count,
214 drive_service_->resource_list_load_count());
215 EXPECT_EQ(1, observer.initial_load_complete_count());
217 // Update should be checked by LoadIfNeeded().
218 EXPECT_EQ(drive_service_->largest_changestamp(),
219 metadata_->GetLargestChangestamp());
220 EXPECT_EQ(1, drive_service_->change_list_load_count());
221 EXPECT_EQ(1, observer.load_from_server_complete_count());
222 EXPECT_EQ(1U, observer.changed_directories().count(
223 util::GetDriveMyDriveRootPath()));
225 base::FilePath file_path =
226 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry->title());
228 EXPECT_EQ(FILE_ERROR_OK,
229 metadata_->GetResourceEntryByPath(file_path, &entry));
232 TEST_F(ChangeListLoaderTest, LoadIfNeeded_MyDrive) {
233 TestChangeListLoaderObserver observer(change_list_loader_.get());
235 // Emulate the slowness of GetAllResourceList().
236 drive_service_->set_never_return_all_resource_list(true);
239 FileError error = FILE_ERROR_FAILED;
240 change_list_loader_->LoadIfNeeded(
241 DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
242 google_apis::test_util::CreateCopyResultCallback(&error));
243 base::RunLoop().RunUntilIdle();
244 EXPECT_EQ(FILE_ERROR_OK, error);
245 EXPECT_EQ(1U, observer.changed_directories().count(
246 util::GetDriveGrandRootPath()));
247 observer.clear_changed_directories();
249 // GetAllResourceList() was called.
250 EXPECT_EQ(1, drive_service_->blocked_resource_list_load_count());
252 // My Drive is present in the local metadata, but its child is not.
254 EXPECT_EQ(FILE_ERROR_OK,
255 metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
257 const int64 mydrive_changestamp =
258 entry.directory_specific_info().changestamp();
260 base::FilePath file_path =
261 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
262 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
263 metadata_->GetResourceEntryByPath(file_path, &entry));
266 change_list_loader_->LoadIfNeeded(
267 DirectoryFetchInfo(drive_service_->GetRootResourceId(),
268 mydrive_changestamp),
269 google_apis::test_util::CreateCopyResultCallback(&error));
270 base::RunLoop().RunUntilIdle();
271 EXPECT_EQ(FILE_ERROR_OK, error);
272 EXPECT_EQ(1U, observer.changed_directories().count(
273 util::GetDriveMyDriveRootPath()));
275 // Now the file is present.
276 EXPECT_EQ(FILE_ERROR_OK,
277 metadata_->GetResourceEntryByPath(file_path, &entry));
280 TEST_F(ChangeListLoaderTest, LoadIfNeeded_NewDirectories) {
281 // Make local metadata up to date.
282 FileError error = FILE_ERROR_FAILED;
283 change_list_loader_->LoadIfNeeded(
284 DirectoryFetchInfo(),
285 google_apis::test_util::CreateCopyResultCallback(&error));
286 base::RunLoop().RunUntilIdle();
287 EXPECT_EQ(FILE_ERROR_OK, error);
290 scoped_ptr<google_apis::ResourceEntry> file = AddNewFile("New File");
293 // Emulate the slowness of GetAllResourceList().
294 drive_service_->set_never_return_all_resource_list(true);
296 // Enter refreshing state.
297 FileError check_for_updates_error = FILE_ERROR_FAILED;
298 change_list_loader_->CheckForUpdates(
299 google_apis::test_util::CreateCopyResultCallback(
300 &check_for_updates_error));
301 EXPECT_TRUE(change_list_loader_->IsRefreshing());
304 TestChangeListLoaderObserver observer(change_list_loader_.get());
305 change_list_loader_->LoadIfNeeded(
306 DirectoryFetchInfo(drive_service_->GetRootResourceId(),
307 metadata_->GetLargestChangestamp()),
308 google_apis::test_util::CreateCopyResultCallback(&error));
309 base::RunLoop().RunUntilIdle();
310 EXPECT_EQ(FILE_ERROR_OK, error);
311 EXPECT_EQ(1U, observer.changed_directories().count(
312 util::GetDriveMyDriveRootPath()));
314 // The new file is present in the local metadata.
315 base::FilePath file_path =
316 util::GetDriveMyDriveRootPath().AppendASCII(file->title());
318 EXPECT_EQ(FILE_ERROR_OK,
319 metadata_->GetResourceEntryByPath(file_path, &entry));
322 TEST_F(ChangeListLoaderTest, LoadIfNeeded_MultipleCalls) {
323 TestChangeListLoaderObserver observer(change_list_loader_.get());
326 FileError error = FILE_ERROR_FAILED;
327 change_list_loader_->LoadIfNeeded(
328 DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
329 google_apis::test_util::CreateCopyResultCallback(&error));
331 // Load grand root again without waiting for the result.
332 FileError error2 = FILE_ERROR_FAILED;
333 change_list_loader_->LoadIfNeeded(
334 DirectoryFetchInfo(util::kDriveGrandRootSpecialResourceId, 0),
335 google_apis::test_util::CreateCopyResultCallback(&error2));
336 base::RunLoop().RunUntilIdle();
338 // Callback is called for each method call.
339 EXPECT_EQ(FILE_ERROR_OK, error);
340 EXPECT_EQ(FILE_ERROR_OK, error2);
342 // No duplicated resource list load and observer events.
343 EXPECT_EQ(1, drive_service_->resource_list_load_count());
344 EXPECT_EQ(1, observer.initial_load_complete_count());
345 EXPECT_EQ(1, observer.load_from_server_complete_count());
348 TEST_F(ChangeListLoaderTest, CheckForUpdates) {
349 // CheckForUpdates() results in no-op before load.
350 FileError check_for_updates_error = FILE_ERROR_FAILED;
351 change_list_loader_->CheckForUpdates(
352 google_apis::test_util::CreateCopyResultCallback(
353 &check_for_updates_error));
354 EXPECT_FALSE(change_list_loader_->IsRefreshing());
355 base::RunLoop().RunUntilIdle();
356 EXPECT_EQ(FILE_ERROR_FAILED,
357 check_for_updates_error); // Callback was not run.
358 EXPECT_EQ(0, metadata_->GetLargestChangestamp());
359 EXPECT_EQ(0, drive_service_->resource_list_load_count());
361 // Start initial load.
362 FileError load_error = FILE_ERROR_FAILED;
363 change_list_loader_->LoadIfNeeded(
364 DirectoryFetchInfo(),
365 google_apis::test_util::CreateCopyResultCallback(&load_error));
366 EXPECT_TRUE(change_list_loader_->IsRefreshing());
368 // CheckForUpdates() while loading.
369 change_list_loader_->CheckForUpdates(
370 google_apis::test_util::CreateCopyResultCallback(
371 &check_for_updates_error));
373 base::RunLoop().RunUntilIdle();
374 EXPECT_FALSE(change_list_loader_->IsRefreshing());
375 EXPECT_EQ(FILE_ERROR_OK, load_error);
376 EXPECT_EQ(FILE_ERROR_OK, check_for_updates_error);
377 EXPECT_LT(0, metadata_->GetLargestChangestamp());
378 EXPECT_EQ(1, drive_service_->resource_list_load_count());
380 int64 previous_changestamp = metadata_->GetLargestChangestamp();
381 // CheckForUpdates() results in no update.
382 change_list_loader_->CheckForUpdates(
383 google_apis::test_util::CreateCopyResultCallback(
384 &check_for_updates_error));
385 EXPECT_TRUE(change_list_loader_->IsRefreshing());
386 base::RunLoop().RunUntilIdle();
387 EXPECT_FALSE(change_list_loader_->IsRefreshing());
388 EXPECT_EQ(previous_changestamp, metadata_->GetLargestChangestamp());
390 // Add a file to the service.
391 scoped_ptr<google_apis::ResourceEntry> gdata_entry = AddNewFile("New File");
392 ASSERT_TRUE(gdata_entry);
394 // CheckForUpdates() results in update.
395 TestChangeListLoaderObserver observer(change_list_loader_.get());
396 change_list_loader_->CheckForUpdates(
397 google_apis::test_util::CreateCopyResultCallback(
398 &check_for_updates_error));
399 EXPECT_TRUE(change_list_loader_->IsRefreshing());
400 base::RunLoop().RunUntilIdle();
401 EXPECT_FALSE(change_list_loader_->IsRefreshing());
402 EXPECT_LT(previous_changestamp, metadata_->GetLargestChangestamp());
403 EXPECT_EQ(1, observer.load_from_server_complete_count());
404 EXPECT_EQ(1U, observer.changed_directories().count(
405 util::GetDriveMyDriveRootPath()));
407 // The new file is found in the local metadata.
408 base::FilePath new_file_path =
409 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry->title());
411 EXPECT_EQ(FILE_ERROR_OK,
412 metadata_->GetResourceEntryByPath(new_file_path, &entry));
415 } // namespace internal