Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / fileapi / itunes_data_provider_browsertest.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 <string>
6 #include <vector>
7
8 #include "base/bind.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/format_macros.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/run_loop.h"
17 #include "base/strings/stringprintf.h"
18 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h"
19 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
20 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "url/gurl.h"
24
25 namespace itunes {
26
27 namespace {
28
29 struct LibraryEntry {
30   LibraryEntry(const std::string& artist, const std::string& album,
31                const base::FilePath& location)
32       : artist(artist),
33         album(album),
34         location(location) {
35   }
36   std::string artist;
37   std::string album;
38   base::FilePath location;
39 };
40
41 }  // namespace
42
43 class TestITunesDataProvider : public ITunesDataProvider {
44  public:
45   TestITunesDataProvider(const base::FilePath& xml_library_path,
46                          const base::Closure& callback)
47       : ITunesDataProvider(xml_library_path),
48         callback_(callback) {
49   }
50   virtual ~TestITunesDataProvider() {}
51
52  private:
53   virtual void OnLibraryChanged(const base::FilePath& path,
54                                 bool error) OVERRIDE {
55     ITunesDataProvider::OnLibraryChanged(path, error);
56     callback_.Run();
57   }
58
59   base::Closure callback_;
60
61   DISALLOW_COPY_AND_ASSIGN(TestITunesDataProvider);
62 };
63
64 class ITunesDataProviderTest : public InProcessBrowserTest {
65  public:
66   ITunesDataProviderTest() {}
67   virtual ~ITunesDataProviderTest() {}
68
69  protected:
70   virtual void SetUp() OVERRIDE {
71     ASSERT_TRUE(library_dir_.CreateUniqueTempDir());
72     WriteLibraryInternal(SetUpLibrary());
73     // The ImportedMediaGalleryRegistry is created on which ever thread calls
74     // GetInstance() first.  It shouldn't matter what thread creates, however
75     // in practice it is always created on the UI thread, so this calls
76     // GetInstance here to mirror those real conditions.
77     ImportedMediaGalleryRegistry::GetInstance();
78     InProcessBrowserTest::SetUp();
79   }
80
81   void RunTest() {
82     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
83     base::RunLoop loop;
84     quit_closure_ = loop.QuitClosure();
85     MediaFileSystemBackend::MediaTaskRunner()->PostTask(
86         FROM_HERE,
87         base::Bind(&ITunesDataProviderTest::StartTestOnMediaTaskRunner,
88                    base::Unretained(this)));
89     loop.Run();
90   }
91
92   void WriteLibrary(const std::vector<LibraryEntry>& entries,
93                     const base::Closure& callback) {
94     SetLibraryChangeCallback(callback);
95     WriteLibraryInternal(entries);
96   }
97
98   void SetLibraryChangeCallback(const base::Closure& callback) {
99     EXPECT_TRUE(library_changed_callback_.is_null());
100     library_changed_callback_ = callback;
101   }
102
103   ITunesDataProvider* data_provider() const {
104     return ImportedMediaGalleryRegistry::ITunesDataProvider();
105   }
106
107   const base::FilePath& library_dir() const {
108     return library_dir_.path();
109   }
110
111   base::FilePath XmlFile() const {
112     return library_dir_.path().AppendASCII("library.xml");
113   }
114
115   void ExpectTrackLocation(const std::string& artist, const std::string& album,
116                            const std::string& track_name) {
117     base::FilePath track =
118         library_dir().AppendASCII(track_name).NormalizePathSeparators();
119     EXPECT_EQ(track.value(),
120               data_provider()->GetTrackLocation(
121                   artist, album, track_name).NormalizePathSeparators().value());
122   }
123
124   void ExpectNoTrack(const std::string& artist, const std::string& album,
125                      const std::string& track_name) {
126     EXPECT_TRUE(data_provider()->GetTrackLocation(
127           artist, album, track_name).empty()) << track_name;
128   }
129
130
131   // Get the initial set of library entries, called by SetUp.  If no entries
132   // are returned the xml file is not created.
133   virtual std::vector<LibraryEntry> SetUpLibrary() {
134     return std::vector<LibraryEntry>();
135   }
136
137   // Start the test. The data provider is refreshed before calling StartTest
138   // and the result of the refresh is passed in.
139   virtual void StartTest(bool parse_success) = 0;
140
141   void TestDone() {
142     DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
143     ImportedMediaGalleryRegistry* imported_registry =
144         ImportedMediaGalleryRegistry::GetInstance();
145     imported_registry->itunes_data_provider_.reset();
146     content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
147                                      quit_closure_);
148   }
149
150  private:
151   void StartTestOnMediaTaskRunner() {
152     DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
153     ImportedMediaGalleryRegistry* imported_registry =
154         ImportedMediaGalleryRegistry::GetInstance();
155     imported_registry->itunes_data_provider_.reset(
156         new TestITunesDataProvider(
157             XmlFile(),
158             base::Bind(&ITunesDataProviderTest::OnLibraryChanged,
159                        base::Unretained(this))));
160     data_provider()->RefreshData(base::Bind(&ITunesDataProviderTest::StartTest,
161                                             base::Unretained(this)));
162   };
163
164   void OnLibraryChanged() {
165     DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
166     if (!library_changed_callback_.is_null()) {
167       library_changed_callback_.Run();
168       library_changed_callback_.Reset();
169     }
170   }
171
172   void WriteLibraryInternal(const std::vector<LibraryEntry>& entries) {
173     if (!entries.size())
174       return;
175     std::string xml = "<plist><dict><key>Tracks</key><dict>\n";
176     for (size_t i = 0; i < entries.size(); ++i) {
177       std::string separator;
178 #if defined(OS_WIN)
179       separator = "/";
180 #endif
181       GURL location("file://localhost" + separator +
182                     entries[i].location.AsUTF8Unsafe());
183       std::string entry_string = base::StringPrintf(
184           "<key>%" PRIuS "</key><dict>\n"
185           "  <key>Track ID</key><integer>%" PRIuS "</integer>\n"
186           "  <key>Location</key><string>%s</string>\n"
187           "  <key>Artist</key><string>%s</string>\n"
188           "  <key>Album</key><string>%s</string>\n"
189           "</dict>\n",
190           i + 1, i + 1, location.spec().c_str(), entries[i].artist.c_str(),
191           entries[i].album.c_str());
192       xml += entry_string;
193     }
194     xml += "</dict></dict></plist>\n";
195     ASSERT_EQ(static_cast<int>(xml.size()),
196               file_util::WriteFile(XmlFile(), xml.c_str(), xml.size()));
197   }
198
199   base::ScopedTempDir library_dir_;
200
201   base::Closure library_changed_callback_;
202
203   base::Closure quit_closure_;
204
205   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderTest);
206 };
207
208 class ITunesDataProviderBasicTest : public ITunesDataProviderTest {
209  public:
210   ITunesDataProviderBasicTest() {}
211   virtual ~ITunesDataProviderBasicTest() {}
212
213   virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE {
214     base::FilePath track = library_dir().AppendASCII("Track.mp3");
215     std::vector<LibraryEntry> entries;
216     entries.push_back(LibraryEntry("Artist", "Album", track));
217     return entries;
218   }
219
220   virtual void StartTest(bool parse_success) OVERRIDE {
221     EXPECT_TRUE(parse_success);
222
223     // KnownArtist
224     EXPECT_TRUE(data_provider()->KnownArtist("Artist"));
225     EXPECT_FALSE(data_provider()->KnownArtist("Artist2"));
226
227     // KnownAlbum
228     EXPECT_TRUE(data_provider()->KnownAlbum("Artist", "Album"));
229     EXPECT_FALSE(data_provider()->KnownAlbum("Artist", "Album2"));
230     EXPECT_FALSE(data_provider()->KnownAlbum("Artist2", "Album"));
231
232     // GetTrackLocation
233     ExpectTrackLocation("Artist", "Album", "Track.mp3");
234     ExpectNoTrack("Artist", "Album", "Track2.mp3");
235     ExpectNoTrack("Artist", "Album2", "Track.mp3");
236     ExpectNoTrack("Artist2", "Album", "Track.mp3");
237
238     // GetArtistNames
239     std::set<ITunesDataProvider::ArtistName> artists =
240       data_provider()->GetArtistNames();
241     ASSERT_EQ(1U, artists.size());
242     EXPECT_EQ("Artist", *artists.begin());
243
244     // GetAlbumNames
245     std::set<ITunesDataProvider::AlbumName> albums =
246         data_provider()->GetAlbumNames("Artist");
247     ASSERT_EQ(1U, albums.size());
248     EXPECT_EQ("Album", *albums.begin());
249
250     albums = data_provider()->GetAlbumNames("Artist2");
251     EXPECT_EQ(0U, albums.size());
252
253     // GetAlbum
254     base::FilePath track =
255         library_dir().AppendASCII("Track.mp3").NormalizePathSeparators();
256     ITunesDataProvider::Album album =
257         data_provider()->GetAlbum("Artist", "Album");
258     ASSERT_EQ(1U, album.size());
259     EXPECT_EQ(track.BaseName().AsUTF8Unsafe(), album.begin()->first);
260     EXPECT_EQ(track.value(),
261               album.begin()->second.NormalizePathSeparators().value());
262
263     album = data_provider()->GetAlbum("Artist", "Album2");
264     EXPECT_EQ(0U, album.size());
265
266     album = data_provider()->GetAlbum("Artist2", "Album");
267     EXPECT_EQ(0U, album.size());
268
269     TestDone();
270   }
271
272  private:
273   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderBasicTest);
274 };
275
276 class ITunesDataProviderRefreshTest : public ITunesDataProviderTest {
277  public:
278   ITunesDataProviderRefreshTest() {}
279   virtual ~ITunesDataProviderRefreshTest() {}
280
281   virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE {
282     base::FilePath track = library_dir().AppendASCII("Track.mp3");
283     std::vector<LibraryEntry> entries;
284     entries.push_back(LibraryEntry("Artist", "Album", track));
285     return entries;
286   }
287
288   virtual void StartTest(bool parse_success) OVERRIDE {
289     EXPECT_TRUE(parse_success);
290
291     // Initial contents.
292     ExpectTrackLocation("Artist", "Album", "Track.mp3");
293     ExpectNoTrack("Artist2", "Album2", "Track2.mp3");
294
295     // New file.
296     base::FilePath track2 = library_dir().AppendASCII("Track2.mp3");
297     std::vector<LibraryEntry> entries;
298     entries.push_back(LibraryEntry("Artist2", "Album2", track2));
299     WriteLibrary(entries,
300                  base::Bind(&ITunesDataProviderRefreshTest::CheckAfterWrite,
301                             base::Unretained(this)));
302   }
303
304   void CheckAfterWrite() {
305     // Content the same.
306     ExpectTrackLocation("Artist", "Album", "Track.mp3");
307     ExpectNoTrack("Artist2", "Album2", "Track2.mp3");
308
309     data_provider()->RefreshData(
310         base::Bind(&ITunesDataProviderRefreshTest::CheckRefresh,
311                    base::Unretained(this)));
312   }
313
314   void CheckRefresh(bool is_valid) {
315     EXPECT_TRUE(is_valid);
316
317     ExpectTrackLocation("Artist2", "Album2", "Track2.mp3");
318     ExpectNoTrack("Artist", "Album", "Track.mp3");
319     TestDone();
320   }
321
322  private:
323   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderRefreshTest);
324 };
325
326 class ITunesDataProviderInvalidTest : public ITunesDataProviderTest {
327  public:
328   ITunesDataProviderInvalidTest() {}
329   virtual ~ITunesDataProviderInvalidTest() {}
330
331   virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE {
332     base::FilePath track = library_dir().AppendASCII("Track.mp3");
333     std::vector<LibraryEntry> entries;
334     entries.push_back(LibraryEntry("Artist", "Album", track));
335     return entries;
336   }
337
338   virtual void StartTest(bool parse_success) OVERRIDE {
339     EXPECT_TRUE(parse_success);
340
341     SetLibraryChangeCallback(
342         base::Bind(&ITunesDataProvider::RefreshData,
343                    base::Unretained(data_provider()),
344                    base::Bind(&ITunesDataProviderInvalidTest::CheckInvalid,
345                               base::Unretained(this))));
346     ASSERT_EQ(1L, file_util::WriteFile(XmlFile(), " ", 1));
347   }
348
349   void CheckInvalid(bool is_valid) {
350     EXPECT_FALSE(is_valid);
351     TestDone();
352   }
353
354  private:
355   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderInvalidTest);
356 };
357
358 class ITunesDataProviderUniqueNameTest : public ITunesDataProviderTest {
359  public:
360   ITunesDataProviderUniqueNameTest() {}
361   virtual ~ITunesDataProviderUniqueNameTest() {}
362
363   virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE {
364     base::FilePath track = library_dir().AppendASCII("Track.mp3");
365     std::vector<LibraryEntry> entries;
366     // Dupe album names should get uniquified with the track id, which in the
367     // test framework is the vector index.
368     entries.push_back(LibraryEntry("Artist", "Album", track));
369     entries.push_back(LibraryEntry("Artist", "Album", track));
370     entries.push_back(LibraryEntry("Artist", "Album2", track));
371     return entries;
372   }
373
374   virtual void StartTest(bool parse_success) OVERRIDE {
375     EXPECT_TRUE(parse_success);
376
377     base::FilePath track =
378         library_dir().AppendASCII("Track.mp3").NormalizePathSeparators();
379     EXPECT_EQ(track.value(),
380               data_provider()->GetTrackLocation(
381                   "Artist", "Album",
382                   "Track (1).mp3").NormalizePathSeparators().value());
383     EXPECT_EQ(track.value(),
384               data_provider()->GetTrackLocation(
385                   "Artist", "Album",
386                   "Track (2).mp3").NormalizePathSeparators().value());
387     EXPECT_EQ(track.value(),
388               data_provider()->GetTrackLocation(
389                   "Artist", "Album2",
390                   "Track.mp3").NormalizePathSeparators().value());
391
392     TestDone();
393   }
394
395  private:
396   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderUniqueNameTest);
397 };
398
399 class ITunesDataProviderEscapeTest : public ITunesDataProviderTest {
400  // Albums and tracks that aren't the same, but become the same after
401  // replacing bad characters are not handled properly, but that case should
402  // never happen in practice.
403  public:
404   ITunesDataProviderEscapeTest() {}
405   virtual ~ITunesDataProviderEscapeTest() {}
406
407   virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE {
408     base::FilePath track = library_dir().AppendASCII("Track:1.mp3");
409     std::vector<LibraryEntry> entries;
410     entries.push_back(LibraryEntry("Artist:/name", "Album:name/", track));
411     entries.push_back(LibraryEntry("Artist/name", "Album:name", track));
412     entries.push_back(LibraryEntry("Artist/name", "Album:name", track));
413     return entries;
414   }
415
416   virtual void StartTest(bool parse_success) OVERRIDE {
417     EXPECT_TRUE(parse_success);
418
419     base::FilePath track =
420         library_dir().AppendASCII("Track:1.mp3").NormalizePathSeparators();
421     EXPECT_EQ(track.value(),
422               data_provider()->GetTrackLocation(
423                   "Artist__name", "Album_name_",
424                   "Track_1.mp3").NormalizePathSeparators().value());
425     EXPECT_EQ(track.value(),
426               data_provider()->GetTrackLocation(
427                   "Artist_name", "Album_name",
428                   "Track_1 (2).mp3").NormalizePathSeparators().value());
429     EXPECT_EQ(track.value(),
430               data_provider()->GetTrackLocation(
431                   "Artist_name", "Album_name",
432                   "Track_1 (3).mp3").NormalizePathSeparators().value());
433
434     TestDone();
435   }
436
437  private:
438   DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderEscapeTest);
439 };
440
441 IN_PROC_BROWSER_TEST_F(ITunesDataProviderBasicTest, BasicTest) {
442   RunTest();
443 }
444
445 IN_PROC_BROWSER_TEST_F(ITunesDataProviderRefreshTest, RefreshTest) {
446   RunTest();
447 }
448
449 IN_PROC_BROWSER_TEST_F(ITunesDataProviderInvalidTest, InvalidTest) {
450   RunTest();
451 }
452
453 IN_PROC_BROWSER_TEST_F(ITunesDataProviderUniqueNameTest, UniqueNameTest) {
454   RunTest();
455 }
456
457 IN_PROC_BROWSER_TEST_F(ITunesDataProviderEscapeTest, EscapeTest) {
458   RunTest();
459 }
460
461 }  // namespace itunes