- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / utility / media_galleries / itunes_library_parser_unittest.cc
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.
4
5 #include "base/logging.h"
6 #include "chrome/common/media_galleries/itunes_library.h"
7 #include "chrome/utility/media_galleries/itunes_library_parser.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 #define SIMPLE_HEADER()         \
11     "<plist>"                   \
12     "  <dict>"                  \
13     "    <key>Tracks</key>"     \
14     "    <dict>"
15
16 #define SIMPLE_TRACK(key, id, path, artist, album)                     \
17     "<key>" #key "</key>"                                              \
18     "<dict>"                                                           \
19     "  <key>Track ID</key><integer>" #id "</integer>"                  \
20     "  <key>Location</key><string>file://localhost/" path "</string>"  \
21     "  <key>Artist</key><string>" artist "</string>"                   \
22     "  <key>Album</key><string>" album "</string>"                     \
23     "</dict>"
24
25 #define SIMPLE_FOOTER()  \
26     "    </dict>"        \
27     "  </dict>"          \
28     "</plist>"
29
30 namespace itunes {
31
32 namespace {
33
34 void CompareTrack(const parser::Track& a, const parser::Track& b) {
35   EXPECT_EQ(a.id, b.id);
36   EXPECT_EQ(a.location.value(), b.location.value());
37 }
38
39 void CompareAlbum(const parser::Album& a, const parser::Album& b) {
40   EXPECT_EQ(a.size(), b.size());
41
42   parser::Album::const_iterator a_it;
43   parser::Album::const_iterator b_it;
44   for (a_it = a.begin(), b_it = b.begin();
45        a_it != a.end() && b_it != b.end();
46        ++a_it, ++b_it) {
47     CompareTrack(*a_it, *b_it);
48   }
49 }
50
51 void CompareAlbums(const parser::Albums& a, const parser::Albums& b) {
52   EXPECT_EQ(a.size(), b.size());
53
54   parser::Albums::const_iterator a_it;
55   parser::Albums::const_iterator b_it;
56   for (a_it = a.begin(), b_it = b.begin();
57        a_it != a.end() && b_it != b.end();
58        ++a_it, ++b_it) {
59     EXPECT_EQ(a_it->first, b_it->first);
60     CompareAlbum(a_it->second, b_it->second);
61   }
62 }
63
64 void CompareLibrary(const parser::Library& a, const parser::Library& b) {
65   EXPECT_EQ(a.size(), b.size());
66
67   parser::Library::const_iterator a_it;
68   parser::Library::const_iterator b_it;
69   for (a_it = a.begin(), b_it = b.begin();
70        a_it != a.end() && b_it != b.end();
71        ++a_it, ++b_it) {
72     EXPECT_EQ(a_it->first, b_it->first);
73     CompareAlbums(a_it->second, b_it->second);
74   }
75 }
76
77 class ITunesLibraryParserTest : public testing::Test {
78  public:
79   ITunesLibraryParserTest() {}
80
81   void TestParser(bool expected_result, const std::string& xml) {
82     ITunesLibraryParser parser;
83
84     EXPECT_EQ(expected_result, parser.Parse(xml));
85     if (!expected_result)
86       return;
87
88     CompareLibrary(expected_library_, parser.library());
89   }
90
91   void AddExpectedTrack(uint32 id, const std::string& location,
92                         const std::string& artist, const std::string& album) {
93     // On Mac this pretends that C: is a directory.
94 #if defined(OS_MACOSX)
95     std::string os_location = "/" + location;
96 #else
97     const std::string& os_location = location;
98 #endif
99     parser::Track track(id, base::FilePath::FromUTF8Unsafe(os_location));
100     expected_library_[artist][album].insert(track);
101   }
102
103  private:
104   parser::Library expected_library_;
105
106   DISALLOW_COPY_AND_ASSIGN(ITunesLibraryParserTest);
107 };
108
109 TEST_F(ITunesLibraryParserTest, EmptyLibrary) {
110   TestParser(false, "");
111 }
112
113 TEST_F(ITunesLibraryParserTest, MinimalXML) {
114   AddExpectedTrack(1, "C:/dir/Song With Space.mp3", "Artist A", "Album A");
115   TestParser(
116       true,
117       SIMPLE_HEADER()
118       SIMPLE_TRACK(1, 1, "C:/dir/Song%20With%20Space.mp3", "Artist A",
119                    "Album A")
120       SIMPLE_FOOTER());
121 }
122
123 TEST_F(ITunesLibraryParserTest, MultipleSongs) {
124   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
125   AddExpectedTrack(2, "C:/dir/SongA2.mp3", "Artist A", "Album A");
126   AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Artist A", "Album A");
127   AddExpectedTrack(4, "C:/dir/SongB1.mp3", "Artist A", "Album B");
128   AddExpectedTrack(5, "C:/dir/SongB2.mp3", "Artist A", "Album B");
129   AddExpectedTrack(6, "C:/dir2/SongB1.mp3", "Artist B", "Album B");
130   AddExpectedTrack(7, "C:/dir2/SongB2.mp3", "Artist B", "Album B");
131   TestParser(
132       true,
133       SIMPLE_HEADER()
134       SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
135       SIMPLE_TRACK(2, 2, "C:/dir/SongA2.mp3", "Artist A", "Album A")
136       SIMPLE_TRACK(3, 3, "C:/dir/SongA3.mp3", "Artist A", "Album A")
137       SIMPLE_TRACK(4, 4, "C:/dir/SongB1.mp3", "Artist A", "Album B")
138       SIMPLE_TRACK(5, 5, "C:/dir/SongB2.mp3", "Artist A", "Album B")
139       SIMPLE_TRACK(6, 6, "C:/dir2/SongB1.mp3", "Artist B", "Album B")
140       SIMPLE_TRACK(7, 7, "C:/dir2/SongB2.mp3", "Artist B", "Album B")
141       SIMPLE_FOOTER());
142 }
143
144 TEST_F(ITunesLibraryParserTest, MismatchedId) {
145   TestParser(
146       false,
147       SIMPLE_HEADER()
148       SIMPLE_TRACK(1, 2, "C:/dir/SongA1.mp3", "Artist A", "Album A")
149       SIMPLE_FOOTER());
150
151   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
152   TestParser(
153       true,
154       SIMPLE_HEADER()
155       SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
156       SIMPLE_TRACK(2, 3, "C:/dir/SongA2.mp3", "Artist A", "Album A")
157       SIMPLE_FOOTER());
158 }
159
160 TEST_F(ITunesLibraryParserTest, OtherDictionaryEntries) {
161   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
162   TestParser(
163       true,
164       "<plist>"
165       "  <dict>"
166       "    <key>Other section</key>"
167       "    <dict>"
168       // In Other section, not Tracks.
169       SIMPLE_TRACK(10, 10, "C:/dir/SongB2.mp3", "Artist B", "Album B")
170       "    </dict>"
171       "    <key>Tracks</key>"
172       "    <dict>"
173       "      <key>1</key>"
174       "      <dict>"
175       // In the body of a track dictionary before the interesting entries.
176       SIMPLE_TRACK(20, 20, "C:/dir/SongB2.mp3", "Artist B", "Album B")
177       // Entries in a different order.
178       "        <key>Artist</key><string>Artist A</string>"
179       "        <key>Location</key>"
180       "          <string>file://localhost/C:/dir/SongA1.mp3</string>"
181       "        <key>Album</key><string>Album A</string>"
182       "        <key>Track ID</key><integer>1</integer>"
183       // In the body of a track dictionary after the interesting entries.
184       SIMPLE_TRACK(30, 30, "C:/dir/SongB3.mp3", "Artist B", "Album B")
185       "      </dict>"
186       "      <key>40</key>"
187       "      <dict>"
188       // Missing album name.
189       "        <key>Artist</key><string>Artist B</string>"
190       "        <key>Location</key>"
191       "          <string>file://localhost/C:/dir/SongB4.mp3</string>"
192       "        <key>Track ID</key><integer>1</integer>"
193       "      </dict>"
194       SIMPLE_FOOTER());
195 }
196
197 TEST_F(ITunesLibraryParserTest, MissingEntry) {
198   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Album A");
199   AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Artist A", "Album A");
200   TestParser(
201       true,
202       SIMPLE_HEADER()
203       SIMPLE_TRACK(1, 1, "C:/dir/SongA1.mp3", "Artist A", "Album A")
204       "<key>2</key><dict>"
205       "  <key>Track ID</key><integer>2</integer>"
206       "  <key>Album</key><string>Album A</string>"
207       "  <key>Foo</key><string>Bar</string>"
208       "   "  // A whitespace node is important for the test.
209       "</dict>"
210       SIMPLE_TRACK(3, 3, "C:/dir/SongA3.mp3", "Artist A", "Album A")
211       SIMPLE_FOOTER());
212 }
213
214 TEST_F(ITunesLibraryParserTest, UnknownAlbumOrArtist) {
215   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Unknown Album");
216   AddExpectedTrack(2, "C:/dir/SongA2.mp3", "Unknown Artist", "Album A");
217   AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Unknown Artist", "Unknown Album");
218   TestParser(
219       true,
220       SIMPLE_HEADER()
221       "<key>1</key><dict>"
222       "  <key>Track ID</key><integer>1</integer>"
223       "  <key>Location</key><string>file://localhost/C:/dir/SongA1.mp3</string>"
224       "  <key>Artist</key><string>Artist A</string>"
225       "</dict>"
226       "<key>2</key><dict>"
227       "  <key>Track ID</key><integer>2</integer>"
228       "  <key>Location</key><string>file://localhost/C:/dir/SongA2.mp3</string>"
229       "  <key>Album</key><string>Album A</string>"
230       "</dict>"
231       "<key>3</key><dict>"
232       "  <key>Track ID</key><integer>3</integer>"
233       "  <key>Location</key><string>file://localhost/C:/dir/SongA3.mp3</string>"
234       "</dict>"
235       SIMPLE_FOOTER());
236 }
237
238 TEST_F(ITunesLibraryParserTest, AlbumArtist) {
239   AddExpectedTrack(1, "C:/dir/SongA1.mp3", "Artist A", "Unknown Album");
240   AddExpectedTrack(2, "C:/dir/SongA2.mp3", "Artist A", "Unknown Album");
241   AddExpectedTrack(3, "C:/dir/SongA3.mp3", "Artist A", "Unknown Album");
242   AddExpectedTrack(4, "C:/dir/SongA4.mp3", "Artist A", "Album");
243   TestParser(
244       true,
245       SIMPLE_HEADER()
246       "<key>1</key><dict>"
247       "  <key>Track ID</key><integer>1</integer>"
248       "  <key>Location</key><string>file://localhost/C:/dir/SongA1.mp3</string>"
249       "  <key>Album Artist</key><string>Artist A</string>"
250       "</dict>"
251       "<key>2</key><dict>"
252       "  <key>Track ID</key><integer>2</integer>"
253       "  <key>Location</key><string>file://localhost/C:/dir/SongA2.mp3</string>"
254       "  <key>Artist</key><string>Artist B</string>"
255       "  <key>Album Artist</key><string>Artist A</string>"
256       "</dict>"
257       "<key>3</key><dict>"
258       "  <key>Track ID</key><integer>3</integer>"
259       "  <key>Location</key><string>file://localhost/C:/dir/SongA3.mp3</string>"
260       "  <key>Album Artist</key><string>Artist A</string>"
261       "  <key>Artist</key><string>Artist B</string>"
262       "</dict>"
263       "<key>4</key><dict>"
264       "  <key>Track ID</key><integer>4</integer>"
265       "  <key>Location</key><string>file://localhost/C:/dir/SongA4.mp3</string>"
266       "  <key>Album</key><string>Album</string>"
267       "  <key>Artist</key><string>Artist B</string>"
268       "  <key>Album Artist</key><string>Artist A</string>"
269       "</dict>"
270       SIMPLE_FOOTER());
271 }
272
273 TEST_F(ITunesLibraryParserTest, MacPath) {
274   AddExpectedTrack(1, "dir/Song With Space.mp3", "Artist A", "Album A");
275   TestParser(
276       true,
277       SIMPLE_HEADER()
278       // This path is concatenated with "http://localhost/", so no leading
279       // slash should be used.
280       SIMPLE_TRACK(1, 1, "dir/Song%20With%20Space.mp3", "Artist A", "Album A")
281       SIMPLE_FOOTER());
282 }
283
284 }  // namespace
285
286 }  // namespace itunes