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 "base/logging.h"
6 #include "chrome/common/media_galleries/iphoto_library.h"
7 #include "chrome/utility/media_galleries/iphoto_library_parser.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 #define SIMPLE_HEADER() \
11 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
12 "<plist version=\"1.0\">" \
14 " <key>Archive Path</key>" \
15 " <string>/Users/username/px</string>"
17 #define ALBUMS_HEADER() \
18 " <key>List of Albums</key>" \
21 #define ALBUMS_FOOTER() \
24 #define SIMPLE_ALBUM(id, name, photo1, photo2) \
26 " <key>AlbumId</key>" \
27 " <integer>" #id "</integer>" \
28 " <key>AlbumName</key>" \
29 " <string>" name "</string>" \
30 " <key>KeyList</key>" \
32 " <string>" #photo1 "</string>" \
33 " <string>" #photo2 "</string>" \
37 #define IMAGE_LIST_HEADER() \
38 " <key>Master Image List</key>" \
41 #define IMAGE_LIST_FOOTER() \
44 #define SIMPLE_PHOTO(id, guid, path, caption) \
45 " <key>" #id "</key>" \
47 " <key>MediaType</key>" \
48 " <string>Image</string>" \
49 " <key>Caption</key>" \
50 " <string>" caption "</string>" \
52 " <string>" #guid "</string>" \
53 " <key>ModDateAsTimerInterval</key>" \
54 " <string>386221543.0000</string>" \
55 " <key>DateAsTimerInterval</key>" \
56 " <string>386221543.0000</string>" \
57 " <key>DateAsTimerIntervalGMT</key>" \
58 " <string>385123456.00</string>" \
59 " <key>ImagePath</key>" \
60 " <string>" path "</string>" \
61 " <key>OriginalPath</key>" \
62 " <string>/original" path "</string>" \
63 " <key>ThumbPath</key>" \
64 " <string>" path "</string>" \
67 #define SIMPLE_FOOTER() \
71 // Mismatched key/string tag at ImagePath.
72 #define MALFORMED_PHOTO1(id, guid, path, caption) \
73 " <key>" #id "</key>" \
75 " <key>MediaType</key>" \
76 " <string>Image</string>" \
77 " <key>Caption<key>" \
78 " <string>" caption "</string>" \
80 " <string>" #guid "</string>" \
81 " <key>ImagePath</string>" \
82 " <string>" path "</string>" \
83 " <key>ThumbPath</key>" \
84 " <string>" path "</string>" \
87 // Missing "<" delimiter at ImagePath.
88 #define MALFORMED_PHOTO2(id, guid, path, caption) \
89 " <key>" #id "</key>" \
91 " <key>MediaType</key>" \
92 " <string>Image</string>" \
93 " <key>Caption<key>" \
94 " <string>" caption "</string>" \
96 " <string>" #guid "</string>" \
97 " <key>ImagePath/key>" \
98 " <string>" path "</string>" \
99 " <key>ThumbPath</key>" \
100 " <string>" path "</string>" \
107 void ComparePhoto(const parser::Photo
& a
, const parser::Photo
& b
) {
108 EXPECT_EQ(a
.id
, b
.id
);
109 EXPECT_EQ(a
.location
.value(), b
.location
.value());
110 EXPECT_EQ(a
.original_location
.value(), b
.original_location
.value());
113 void CompareAlbum(const parser::Album
& a
, const parser::Album
& b
) {
114 EXPECT_EQ(a
.size(), b
.size());
116 parser::Album::const_iterator a_it
;
117 parser::Album::const_iterator b_it
;
118 for (a_it
= a
.begin(), b_it
= b
.begin();
119 a_it
!= a
.end() && b_it
!= b
.end();
121 EXPECT_EQ(*a_it
, *b_it
);
125 void CompareAlbums(const parser::Albums
& a
, const parser::Albums
& b
) {
126 EXPECT_EQ(a
.size(), b
.size());
128 parser::Albums::const_iterator a_it
;
129 parser::Albums::const_iterator b_it
;
130 for (a_it
= a
.begin(), b_it
= b
.begin();
131 a_it
!= a
.end() && b_it
!= b
.end();
133 EXPECT_EQ(a_it
->first
, b_it
->first
);
134 CompareAlbum(a_it
->second
, b_it
->second
);
138 void CompareLibrary(const parser::Library
& a
, const parser::Library
& b
) {
139 CompareAlbums(a
.albums
, b
.albums
);
141 std::set
<parser::Photo
>::const_iterator a_it
;
142 std::set
<parser::Photo
>::const_iterator b_it
;
143 for (a_it
= a
.all_photos
.begin(), b_it
= b
.all_photos
.begin();
144 a_it
!= a
.all_photos
.end() && b_it
!= b
.all_photos
.end();
146 ComparePhoto(*a_it
, *b_it
);
150 class IPhotoLibraryParserTest
: public testing::Test
{
152 IPhotoLibraryParserTest() {}
154 void TestParser(bool expected_result
, const std::string
& xml
) {
155 IPhotoLibraryParser parser
;
157 EXPECT_EQ(expected_result
, parser
.Parse(xml
));
158 if (!expected_result
)
161 CompareLibrary(expected_library_
, parser
.library());
164 void AddExpectedPhoto(uint32 id
,
165 const std::string
& location
,
166 const std::string
& album
) {
167 parser::Photo
photo(id
, base::FilePath::FromUTF8Unsafe(location
),
168 base::FilePath::FromUTF8Unsafe("/original" + location
));
170 expected_library_
.albums
[album
].insert(id
);
171 expected_library_
.all_photos
.insert(photo
);
175 parser::Library expected_library_
;
177 DISALLOW_COPY_AND_ASSIGN(IPhotoLibraryParserTest
);
180 TEST_F(IPhotoLibraryParserTest
, EmptyLibrary
) {
181 TestParser(false, "");
184 TEST_F(IPhotoLibraryParserTest
, MinimalXML
) {
185 AddExpectedPhoto(1, "/dir/Photo With Space.jpg", "");
190 SIMPLE_PHOTO(1, 1, "/dir/Photo With Space.jpg", "Photo 1")
195 TEST_F(IPhotoLibraryParserTest
, MultiplePhotos
) {
196 AddExpectedPhoto(1, "/dir/SongA1.jpg", "");
197 AddExpectedPhoto(2, "/dir/SongA2.jpg", "");
198 AddExpectedPhoto(3, "/dir/SongA3.jpg", "");
199 AddExpectedPhoto(4, "/dir/SongB1.jpg", "");
200 AddExpectedPhoto(5, "/dir/SongB2.jpg", "");
201 AddExpectedPhoto(6, "/dir2/SongB1.jpg", "");
202 AddExpectedPhoto(7, "/dir2/SongB2.jpg", "");
207 SIMPLE_PHOTO(1, 1, "/dir/SongA1.jpg", "Photo 1")
208 SIMPLE_PHOTO(2, 2, "/dir/SongA2.jpg", "Photo 2")
209 SIMPLE_PHOTO(3, 3, "/dir/SongA3.jpg", "Photo 3")
210 SIMPLE_PHOTO(4, 4, "/dir/SongB1.jpg", "Photo 4")
211 SIMPLE_PHOTO(5, 5, "/dir/SongB2.jpg", "Photo 5")
212 SIMPLE_PHOTO(6, 6, "/dir2/SongB1.jpg", "Photo 6")
213 SIMPLE_PHOTO(7, 7, "/dir2/SongB2.jpg", "Photo 7")
218 TEST_F(IPhotoLibraryParserTest
, Albums
) {
219 AddExpectedPhoto(1, "/dir/PhotoA1.jpg", "Album 1");
220 AddExpectedPhoto(2, "/dir/PhotoA2.jpg", "Album 1");
221 AddExpectedPhoto(3, "/dir/PhotoA3.jpg", "Album 2");
222 AddExpectedPhoto(4, "/dir/PhotoB1.jpg", "Album 2");
223 AddExpectedPhoto(5, "/dir/PhotoB2.jpg", "Album 3");
224 AddExpectedPhoto(6, "/dir2/PhotoB1.jpg", "Album 3");
225 AddExpectedPhoto(7, "/dir2/PhotoB2.jpg", "");
230 SIMPLE_ALBUM(10, "Album 1", 1, 2)
231 SIMPLE_ALBUM(11, "Album 2", 3, 4)
232 SIMPLE_ALBUM(11, "Album/3", 5, 6)
235 SIMPLE_PHOTO(1, 1, "/dir/PhotoA1.jpg", "Photo 1")
236 SIMPLE_PHOTO(2, 2, "/dir/PhotoA2.jpg", "Photo 2")
237 SIMPLE_PHOTO(3, 3, "/dir/PhotoA3.jpg", "Photo 3")
238 SIMPLE_PHOTO(4, 4, "/dir/PhotoB1.jpg", "Photo 4")
239 SIMPLE_PHOTO(5, 5, "/dir/PhotoB2.jpg", "Photo 5")
240 SIMPLE_PHOTO(6, 6, "/dir2/PhotoB1.jpg", "Photo 6")
241 SIMPLE_PHOTO(7, 7, "/dir2/PhotoB2.jpg", "Photo 7")
246 TEST_F(IPhotoLibraryParserTest
, MalformedStructure
) {
262 SIMPLE_PHOTO(1, 1, "/bad.jpg", "p1")
274 SIMPLE_PHOTO(1, 1, "/bad.jpg", "p1")
279 TEST_F(IPhotoLibraryParserTest
, MalformedSyntax
) {
286 MALFORMED_PHOTO1(1, 1, "/bad.jpg", "p1")
296 MALFORMED_PHOTO2(1, 1, "/bad.jpg", "p1")
301 TEST_F(IPhotoLibraryParserTest
, DuplicateAlbumNames
) {
302 AddExpectedPhoto(1, "/dir/PhotoA1.jpg", "Album 1");
303 AddExpectedPhoto(2, "/dir/PhotoA2.jpg", "Album 1");
304 AddExpectedPhoto(3, "/dir/PhotoA3.jpg", "Album 1(11)");
305 AddExpectedPhoto(4, "/dir/PhotoB1.jpg", "Album 1(11)");
310 SIMPLE_ALBUM(10, "Album 1", 1, 2)
311 SIMPLE_ALBUM(11, "Album 1", 3, 4)
314 SIMPLE_PHOTO(1, 1, "/dir/PhotoA1.jpg", "Photo 1")
315 SIMPLE_PHOTO(2, 2, "/dir/PhotoA2.jpg", "Photo 2")
316 SIMPLE_PHOTO(3, 3, "/dir/PhotoA3.jpg", "Photo 3")
317 SIMPLE_PHOTO(4, 4, "/dir/PhotoB1.jpg", "Photo 4")
324 } // namespace iphoto