[Media Router] Add integration tests and e2e tests for media router and presentation...
[chromium-blink-merge.git] / chrome / browser / media_galleries / fileapi / itunes_data_provider_browsertest.cc
blob72130a00232822af6a101b1fb064f538bc92757a
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 <string>
6 #include <vector>
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"
25 namespace itunes {
27 namespace {
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) {
36 std::string artist;
37 std::string album;
38 base::FilePath location;
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};
48 } // namespace
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) {
57 ~TestITunesDataProvider() override {}
59 private:
60 void OnLibraryChanged(const base::FilePath& path, bool error) override {
61 ITunesDataProvider::OnLibraryChanged(path, error);
62 callback_.Run();
65 base::Closure callback_;
67 DISALLOW_COPY_AND_ASSIGN(TestITunesDataProvider);
70 class ITunesDataProviderTest : public InProcessBrowserTest {
71 public:
72 ITunesDataProviderTest() {}
74 protected:
75 void SetUp() override {
76 ASSERT_TRUE(library_dir_.CreateUniqueTempDir());
77 WriteLibraryInternal(SetUpLibrary());
78 // The ImportedMediaGalleryRegistry is created on which ever thread calls
79 // GetInstance() first. It shouldn't matter what thread creates, however
80 // in practice it is always created on the UI thread, so this calls
81 // GetInstance here to mirror those real conditions.
82 ImportedMediaGalleryRegistry::GetInstance();
83 InProcessBrowserTest::SetUp();
86 void RunTest() {
87 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
88 base::RunLoop loop;
89 quit_closure_ = loop.QuitClosure();
90 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
91 FROM_HERE,
92 base::Bind(&ITunesDataProviderTest::StartTestOnMediaTaskRunner,
93 base::Unretained(this)));
94 loop.Run();
97 void WriteLibrary(const std::vector<LibraryEntry>& entries,
98 const base::Closure& callback) {
99 SetLibraryChangeCallback(callback);
100 WriteLibraryInternal(entries);
103 void SetLibraryChangeCallback(const base::Closure& callback) {
104 EXPECT_TRUE(library_changed_callback_.is_null());
105 library_changed_callback_ = callback;
108 ITunesDataProvider* data_provider() const {
109 return ImportedMediaGalleryRegistry::ITunesDataProvider();
112 const base::FilePath& library_dir() const {
113 return library_dir_.path();
116 base::FilePath XmlFile() const {
117 return library_dir_.path().AppendASCII("library.xml");
120 void ExpectTrackLocation(const std::string& artist, const std::string& album,
121 const std::string& track_name) {
122 base::FilePath track =
123 library_dir().AppendASCII(track_name).NormalizePathSeparators();
124 EXPECT_EQ(track.value(),
125 data_provider()->GetTrackLocation(
126 artist, album, track_name).NormalizePathSeparators().value());
129 void ExpectNoTrack(const std::string& artist, const std::string& album,
130 const std::string& track_name) {
131 EXPECT_TRUE(data_provider()->GetTrackLocation(
132 artist, album, track_name).empty()) << track_name;
136 // Get the initial set of library entries, called by SetUp. If no entries
137 // are returned the xml file is not created.
138 virtual std::vector<LibraryEntry> SetUpLibrary() {
139 return std::vector<LibraryEntry>();
142 // Start the test. The data provider is refreshed before calling StartTest
143 // and the result of the refresh is passed in.
144 virtual void StartTest(bool parse_success) = 0;
146 void TestDone() {
147 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
148 ImportedMediaGalleryRegistry* imported_registry =
149 ImportedMediaGalleryRegistry::GetInstance();
150 imported_registry->itunes_data_provider_.reset();
151 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
152 quit_closure_);
155 private:
156 void StartTestOnMediaTaskRunner() {
157 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
158 ImportedMediaGalleryRegistry* imported_registry =
159 ImportedMediaGalleryRegistry::GetInstance();
160 imported_registry->itunes_data_provider_.reset(
161 new TestITunesDataProvider(
162 XmlFile(),
163 base::Bind(&ITunesDataProviderTest::OnLibraryChanged,
164 base::Unretained(this))));
165 data_provider()->RefreshData(base::Bind(&ITunesDataProviderTest::StartTest,
166 base::Unretained(this)));
169 void OnLibraryChanged() {
170 DCHECK(MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread());
171 if (!library_changed_callback_.is_null()) {
172 library_changed_callback_.Run();
173 library_changed_callback_.Reset();
177 void WriteLibraryInternal(const std::vector<LibraryEntry>& entries) {
178 if (!entries.size())
179 return;
180 std::string xml = "<plist><dict><key>Tracks</key><dict>\n";
181 for (size_t i = 0; i < entries.size(); ++i) {
182 std::string separator;
183 #if defined(OS_WIN)
184 separator = "/";
185 #endif
186 GURL location("file://localhost" + separator +
187 entries[i].location.AsUTF8Unsafe());
188 std::string entry_string = base::StringPrintf(
189 "<key>%" PRIuS "</key><dict>\n"
190 " <key>Track ID</key><integer>%" PRIuS "</integer>\n"
191 " <key>Location</key><string>%s</string>\n"
192 " <key>Artist</key><string>%s</string>\n"
193 " <key>Album</key><string>%s</string>\n"
194 "</dict>\n",
195 i + 1, i + 1, location.spec().c_str(), entries[i].artist.c_str(),
196 entries[i].album.c_str());
197 xml += entry_string;
199 xml += "</dict></dict></plist>\n";
200 ASSERT_EQ(static_cast<int>(xml.size()),
201 base::WriteFile(XmlFile(), xml.c_str(), xml.size()));
204 base::ScopedTempDir library_dir_;
206 base::Closure library_changed_callback_;
208 base::Closure quit_closure_;
210 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderTest);
213 class ITunesDataProviderBasicTest : public ITunesDataProviderTest {
214 public:
215 ITunesDataProviderBasicTest() {}
217 std::vector<LibraryEntry> SetUpLibrary() override {
218 base::FilePath track = library_dir().AppendASCII("Track.mp3");
219 std::vector<LibraryEntry> entries;
220 entries.push_back(LibraryEntry("Artist", "Album", track));
221 return entries;
224 void StartTest(bool parse_success) override {
225 EXPECT_TRUE(parse_success);
227 // KnownArtist
228 EXPECT_TRUE(data_provider()->KnownArtist("Artist"));
229 EXPECT_FALSE(data_provider()->KnownArtist("Artist2"));
231 // KnownAlbum
232 EXPECT_TRUE(data_provider()->KnownAlbum("Artist", "Album"));
233 EXPECT_FALSE(data_provider()->KnownAlbum("Artist", "Album2"));
234 EXPECT_FALSE(data_provider()->KnownAlbum("Artist2", "Album"));
236 // GetTrackLocation
237 ExpectTrackLocation("Artist", "Album", "Track.mp3");
238 ExpectNoTrack("Artist", "Album", "Track2.mp3");
239 ExpectNoTrack("Artist", "Album2", "Track.mp3");
240 ExpectNoTrack("Artist2", "Album", "Track.mp3");
242 // GetArtistNames
243 std::set<ITunesDataProvider::ArtistName> artists =
244 data_provider()->GetArtistNames();
245 ASSERT_EQ(1U, artists.size());
246 EXPECT_EQ("Artist", *artists.begin());
248 // GetAlbumNames
249 std::set<ITunesDataProvider::AlbumName> albums =
250 data_provider()->GetAlbumNames("Artist");
251 ASSERT_EQ(1U, albums.size());
252 EXPECT_EQ("Album", *albums.begin());
254 albums = data_provider()->GetAlbumNames("Artist2");
255 EXPECT_EQ(0U, albums.size());
257 // GetAlbum
258 base::FilePath track =
259 library_dir().AppendASCII("Track.mp3").NormalizePathSeparators();
260 ITunesDataProvider::Album album =
261 data_provider()->GetAlbum("Artist", "Album");
262 ASSERT_EQ(1U, album.size());
263 EXPECT_EQ(track.BaseName().AsUTF8Unsafe(), album.begin()->first);
264 EXPECT_EQ(track.value(),
265 album.begin()->second.NormalizePathSeparators().value());
267 album = data_provider()->GetAlbum("Artist", "Album2");
268 EXPECT_EQ(0U, album.size());
270 album = data_provider()->GetAlbum("Artist2", "Album");
271 EXPECT_EQ(0U, album.size());
273 TestDone();
276 private:
277 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderBasicTest);
280 class ITunesDataProviderRefreshTest : public ITunesDataProviderTest {
281 public:
282 ITunesDataProviderRefreshTest() {}
284 std::vector<LibraryEntry> SetUpLibrary() override {
285 base::FilePath track = library_dir().AppendASCII("Track.mp3");
286 std::vector<LibraryEntry> entries;
287 entries.push_back(LibraryEntry("Artist", "Album", track));
288 return entries;
291 void StartTest(bool parse_success) override {
292 EXPECT_TRUE(parse_success);
294 // Initial contents.
295 ExpectTrackLocation("Artist", "Album", "Track.mp3");
296 ExpectNoTrack("Artist2", "Album2", "Track2.mp3");
298 // New file.
299 base::FilePath track2 = library_dir().AppendASCII("Track2.mp3");
300 std::vector<LibraryEntry> entries;
301 entries.push_back(LibraryEntry("Artist2", "Album2", track2));
302 WriteLibrary(entries,
303 base::Bind(&ITunesDataProviderRefreshTest::CheckAfterWrite,
304 base::Unretained(this)));
307 void CheckAfterWrite() {
308 // Content the same.
309 ExpectTrackLocation("Artist", "Album", "Track.mp3");
310 ExpectNoTrack("Artist2", "Album2", "Track2.mp3");
312 data_provider()->RefreshData(
313 base::Bind(&ITunesDataProviderRefreshTest::CheckRefresh,
314 base::Unretained(this)));
317 void CheckRefresh(bool is_valid) {
318 EXPECT_TRUE(is_valid);
320 ExpectTrackLocation("Artist2", "Album2", "Track2.mp3");
321 ExpectNoTrack("Artist", "Album", "Track.mp3");
322 TestDone();
325 private:
326 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderRefreshTest);
329 class ITunesDataProviderInvalidTest : public ITunesDataProviderTest {
330 public:
331 ITunesDataProviderInvalidTest() {}
333 std::vector<LibraryEntry> SetUpLibrary() override {
334 base::FilePath track = library_dir().AppendASCII("Track.mp3");
335 std::vector<LibraryEntry> entries;
336 entries.push_back(LibraryEntry("Artist", "Album", track));
337 return entries;
340 void StartTest(bool parse_success) override {
341 EXPECT_TRUE(parse_success);
343 SetLibraryChangeCallback(
344 base::Bind(&ITunesDataProvider::RefreshData,
345 base::Unretained(data_provider()),
346 base::Bind(&ITunesDataProviderInvalidTest::CheckInvalid,
347 base::Unretained(this))));
348 ASSERT_EQ(1L, base::WriteFile(XmlFile(), " ", 1));
351 void CheckInvalid(bool is_valid) {
352 EXPECT_FALSE(is_valid);
353 TestDone();
356 private:
357 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderInvalidTest);
360 class ITunesDataProviderUniqueNameTest : public ITunesDataProviderTest {
361 public:
362 ITunesDataProviderUniqueNameTest() {}
364 std::vector<LibraryEntry> SetUpLibrary() override {
365 base::FilePath track = library_dir().AppendASCII("Track.mp3");
366 std::vector<LibraryEntry> entries;
367 // Dupe album names should get uniquified with the track id, which in the
368 // test framework is the vector index.
369 entries.push_back(LibraryEntry("Artist", "Album", track));
370 entries.push_back(LibraryEntry("Artist", "Album", track));
371 entries.push_back(LibraryEntry("Artist", "Album2", track));
372 return entries;
375 void StartTest(bool parse_success) override {
376 EXPECT_TRUE(parse_success);
378 base::FilePath track =
379 library_dir().AppendASCII("Track.mp3").NormalizePathSeparators();
380 EXPECT_EQ(track.value(),
381 data_provider()->GetTrackLocation(
382 "Artist", "Album",
383 "Track (1).mp3").NormalizePathSeparators().value());
384 EXPECT_EQ(track.value(),
385 data_provider()->GetTrackLocation(
386 "Artist", "Album",
387 "Track (2).mp3").NormalizePathSeparators().value());
388 EXPECT_EQ(track.value(),
389 data_provider()->GetTrackLocation(
390 "Artist", "Album2",
391 "Track.mp3").NormalizePathSeparators().value());
393 TestDone();
396 private:
397 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderUniqueNameTest);
400 class ITunesDataProviderEscapeTest : public ITunesDataProviderTest {
401 // Albums and tracks that aren't the same, but become the same after
402 // replacing bad characters are not handled properly, but that case should
403 // never happen in practice.
404 public:
405 ITunesDataProviderEscapeTest() {}
407 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 entries.push_back(LibraryEntry(kDeNormalizedName, kNormalizedName, track));
414 return entries;
417 void StartTest(bool parse_success) override {
418 EXPECT_TRUE(parse_success);
420 base::FilePath track =
421 library_dir().AppendASCII("Track:1.mp3").NormalizePathSeparators();
422 EXPECT_EQ(track.value(),
423 data_provider()->GetTrackLocation(
424 "Artist__name", "Album_name_",
425 "Track_1.mp3").NormalizePathSeparators().value());
426 EXPECT_EQ(track.value(),
427 data_provider()->GetTrackLocation(
428 "Artist_name", "Album_name",
429 "Track_1 (2).mp3").NormalizePathSeparators().value());
430 EXPECT_EQ(track.value(),
431 data_provider()->GetTrackLocation(
432 "Artist_name", "Album_name",
433 "Track_1 (3).mp3").NormalizePathSeparators().value());
434 EXPECT_EQ(track.value(),
435 data_provider()->GetTrackLocation(
436 kNormalizedName, kNormalizedName,
437 "Track_1.mp3").NormalizePathSeparators().value());
439 TestDone();
442 private:
443 DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderEscapeTest);
446 IN_PROC_BROWSER_TEST_F(ITunesDataProviderBasicTest, BasicTest) {
447 RunTest();
450 IN_PROC_BROWSER_TEST_F(ITunesDataProviderRefreshTest, RefreshTest) {
451 RunTest();
454 IN_PROC_BROWSER_TEST_F(ITunesDataProviderInvalidTest, InvalidTest) {
455 RunTest();
458 IN_PROC_BROWSER_TEST_F(ITunesDataProviderUniqueNameTest, UniqueNameTest) {
459 RunTest();
462 IN_PROC_BROWSER_TEST_F(ITunesDataProviderEscapeTest, EscapeTest) {
463 RunTest();
466 } // namespace itunes