// Copyright 2013 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 "base/logging.h" #include "chrome/common/media_galleries/iphoto_library.h" #include "chrome/utility/media_galleries/iphoto_library_parser.h" #include "testing/gtest/include/gtest/gtest.h" #define SIMPLE_HEADER() \ "" \ "" \ " " \ " Archive Path" \ " /Users/username/px" #define ALBUMS_HEADER() \ " List of Albums" \ " " #define ALBUMS_FOOTER() \ " " #define SIMPLE_ALBUM(id, name, photo1, photo2) \ " " \ " AlbumId" \ " " #id "" \ " AlbumName" \ " " name "" \ " KeyList" \ " " \ " " #photo1 "" \ " " #photo2 "" \ " " \ " " #define IMAGE_LIST_HEADER() \ " Master Image List" \ " " #define IMAGE_LIST_FOOTER() \ " " #define SIMPLE_PHOTO(id, guid, path, caption) \ " " #id "" \ " " \ " MediaType" \ " Image" \ " Caption" \ " " caption "" \ " GUID" \ " " #guid "" \ " ModDateAsTimerInterval" \ " 386221543.0000" \ " DateAsTimerInterval" \ " 386221543.0000" \ " DateAsTimerIntervalGMT" \ " 385123456.00" \ " ImagePath" \ " " path "" \ " OriginalPath" \ " /original" path "" \ " ThumbPath" \ " " path "" \ " " #define SIMPLE_FOOTER() \ " " \ "" // Mismatched key/string tag at ImagePath. #define MALFORMED_PHOTO1(id, guid, path, caption) \ " " #id "" \ " " \ " MediaType" \ " Image" \ " Caption" \ " " caption "" \ " GUID" \ " " #guid "" \ " ImagePath" \ " " path "" \ " ThumbPath" \ " " path "" \ " " // Missing "<" delimiter at ImagePath. #define MALFORMED_PHOTO2(id, guid, path, caption) \ " " #id "" \ " " \ " MediaType" \ " Image" \ " Caption" \ " " caption "" \ " GUID" \ " " #guid "" \ " ImagePath/key>" \ " " path "" \ " ThumbPath" \ " " path "" \ " " namespace iphoto { namespace { void ComparePhoto(const parser::Photo& a, const parser::Photo& b) { EXPECT_EQ(a.id, b.id); EXPECT_EQ(a.location.value(), b.location.value()); EXPECT_EQ(a.original_location.value(), b.original_location.value()); } void CompareAlbum(const parser::Album& a, const parser::Album& b) { EXPECT_EQ(a.size(), b.size()); parser::Album::const_iterator a_it; parser::Album::const_iterator b_it; for (a_it = a.begin(), b_it = b.begin(); a_it != a.end() && b_it != b.end(); ++a_it, ++b_it) { EXPECT_EQ(*a_it, *b_it); } } void CompareAlbums(const parser::Albums& a, const parser::Albums& b) { EXPECT_EQ(a.size(), b.size()); parser::Albums::const_iterator a_it; parser::Albums::const_iterator b_it; for (a_it = a.begin(), b_it = b.begin(); a_it != a.end() && b_it != b.end(); ++a_it, ++b_it) { EXPECT_EQ(a_it->first, b_it->first); CompareAlbum(a_it->second, b_it->second); } } void CompareLibrary(const parser::Library& a, const parser::Library& b) { CompareAlbums(a.albums, b.albums); std::set::const_iterator a_it; std::set::const_iterator b_it; for (a_it = a.all_photos.begin(), b_it = b.all_photos.begin(); a_it != a.all_photos.end() && b_it != b.all_photos.end(); ++a_it, ++b_it) { ComparePhoto(*a_it, *b_it); } } class IPhotoLibraryParserTest : public testing::Test { public: IPhotoLibraryParserTest() {} void TestParser(bool expected_result, const std::string& xml) { IPhotoLibraryParser parser; EXPECT_EQ(expected_result, parser.Parse(xml)); if (!expected_result) return; CompareLibrary(expected_library_, parser.library()); } void AddExpectedPhoto(uint32 id, const std::string& location, const std::string& album) { parser::Photo photo(id, base::FilePath::FromUTF8Unsafe(location), base::FilePath::FromUTF8Unsafe("/original" + location)); if (!album.empty()) expected_library_.albums[album].insert(id); expected_library_.all_photos.insert(photo); } private: parser::Library expected_library_; DISALLOW_COPY_AND_ASSIGN(IPhotoLibraryParserTest); }; TEST_F(IPhotoLibraryParserTest, EmptyLibrary) { TestParser(false, ""); } TEST_F(IPhotoLibraryParserTest, MinimalXML) { AddExpectedPhoto(1, "/dir/Photo With Space.jpg", ""); TestParser( true, SIMPLE_HEADER() IMAGE_LIST_HEADER() SIMPLE_PHOTO(1, 1, "/dir/Photo With Space.jpg", "Photo 1") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } TEST_F(IPhotoLibraryParserTest, MultiplePhotos) { AddExpectedPhoto(1, "/dir/SongA1.jpg", ""); AddExpectedPhoto(2, "/dir/SongA2.jpg", ""); AddExpectedPhoto(3, "/dir/SongA3.jpg", ""); AddExpectedPhoto(4, "/dir/SongB1.jpg", ""); AddExpectedPhoto(5, "/dir/SongB2.jpg", ""); AddExpectedPhoto(6, "/dir2/SongB1.jpg", ""); AddExpectedPhoto(7, "/dir2/SongB2.jpg", ""); TestParser( true, SIMPLE_HEADER() IMAGE_LIST_HEADER() SIMPLE_PHOTO(1, 1, "/dir/SongA1.jpg", "Photo 1") SIMPLE_PHOTO(2, 2, "/dir/SongA2.jpg", "Photo 2") SIMPLE_PHOTO(3, 3, "/dir/SongA3.jpg", "Photo 3") SIMPLE_PHOTO(4, 4, "/dir/SongB1.jpg", "Photo 4") SIMPLE_PHOTO(5, 5, "/dir/SongB2.jpg", "Photo 5") SIMPLE_PHOTO(6, 6, "/dir2/SongB1.jpg", "Photo 6") SIMPLE_PHOTO(7, 7, "/dir2/SongB2.jpg", "Photo 7") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } TEST_F(IPhotoLibraryParserTest, Albums) { AddExpectedPhoto(1, "/dir/PhotoA1.jpg", "Album 1"); AddExpectedPhoto(2, "/dir/PhotoA2.jpg", "Album 1"); AddExpectedPhoto(3, "/dir/PhotoA3.jpg", "Album 2"); AddExpectedPhoto(4, "/dir/PhotoB1.jpg", "Album 2"); AddExpectedPhoto(5, "/dir/PhotoB2.jpg", "Album 3"); AddExpectedPhoto(6, "/dir2/PhotoB1.jpg", "Album 3"); AddExpectedPhoto(7, "/dir2/PhotoB2.jpg", ""); TestParser( true, SIMPLE_HEADER() ALBUMS_HEADER() SIMPLE_ALBUM(10, "Album 1", 1, 2) SIMPLE_ALBUM(11, "Album 2", 3, 4) SIMPLE_ALBUM(11, "Album/3", 5, 6) ALBUMS_FOOTER() IMAGE_LIST_HEADER() SIMPLE_PHOTO(1, 1, "/dir/PhotoA1.jpg", "Photo 1") SIMPLE_PHOTO(2, 2, "/dir/PhotoA2.jpg", "Photo 2") SIMPLE_PHOTO(3, 3, "/dir/PhotoA3.jpg", "Photo 3") SIMPLE_PHOTO(4, 4, "/dir/PhotoB1.jpg", "Photo 4") SIMPLE_PHOTO(5, 5, "/dir/PhotoB2.jpg", "Photo 5") SIMPLE_PHOTO(6, 6, "/dir2/PhotoB1.jpg", "Photo 6") SIMPLE_PHOTO(7, 7, "/dir2/PhotoB2.jpg", "Photo 7") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } TEST_F(IPhotoLibraryParserTest, MalformedStructure) { TestParser( false, SIMPLE_HEADER() ALBUMS_HEADER() ALBUMS_HEADER() ALBUMS_FOOTER() SIMPLE_FOOTER()); TestParser( false, SIMPLE_HEADER() ALBUMS_HEADER() ALBUMS_FOOTER() IMAGE_LIST_HEADER() IMAGE_LIST_HEADER() SIMPLE_PHOTO(1, 1, "/bad.jpg", "p1") IMAGE_LIST_FOOTER() IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); TestParser( false, SIMPLE_HEADER() ALBUMS_HEADER() ALBUMS_FOOTER() IMAGE_LIST_HEADER() ALBUMS_HEADER() SIMPLE_PHOTO(1, 1, "/bad.jpg", "p1") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } TEST_F(IPhotoLibraryParserTest, MalformedSyntax) { TestParser( false, SIMPLE_HEADER() ALBUMS_HEADER() ALBUMS_FOOTER() IMAGE_LIST_HEADER() MALFORMED_PHOTO1(1, 1, "/bad.jpg", "p1") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); TestParser( false, SIMPLE_HEADER() ALBUMS_HEADER() ALBUMS_FOOTER() IMAGE_LIST_HEADER() MALFORMED_PHOTO2(1, 1, "/bad.jpg", "p1") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } TEST_F(IPhotoLibraryParserTest, DuplicateAlbumNames) { AddExpectedPhoto(1, "/dir/PhotoA1.jpg", "Album 1"); AddExpectedPhoto(2, "/dir/PhotoA2.jpg", "Album 1"); AddExpectedPhoto(3, "/dir/PhotoA3.jpg", "Album 1(11)"); AddExpectedPhoto(4, "/dir/PhotoB1.jpg", "Album 1(11)"); TestParser( true, SIMPLE_HEADER() ALBUMS_HEADER() SIMPLE_ALBUM(10, "Album 1", 1, 2) SIMPLE_ALBUM(11, "Album 1", 3, 4) ALBUMS_FOOTER() IMAGE_LIST_HEADER() SIMPLE_PHOTO(1, 1, "/dir/PhotoA1.jpg", "Photo 1") SIMPLE_PHOTO(2, 2, "/dir/PhotoA2.jpg", "Photo 2") SIMPLE_PHOTO(3, 3, "/dir/PhotoA3.jpg", "Photo 3") SIMPLE_PHOTO(4, 4, "/dir/PhotoB1.jpg", "Photo 4") IMAGE_LIST_FOOTER() SIMPLE_FOOTER()); } } // namespace } // namespace iphoto