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