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/file_cache.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/chromeos/drive/job_scheduler.h"
15 #include "chrome/browser/chromeos/drive/resource_metadata.h"
16 #include "chrome/browser/chromeos/drive/test_util.h"
17 #include "chrome/browser/drive/fake_drive_service.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "google_apis/drive/test_util.h"
20 #include "testing/gtest/include/gtest/gtest.h"
25 class TestChangeListLoaderObserver
: public ChangeListLoaderObserver
{
27 explicit TestChangeListLoaderObserver(ChangeListLoader
* loader
)
29 load_from_server_complete_count_(0),
30 initial_load_complete_count_(0) {
31 loader_
->AddObserver(this);
34 virtual ~TestChangeListLoaderObserver() {
35 loader_
->RemoveObserver(this);
38 const std::set
<base::FilePath
>& changed_directories() const {
39 return changed_directories_
;
41 void clear_changed_directories() { changed_directories_
.clear(); }
43 int load_from_server_complete_count() const {
44 return load_from_server_complete_count_
;
46 int initial_load_complete_count() const {
47 return initial_load_complete_count_
;
50 // ChageListObserver overrides:
51 virtual void OnDirectoryChanged(
52 const base::FilePath
& directory_path
) OVERRIDE
{
53 changed_directories_
.insert(directory_path
);
55 virtual void OnLoadFromServerComplete() OVERRIDE
{
56 ++load_from_server_complete_count_
;
58 virtual void OnInitialLoadComplete() OVERRIDE
{
59 ++initial_load_complete_count_
;
63 ChangeListLoader
* loader_
;
64 std::set
<base::FilePath
> changed_directories_
;
65 int load_from_server_complete_count_
;
66 int initial_load_complete_count_
;
68 DISALLOW_COPY_AND_ASSIGN(TestChangeListLoaderObserver
);
71 class ChangeListLoaderTest
: public testing::Test
{
73 virtual void SetUp() OVERRIDE
{
74 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
75 pref_service_
.reset(new TestingPrefServiceSimple
);
76 test_util::RegisterDrivePrefs(pref_service_
->registry());
78 drive_service_
.reset(new FakeDriveService
);
79 ASSERT_TRUE(drive_service_
->LoadResourceListForWapi(
80 "gdata/root_feed.json"));
81 ASSERT_TRUE(drive_service_
->LoadAccountMetadataForWapi(
82 "gdata/account_metadata.json"));
84 scheduler_
.reset(new JobScheduler(pref_service_
.get(),
86 base::MessageLoopProxy::current().get()));
87 metadata_storage_
.reset(new ResourceMetadataStorage(
88 temp_dir_
.path(), base::MessageLoopProxy::current().get()));
89 ASSERT_TRUE(metadata_storage_
->Initialize());
91 metadata_
.reset(new ResourceMetadata(
92 metadata_storage_
.get(), base::MessageLoopProxy::current().get()));
93 ASSERT_EQ(FILE_ERROR_OK
, metadata_
->Initialize());
95 cache_
.reset(new FileCache(metadata_storage_
.get(),
97 base::MessageLoopProxy::current().get(),
98 NULL
/* free_disk_space_getter */));
99 ASSERT_TRUE(cache_
->Initialize());
101 change_list_loader_
.reset(
102 new ChangeListLoader(base::MessageLoopProxy::current().get(),
105 drive_service_
.get()));
108 // Adds a new file to the root directory of the service.
109 scoped_ptr
<google_apis::ResourceEntry
> AddNewFile(const std::string
& title
) {
110 google_apis::GDataErrorCode error
= google_apis::GDATA_FILE_ERROR
;
111 scoped_ptr
<google_apis::ResourceEntry
> entry
;
112 drive_service_
->AddNewFile(
115 drive_service_
->GetRootResourceId(),
117 false, // shared_with_me
118 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
119 base::RunLoop().RunUntilIdle();
120 EXPECT_EQ(google_apis::HTTP_CREATED
, error
);
124 content::TestBrowserThreadBundle thread_bundle_
;
125 base::ScopedTempDir temp_dir_
;
126 scoped_ptr
<TestingPrefServiceSimple
> pref_service_
;
127 scoped_ptr
<FakeDriveService
> drive_service_
;
128 scoped_ptr
<JobScheduler
> scheduler_
;
129 scoped_ptr
<ResourceMetadataStorage
,
130 test_util::DestroyHelperForTests
> metadata_storage_
;
131 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
> metadata_
;
132 scoped_ptr
<FileCache
, test_util::DestroyHelperForTests
> cache_
;
133 scoped_ptr
<ChangeListLoader
> change_list_loader_
;
136 TEST_F(ChangeListLoaderTest
, Load
) {
137 EXPECT_FALSE(change_list_loader_
->IsRefreshing());
139 // Start initial load.
140 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
142 EXPECT_EQ(0, drive_service_
->about_resource_load_count());
144 FileError error
= FILE_ERROR_FAILED
;
145 change_list_loader_
->LoadForTesting(
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, drive_service_
->about_resource_load_count());
155 EXPECT_EQ(1, observer
.initial_load_complete_count());
156 EXPECT_EQ(1, observer
.load_from_server_complete_count());
157 EXPECT_TRUE(observer
.changed_directories().empty());
159 base::FilePath file_path
=
160 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
162 EXPECT_EQ(FILE_ERROR_OK
,
163 metadata_
->GetResourceEntryByPath(file_path
, &entry
));
165 // Reload. This should result in no-op.
166 int64 previous_changestamp
= metadata_
->GetLargestChangestamp();
167 int previous_resource_list_load_count
=
168 drive_service_
->resource_list_load_count();
169 change_list_loader_
->LoadForTesting(
170 google_apis::test_util::CreateCopyResultCallback(&error
));
171 base::RunLoop().RunUntilIdle();
172 EXPECT_EQ(FILE_ERROR_OK
, error
);
174 EXPECT_FALSE(change_list_loader_
->IsRefreshing());
175 // Cached value is used.
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
, Load_LocalMetadataAvailable
) {
183 FileError error
= FILE_ERROR_FAILED
;
184 change_list_loader_
->LoadForTesting(
185 google_apis::test_util::CreateCopyResultCallback(&error
));
186 base::RunLoop().RunUntilIdle();
187 EXPECT_EQ(FILE_ERROR_OK
, error
);
190 change_list_loader_
.reset(
191 new ChangeListLoader(base::MessageLoopProxy::current().get(),
194 drive_service_
.get()));
196 // Add a file to the service.
197 scoped_ptr
<google_apis::ResourceEntry
> gdata_entry
= AddNewFile("New File");
198 ASSERT_TRUE(gdata_entry
);
200 // Start loading. Because local metadata is available, the load results in
201 // returning FILE_ERROR_OK without fetching full list of resources.
202 const int previous_resource_list_load_count
=
203 drive_service_
->resource_list_load_count();
204 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
206 change_list_loader_
->LoadForTesting(
207 google_apis::test_util::CreateCopyResultCallback(&error
));
208 EXPECT_TRUE(change_list_loader_
->IsRefreshing());
209 base::RunLoop().RunUntilIdle();
210 EXPECT_EQ(FILE_ERROR_OK
, error
);
211 EXPECT_EQ(previous_resource_list_load_count
,
212 drive_service_
->resource_list_load_count());
213 EXPECT_EQ(1, observer
.initial_load_complete_count());
215 // Update should be checked by Load().
216 EXPECT_EQ(drive_service_
->largest_changestamp(),
217 metadata_
->GetLargestChangestamp());
218 EXPECT_EQ(1, drive_service_
->change_list_load_count());
219 EXPECT_EQ(1, observer
.load_from_server_complete_count());
220 EXPECT_EQ(1U, observer
.changed_directories().count(
221 util::GetDriveMyDriveRootPath()));
223 base::FilePath file_path
=
224 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry
->title());
226 EXPECT_EQ(FILE_ERROR_OK
,
227 metadata_
->GetResourceEntryByPath(file_path
, &entry
));
230 TEST_F(ChangeListLoaderTest
, LoadDirectoryIfNeeded_GrandRoot
) {
231 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
233 // Emulate the slowness of GetAllResourceList().
234 drive_service_
->set_never_return_all_resource_list(true);
237 FileError error
= FILE_ERROR_FAILED
;
238 change_list_loader_
->LoadDirectoryIfNeeded(
239 util::GetDriveGrandRootPath(),
240 google_apis::test_util::CreateCopyResultCallback(&error
));
241 base::RunLoop().RunUntilIdle();
242 EXPECT_EQ(FILE_ERROR_OK
, error
);
243 EXPECT_EQ(0U, observer
.changed_directories().size());
244 observer
.clear_changed_directories();
246 // GetAllResourceList() was called.
247 EXPECT_EQ(1, drive_service_
->blocked_resource_list_load_count());
249 // My Drive has resource ID.
251 EXPECT_EQ(FILE_ERROR_OK
,
252 metadata_
->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
254 EXPECT_EQ(drive_service_
->GetRootResourceId(), entry
.resource_id());
257 TEST_F(ChangeListLoaderTest
, LoadDirectoryIfNeeded_MyDrive
) {
258 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
260 // My Drive does not have resource ID yet.
262 EXPECT_EQ(FILE_ERROR_OK
,
263 metadata_
->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
265 EXPECT_TRUE(entry
.resource_id().empty());
267 // Emulate the slowness of GetAllResourceList().
268 drive_service_
->set_never_return_all_resource_list(true);
271 FileError error
= FILE_ERROR_FAILED
;
272 change_list_loader_
->LoadDirectoryIfNeeded(
273 util::GetDriveMyDriveRootPath(),
274 google_apis::test_util::CreateCopyResultCallback(&error
));
275 base::RunLoop().RunUntilIdle();
276 EXPECT_EQ(FILE_ERROR_OK
, error
);
277 EXPECT_EQ(1U, observer
.changed_directories().count(
278 util::GetDriveMyDriveRootPath()));
280 // GetAllResourceList() was called.
281 EXPECT_EQ(1, drive_service_
->blocked_resource_list_load_count());
283 // My Drive has resource ID.
284 EXPECT_EQ(FILE_ERROR_OK
,
285 metadata_
->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
287 EXPECT_EQ(drive_service_
->GetRootResourceId(), entry
.resource_id());
289 // My Drive's child is present.
290 base::FilePath file_path
=
291 util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
292 EXPECT_EQ(FILE_ERROR_OK
,
293 metadata_
->GetResourceEntryByPath(file_path
, &entry
));
296 TEST_F(ChangeListLoaderTest
, LoadDirectoryIfNeeded_NewDirectories
) {
297 // Make local metadata up to date.
298 FileError error
= FILE_ERROR_FAILED
;
299 change_list_loader_
->LoadForTesting(
300 google_apis::test_util::CreateCopyResultCallback(&error
));
301 base::RunLoop().RunUntilIdle();
302 EXPECT_EQ(FILE_ERROR_OK
, error
);
305 scoped_ptr
<google_apis::ResourceEntry
> file
= AddNewFile("New File");
308 // Emulate the slowness of GetAllResourceList().
309 drive_service_
->set_never_return_all_resource_list(true);
311 // Enter refreshing state.
312 FileError check_for_updates_error
= FILE_ERROR_FAILED
;
313 change_list_loader_
->CheckForUpdates(
314 google_apis::test_util::CreateCopyResultCallback(
315 &check_for_updates_error
));
316 EXPECT_TRUE(change_list_loader_
->IsRefreshing());
319 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
320 change_list_loader_
->LoadDirectoryIfNeeded(
321 util::GetDriveMyDriveRootPath(),
322 google_apis::test_util::CreateCopyResultCallback(&error
));
323 base::RunLoop().RunUntilIdle();
324 EXPECT_EQ(FILE_ERROR_OK
, error
);
325 EXPECT_EQ(1U, observer
.changed_directories().count(
326 util::GetDriveMyDriveRootPath()));
328 // The new file is present in the local metadata.
329 base::FilePath file_path
=
330 util::GetDriveMyDriveRootPath().AppendASCII(file
->title());
332 EXPECT_EQ(FILE_ERROR_OK
,
333 metadata_
->GetResourceEntryByPath(file_path
, &entry
));
336 TEST_F(ChangeListLoaderTest
, LoadDirectoryIfNeeded_MultipleCalls
) {
337 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
340 FileError error
= FILE_ERROR_FAILED
;
341 change_list_loader_
->LoadDirectoryIfNeeded(
342 util::GetDriveGrandRootPath(),
343 google_apis::test_util::CreateCopyResultCallback(&error
));
345 // Load grand root again without waiting for the result.
346 FileError error2
= FILE_ERROR_FAILED
;
347 change_list_loader_
->LoadDirectoryIfNeeded(
348 util::GetDriveGrandRootPath(),
349 google_apis::test_util::CreateCopyResultCallback(&error2
));
350 base::RunLoop().RunUntilIdle();
352 // Callback is called for each method call.
353 EXPECT_EQ(FILE_ERROR_OK
, error
);
354 EXPECT_EQ(FILE_ERROR_OK
, error2
);
356 // No duplicated resource list load and observer events.
357 EXPECT_EQ(1, drive_service_
->resource_list_load_count());
358 EXPECT_EQ(1, observer
.initial_load_complete_count());
359 EXPECT_EQ(1, observer
.load_from_server_complete_count());
362 TEST_F(ChangeListLoaderTest
, CheckForUpdates
) {
363 // CheckForUpdates() results in no-op before load.
364 FileError check_for_updates_error
= FILE_ERROR_FAILED
;
365 change_list_loader_
->CheckForUpdates(
366 google_apis::test_util::CreateCopyResultCallback(
367 &check_for_updates_error
));
368 EXPECT_FALSE(change_list_loader_
->IsRefreshing());
369 base::RunLoop().RunUntilIdle();
370 EXPECT_EQ(FILE_ERROR_FAILED
,
371 check_for_updates_error
); // Callback was not run.
372 EXPECT_EQ(0, metadata_
->GetLargestChangestamp());
373 EXPECT_EQ(0, drive_service_
->resource_list_load_count());
374 EXPECT_EQ(0, drive_service_
->about_resource_load_count());
376 // Start initial load.
377 FileError load_error
= FILE_ERROR_FAILED
;
378 change_list_loader_
->LoadForTesting(
379 google_apis::test_util::CreateCopyResultCallback(&load_error
));
380 EXPECT_TRUE(change_list_loader_
->IsRefreshing());
382 // CheckForUpdates() while loading.
383 change_list_loader_
->CheckForUpdates(
384 google_apis::test_util::CreateCopyResultCallback(
385 &check_for_updates_error
));
387 base::RunLoop().RunUntilIdle();
388 EXPECT_FALSE(change_list_loader_
->IsRefreshing());
389 EXPECT_EQ(FILE_ERROR_OK
, load_error
);
390 EXPECT_EQ(FILE_ERROR_OK
, check_for_updates_error
);
391 EXPECT_LT(0, metadata_
->GetLargestChangestamp());
392 EXPECT_EQ(1, drive_service_
->resource_list_load_count());
394 int64 previous_changestamp
= metadata_
->GetLargestChangestamp();
395 // CheckForUpdates() results in no update.
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_EQ(previous_changestamp
, metadata_
->GetLargestChangestamp());
404 // Add a file to the service.
405 scoped_ptr
<google_apis::ResourceEntry
> gdata_entry
= AddNewFile("New File");
406 ASSERT_TRUE(gdata_entry
);
408 // CheckForUpdates() results in update.
409 TestChangeListLoaderObserver
observer(change_list_loader_
.get());
410 change_list_loader_
->CheckForUpdates(
411 google_apis::test_util::CreateCopyResultCallback(
412 &check_for_updates_error
));
413 EXPECT_TRUE(change_list_loader_
->IsRefreshing());
414 base::RunLoop().RunUntilIdle();
415 EXPECT_FALSE(change_list_loader_
->IsRefreshing());
416 EXPECT_LT(previous_changestamp
, metadata_
->GetLargestChangestamp());
417 EXPECT_EQ(1, observer
.load_from_server_complete_count());
418 EXPECT_EQ(1U, observer
.changed_directories().count(
419 util::GetDriveMyDriveRootPath()));
421 // The new file is found in the local metadata.
422 base::FilePath new_file_path
=
423 util::GetDriveMyDriveRootPath().AppendASCII(gdata_entry
->title());
425 EXPECT_EQ(FILE_ERROR_OK
,
426 metadata_
->GetResourceEntryByPath(new_file_path
, &entry
));
429 } // namespace internal