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.
7 #include "base/file_util.h"
8 #include "base/files/file_enumerator.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "build/build_config.h"
15 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
16 #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h"
17 #include "chrome/common/media_galleries/picasa_test_util.h"
18 #include "chrome/common/media_galleries/picasa_types.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "content/public/test/test_browser_thread.h"
26 void VerifyTestAlbumTable(PicasaDataProvider
* data_provider
,
27 base::FilePath test_folder_1_path
,
28 base::FilePath test_folder_2_path
) {
29 scoped_ptr
<AlbumMap
> folders
= data_provider
->GetFolders();
30 ASSERT_TRUE(folders
.get());
31 EXPECT_EQ(2u, folders
->size());
33 AlbumMap::const_iterator folder_1
= folders
->find(
34 test_folder_1_path
.BaseName().AsUTF8Unsafe() + " 1899-12-30");
35 EXPECT_NE(folders
->end(), folder_1
);
36 EXPECT_EQ(test_folder_1_path
.BaseName().AsUTF8Unsafe(),
37 folder_1
->second
.name
);
38 EXPECT_EQ(test_folder_1_path
, folder_1
->second
.path
);
39 EXPECT_EQ("uid1", folder_1
->second
.uid
);
41 AlbumMap::const_iterator folder_2
= folders
->find(
42 test_folder_2_path
.BaseName().AsUTF8Unsafe() + " 1899-12-30");
43 EXPECT_NE(folders
->end(), folder_2
);
44 EXPECT_EQ(test_folder_2_path
.BaseName().AsUTF8Unsafe(),
45 folder_2
->second
.name
);
46 EXPECT_EQ(test_folder_2_path
, folder_2
->second
.path
);
47 EXPECT_EQ("uid4", folder_2
->second
.uid
);
49 scoped_ptr
<AlbumMap
> albums
= data_provider
->GetAlbums();
50 ASSERT_TRUE(albums
.get());
51 EXPECT_EQ(2u, albums
->size());
53 AlbumMap::const_iterator album_1
= albums
->find("Album 1 Name 1899-12-30");
54 EXPECT_NE(albums
->end(), album_1
);
55 EXPECT_EQ("Album 1 Name", album_1
->second
.name
);
56 EXPECT_EQ(base::FilePath(), album_1
->second
.path
);
57 EXPECT_EQ("uid3", album_1
->second
.uid
);
59 AlbumMap::const_iterator album_2
= albums
->find("Album 2 Name 1899-12-30");
60 EXPECT_NE(albums
->end(), album_2
);
61 EXPECT_EQ("Album 2 Name", album_2
->second
.name
);
62 EXPECT_EQ(base::FilePath(), album_2
->second
.path
);
63 EXPECT_EQ("uid5", album_2
->second
.uid
);
66 void VerifyTestAlbumsImagesIndex(PicasaDataProvider
* data_provider
,
67 base::FilePath test_folder_1_path
,
68 base::FilePath test_folder_2_path
) {
69 base::PlatformFileError error
;
70 scoped_ptr
<AlbumImages
> album_1_images
=
71 data_provider
->FindAlbumImages("uid3", &error
);
72 ASSERT_TRUE(album_1_images
);
73 EXPECT_EQ(base::PLATFORM_FILE_OK
, error
);
74 EXPECT_EQ(2u, album_1_images
->size());
75 EXPECT_NE(album_1_images
->end(), album_1_images
->find("InBoth.jpg"));
76 EXPECT_EQ(test_folder_1_path
.AppendASCII("InBoth.jpg"),
77 (*album_1_images
)["InBoth.jpg"]);
78 EXPECT_NE(album_1_images
->end(),
79 album_1_images
->find("InFirstAlbumOnly.jpg"));
80 EXPECT_EQ(test_folder_2_path
.AppendASCII("InFirstAlbumOnly.jpg"),
81 (*album_1_images
)["InFirstAlbumOnly.jpg"]);
83 scoped_ptr
<AlbumImages
> album_2_images
=
84 data_provider
->FindAlbumImages("uid5", &error
);
85 ASSERT_TRUE(album_2_images
);
86 EXPECT_EQ(base::PLATFORM_FILE_OK
, error
);
87 EXPECT_EQ(2u, album_2_images
->size());
88 EXPECT_NE(album_2_images
->end(), album_2_images
->find("InBoth.jpg"));
89 EXPECT_EQ(test_folder_1_path
.AppendASCII("InBoth.jpg"),
90 (*album_2_images
)["InBoth.jpg"]);
91 EXPECT_NE(album_2_images
->end(),
92 album_2_images
->find("InSecondAlbumOnly.jpg"));
93 EXPECT_EQ(test_folder_1_path
.AppendASCII("InSecondAlbumOnly.jpg"),
94 (*album_2_images
)["InSecondAlbumOnly.jpg"]);
99 class TestPicasaDataProvider
: public PicasaDataProvider
{
101 explicit TestPicasaDataProvider(const base::FilePath
& database_path
)
102 : PicasaDataProvider(database_path
),
103 file_watch_request_returned_(false) {
106 virtual ~TestPicasaDataProvider() {}
108 // |ready_callback| called with true if and when the file watch is started
109 // successfully. If the file watch fails, it's called with false.
110 void EnsureFileWatchStartedForTesting(const ReadyCallback
& ready_callback
) {
111 if (!file_watch_request_returned_
) {
112 file_watch_started_callbacks_
.push_back(ready_callback
);
115 ready_callback
.Run(temp_dir_watcher_
.get() != NULL
);
118 // Simulates the actual writing process of moving all the database files
119 // from the temporary directory to the database directory in a loop.
120 void MoveTempFilesToDatabase() {
121 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
123 base::FileEnumerator
file_enumerator(
124 database_path_
.DirName().AppendASCII(kPicasaTempDirName
),
125 false /* recursive */,
126 base::FileEnumerator::FILES
);
128 for (base::FilePath src_path
= file_enumerator
.Next(); !src_path
.empty();
129 src_path
= file_enumerator
.Next()) {
131 base::Move(src_path
, database_path_
.Append(src_path
.BaseName())));
135 void SetInvalidateCallback(const base::Closure
& callback
) {
136 DCHECK(invalidate_callback_
.is_null());
137 invalidate_callback_
= callback
;
140 virtual void InvalidateData() OVERRIDE
{
141 PicasaDataProvider::InvalidateData();
143 if (!invalidate_callback_
.is_null()) {
144 invalidate_callback_
.Run();
145 invalidate_callback_
.Reset();
149 void SetAlbumMapsForTesting(const AlbumMap
& album_map
,
150 const AlbumMap
& folder_map
) {
151 album_map_
= album_map
;
152 folder_map_
= folder_map
;
156 virtual void OnTempDirWatchStarted(
157 scoped_ptr
<base::FilePathWatcher
> temp_dir_watcher
) OVERRIDE
{
158 PicasaDataProvider::OnTempDirWatchStarted(temp_dir_watcher
.Pass());
160 file_watch_request_returned_
= true;
161 for (std::vector
<ReadyCallback
>::const_iterator it
=
162 file_watch_started_callbacks_
.begin();
163 it
!= file_watch_started_callbacks_
.end();
165 it
->Run(temp_dir_watcher_
.get() != NULL
);
167 file_watch_started_callbacks_
.clear();
170 // Used for test that utilizes file watch
171 bool file_watch_request_returned_
;
172 std::vector
<ReadyCallback
> file_watch_started_callbacks_
;
174 base::Closure invalidate_callback_
;
177 class PicasaDataProviderTest
: public InProcessBrowserTest
{
179 PicasaDataProviderTest() {}
180 virtual ~PicasaDataProviderTest() {}
183 // Runs on the MediaTaskRunner and designed to be overridden by subclasses.
184 virtual void InitializeTestData() {}
187 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
189 quit_closure_
= loop
.QuitClosure();
190 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
192 base::Bind(&PicasaDataProviderTest::SetupFoldersAndDataProvider
,
193 base::Unretained(this)));
194 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
196 base::Bind(&PicasaDataProviderTest::InitializeTestData
,
197 base::Unretained(this)));
198 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
200 base::Bind(&PicasaDataProviderTest::StartTestOnMediaTaskRunner
,
201 base::Unretained(this)));
205 virtual PicasaDataProvider::DataType
RequestedDataType() const = 0;
207 // Start the test. The data provider is refreshed before calling StartTest
208 // and the result of the refresh is passed in.
209 virtual void VerifyRefreshResults(bool parse_success
) {};
212 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
214 // The data provider must be destructed on the MediaTaskRunner. This is done
215 // in a posted task rather than directly because TestDone is called by
216 // PicasaDataProvider. The callee should not destroy the caller.
217 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
219 base::Bind(&PicasaDataProviderTest::DestructDataProviderThenQuit
,
220 base::Unretained(this)));
223 const base::FilePath
& test_folder_1_path() { return test_folder_1_
.path(); }
224 const base::FilePath
& test_folder_2_path() { return test_folder_2_
.path(); }
226 TestPicasaDataProvider
* data_provider() const {
227 return picasa_data_provider_
.get();
230 const base::FilePath
GetTempDirPath() const {
231 return picasa_root_dir_
.path().AppendASCII(kPicasaTempDirName
);
234 virtual base::FilePath
GetColumnFileDestination() const {
235 return picasa_root_dir_
.path().AppendASCII(kPicasaDatabaseDirName
);
239 void SetupFoldersAndDataProvider() {
240 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
241 ASSERT_TRUE(test_folder_1_
.CreateUniqueTempDir());
242 ASSERT_TRUE(test_folder_2_
.CreateUniqueTempDir());
243 ASSERT_TRUE(picasa_root_dir_
.CreateUniqueTempDir());
244 ASSERT_TRUE(base::CreateDirectory(
245 picasa_root_dir_
.path().AppendASCII(kPicasaDatabaseDirName
)));
246 ASSERT_TRUE(base::CreateDirectory(
247 picasa_root_dir_
.path().AppendASCII(kPicasaTempDirName
)));
249 picasa_data_provider_
.reset(new TestPicasaDataProvider(
250 picasa_root_dir_
.path().AppendASCII(kPicasaDatabaseDirName
)));
253 virtual void StartTestOnMediaTaskRunner() {
254 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
256 data_provider()->RefreshData(
258 base::Bind(&PicasaDataProviderTest::VerifyRefreshResults
,
259 base::Unretained(this)));
262 void DestructDataProviderThenQuit() {
263 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
264 picasa_data_provider_
.reset();
265 content::BrowserThread::PostTask(
266 content::BrowserThread::UI
, FROM_HERE
, quit_closure_
);
269 base::ScopedTempDir test_folder_1_
;
270 base::ScopedTempDir test_folder_2_
;
271 base::ScopedTempDir picasa_root_dir_
;
273 scoped_ptr
<TestPicasaDataProvider
> picasa_data_provider_
;
275 base::Closure quit_closure_
;
277 DISALLOW_COPY_AND_ASSIGN(PicasaDataProviderTest
);
280 class PicasaDataProviderNoDatabaseGetListTest
: public PicasaDataProviderTest
{
282 virtual PicasaDataProvider::DataType
RequestedDataType() const OVERRIDE
{
283 return PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
;
285 virtual void VerifyRefreshResults(bool parse_success
) OVERRIDE
{
286 EXPECT_FALSE(parse_success
);
291 IN_PROC_BROWSER_TEST_F(PicasaDataProviderNoDatabaseGetListTest
,
296 class PicasaDataProviderNoDatabaseGetAlbumsImagesTest
297 : public PicasaDataProviderTest
{
299 virtual PicasaDataProvider::DataType
RequestedDataType() const OVERRIDE
{
300 return PicasaDataProvider::ALBUMS_IMAGES_DATA
;
302 virtual void VerifyRefreshResults(bool parse_success
) OVERRIDE
{
303 EXPECT_FALSE(parse_success
);
308 IN_PROC_BROWSER_TEST_F(PicasaDataProviderNoDatabaseGetAlbumsImagesTest
,
309 NoDatabaseGetAlbumsImages
) {
313 class PicasaDataProviderGetListTest
: public PicasaDataProviderTest
{
315 virtual void InitializeTestData() OVERRIDE
{
316 WriteTestAlbumTable(GetColumnFileDestination(), test_folder_1_path(),
317 test_folder_2_path());
320 virtual PicasaDataProvider::DataType
RequestedDataType() const OVERRIDE
{
321 return PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
;
324 virtual void VerifyRefreshResults(bool parse_success
) OVERRIDE
{
325 ASSERT_TRUE(parse_success
);
326 VerifyTestAlbumTable(
327 data_provider(), test_folder_1_path(), test_folder_2_path());
332 IN_PROC_BROWSER_TEST_F(PicasaDataProviderGetListTest
, GetListTest
) {
336 class PicasaDataProviderGetAlbumsImagesTest
: public PicasaDataProviderTest
{
338 virtual void InitializeTestData() OVERRIDE
{
339 WriteTestAlbumTable(GetColumnFileDestination(), test_folder_1_path(),
340 test_folder_2_path());
341 WriteTestAlbumsImagesIndex(test_folder_1_path(), test_folder_2_path());
344 virtual PicasaDataProvider::DataType
RequestedDataType() const OVERRIDE
{
345 return PicasaDataProvider::ALBUMS_IMAGES_DATA
;
348 virtual void VerifyRefreshResults(bool parse_success
) OVERRIDE
{
349 ASSERT_TRUE(parse_success
);
350 VerifyTestAlbumTable(
351 data_provider(), test_folder_1_path(), test_folder_2_path());
352 VerifyTestAlbumsImagesIndex(
353 data_provider(), test_folder_1_path(), test_folder_2_path());
358 IN_PROC_BROWSER_TEST_F(PicasaDataProviderGetAlbumsImagesTest
,
359 GetAlbumsImagesTest
) {
363 class PicasaDataProviderMultipleMixedCallbacksTest
364 : public PicasaDataProviderTest
{
366 PicasaDataProviderMultipleMixedCallbacksTest()
367 : list_callbacks_called_(0), albums_images_callbacks_called_(0) {}
369 virtual void InitializeTestData() OVERRIDE
{
370 WriteTestAlbumTable(GetColumnFileDestination(), test_folder_1_path(),
371 test_folder_2_path());
372 WriteTestAlbumsImagesIndex(test_folder_1_path(), test_folder_2_path());
375 virtual PicasaDataProvider::DataType
RequestedDataType() const OVERRIDE
{
376 return PicasaDataProvider::ALBUMS_IMAGES_DATA
;
380 virtual void ListCallback(int expected_list_callbacks_called
,
381 bool parse_success
) {
382 ASSERT_TRUE(parse_success
);
383 ASSERT_EQ(expected_list_callbacks_called
, ++list_callbacks_called_
);
384 VerifyTestAlbumTable(
385 data_provider(), test_folder_1_path(), test_folder_2_path());
389 virtual void AlbumsImagesCallback(int expected_albums_images_callbacks_called
,
390 bool parse_success
) {
391 ASSERT_TRUE(parse_success
);
392 ASSERT_EQ(expected_albums_images_callbacks_called
,
393 ++albums_images_callbacks_called_
);
394 VerifyTestAlbumsImagesIndex(
395 data_provider(), test_folder_1_path(), test_folder_2_path());
400 void CheckTestDone() {
401 ASSERT_LE(list_callbacks_called_
, 2);
402 ASSERT_LE(albums_images_callbacks_called_
, 2);
403 if (list_callbacks_called_
== 2 && albums_images_callbacks_called_
== 2)
407 virtual void StartTestOnMediaTaskRunner() OVERRIDE
{
408 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
410 data_provider()->RefreshData(
411 PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
,
412 base::Bind(&PicasaDataProviderMultipleMixedCallbacksTest::ListCallback
,
413 base::Unretained(this),
415 data_provider()->RefreshData(
416 PicasaDataProvider::ALBUMS_IMAGES_DATA
,
418 &PicasaDataProviderMultipleMixedCallbacksTest::AlbumsImagesCallback
,
419 base::Unretained(this),
421 data_provider()->RefreshData(
422 PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
,
423 base::Bind(&PicasaDataProviderMultipleMixedCallbacksTest::ListCallback
,
424 base::Unretained(this),
426 data_provider()->RefreshData(
427 PicasaDataProvider::ALBUMS_IMAGES_DATA
,
429 &PicasaDataProviderMultipleMixedCallbacksTest::AlbumsImagesCallback
,
430 base::Unretained(this),
434 int list_callbacks_called_
;
435 int albums_images_callbacks_called_
;
438 IN_PROC_BROWSER_TEST_F(PicasaDataProviderMultipleMixedCallbacksTest
,
439 MultipleMixedCallbacks
) {
443 class PicasaDataProviderFileWatcherInvalidateTest
444 : public PicasaDataProviderGetListTest
{
446 virtual void ListCallback(bool parse_success
) {
447 ASSERT_FALSE(parse_success
);
448 data_provider()->EnsureFileWatchStartedForTesting(
449 base::Bind(&PicasaDataProviderFileWatcherInvalidateTest::
450 OnPicasaTempDirWatchStarted
,
451 base::Unretained(this)));
454 void OnPicasaTempDirWatchStarted(bool file_watch_successful
) {
455 ASSERT_TRUE(file_watch_successful
);
457 // Validate the list after the file move triggers an invalidate.
458 data_provider()->SetInvalidateCallback(base::Bind(
459 &PicasaDataProvider::RefreshData
,
460 base::Unretained(data_provider()),
463 &PicasaDataProviderFileWatcherInvalidateTest::VerifyRefreshResults
,
464 base::Unretained(this))));
466 data_provider()->MoveTempFilesToDatabase();
469 virtual base::FilePath
GetColumnFileDestination() const OVERRIDE
{
470 return GetTempDirPath();
474 virtual void StartTestOnMediaTaskRunner() OVERRIDE
{
475 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
477 // Refresh before moving album table to database dir, guaranteeing failure.
478 data_provider()->RefreshData(
481 &PicasaDataProviderFileWatcherInvalidateTest::ListCallback
,
482 base::Unretained(this)));
486 IN_PROC_BROWSER_TEST_F(PicasaDataProviderFileWatcherInvalidateTest
,
487 FileWatcherInvalidateTest
) {
491 class PicasaDataProviderInvalidateInflightTableReaderTest
492 : public PicasaDataProviderGetListTest
{
494 // Don't write the database files until later.
495 virtual void InitializeTestData() OVERRIDE
{}
498 virtual void StartTestOnMediaTaskRunner() OVERRIDE
{
499 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
501 // Refresh before the database files have been written.
502 // This is guaranteed to fail to read the album table.
503 data_provider()->RefreshData(
505 base::Bind(&PicasaDataProviderInvalidateInflightTableReaderTest::
506 VerifyRefreshResults
,
507 base::Unretained(this)));
509 // Now write the album table and invalidate the inflight table reader.
510 PicasaDataProviderGetListTest::InitializeTestData();
511 data_provider()->InvalidateData();
513 // VerifyRefreshResults callback should receive correct results now.
517 IN_PROC_BROWSER_TEST_F(PicasaDataProviderInvalidateInflightTableReaderTest
,
518 InvalidateInflightTableReaderTest
) {
522 class PicasaDataProviderInvalidateInflightAlbumsIndexerTest
523 : public PicasaDataProviderGetAlbumsImagesTest
{
525 virtual void ListCallback(bool parse_success
) {
526 ASSERT_TRUE(parse_success
);
528 // Empty the album maps to guarantee that the first utility process will
529 // fail to get the correct albums-images index.
530 data_provider()->SetAlbumMapsForTesting(AlbumMap(), AlbumMap());
531 data_provider()->RefreshData(
532 PicasaDataProvider::ALBUMS_IMAGES_DATA
,
533 base::Bind(&PicasaDataProviderInvalidateInflightAlbumsIndexerTest::
534 VerifyRefreshResults
,
535 base::Unretained(this)));
537 // Now invalidate all the data. The album maps will be re-read.
538 data_provider()->InvalidateData();
540 // VerifyRefreshResults callback should receive correct results now.
544 virtual void StartTestOnMediaTaskRunner() OVERRIDE
{
545 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
547 data_provider()->RefreshData(
548 PicasaDataProvider::LIST_OF_ALBUMS_AND_FOLDERS_DATA
,
549 base::Bind(&PicasaDataProviderInvalidateInflightAlbumsIndexerTest::
551 base::Unretained(this)));
555 IN_PROC_BROWSER_TEST_F(PicasaDataProviderInvalidateInflightAlbumsIndexerTest
,
556 InvalidateInflightAlbumsIndexerTest
) {
560 } // namespace picasa