Chromium Code Reviews| Index: chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc |
| diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..32d62902ecdc49a1237a4d1d22971d37490bfbab |
| --- /dev/null |
| +++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc |
| @@ -0,0 +1,416 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| +#include "base/file_util.h" |
| +#include "base/files/file_path.h" |
| +#include "base/files/scoped_temp_dir.h" |
| +#include "base/logging.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop.h" |
| +#include "base/run_loop.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h" |
| +#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" |
| +#include "chrome/browser/media_galleries/imported_media_gallery_registry.h" |
| +#include "chrome/test/base/in_process_browser_test.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "url/gurl.h" |
| + |
| +using chrome::MediaFileSystemBackend; |
| + |
| +namespace itunes { |
| + |
| +namespace { |
| + |
| +struct LibraryEntry { |
| + LibraryEntry(const std::string& artist, const std::string& album, |
| + const base::FilePath& location) |
| + : artist(artist), |
| + album(album), |
| + location(location) { |
| + } |
| + std::string artist; |
| + std::string album; |
| + base::FilePath location; |
| +}; |
| + |
| +} // namespace |
| + |
| +class TestITunesDataProvider : public ITunesDataProvider { |
| + public: |
| + TestITunesDataProvider(const base::FilePath& xml_library_path, |
| + const base::Closure& callback) |
| + : ITunesDataProvider(xml_library_path), |
| + callback_(callback) { |
| + } |
| + virtual ~TestITunesDataProvider() {} |
| + |
| + private: |
| + virtual void OnLibraryChanged(const base::FilePath& path, |
| + bool error) OVERRIDE { |
| + ITunesDataProvider::OnLibraryChanged(path, error); |
| + callback_.Run(); |
| + } |
| + |
| + base::Closure callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TestITunesDataProvider); |
| +}; |
| + |
| +class ITunesDataProviderTest : public InProcessBrowserTest { |
| + public: |
|
Lei Zhang
2013/07/17 02:21:35
None of this actually needs to be public.
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + ITunesDataProviderTest() {} |
| + virtual ~ITunesDataProviderTest() {} |
| + |
| + virtual void SetUp() OVERRIDE { |
| + ASSERT_TRUE(library_dir_.CreateUniqueTempDir()); |
| + WriteLibraryInternal(SetUpLibrary()); |
| + // The ImportedMediaGalleryRegistry is created on which ever thread calls |
| + // GetInstance() first. It shouldn't matter what thread creates, however |
| + // in practice it is always created on the UI thread, so this calls |
| + // GetInstance here to mirror those real conditions. |
| + chrome::ImportedMediaGalleryRegistry::GetInstance(); |
| + InProcessBrowserTest::SetUp(); |
| + } |
| + |
| + void RunTestOnMediaTaskRunner() { |
|
Lei Zhang
2013/07/17 02:21:35
How about just RunTest(). RunTestOnMediaTaskRunner
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| + base::RunLoop loop; |
| + quit_closure_ = loop.QuitClosure(); |
| + MediaFileSystemBackend::MediaTaskRunner()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ITunesDataProviderTest::StartTestOnMediaTaskRunner, |
| + base::Unretained(this))); |
| + loop.Run(); |
| + } |
| + |
| + void WriteLibrary(const std::vector<LibraryEntry>& entries, |
| + const base::Closure& callback) { |
| + SetLibraryChangeCallback(callback); |
| + WriteLibraryInternal(entries); |
| + } |
| + |
| + void SetLibraryChangeCallback(const base::Closure& callback) { |
| + EXPECT_TRUE(library_changed_callback_.is_null()); |
| + library_changed_callback_ = callback; |
| + } |
| + |
| + ITunesDataProvider* data_provider() const { |
| + return chrome::ImportedMediaGalleryRegistry::ITunesDataProvider(); |
| + } |
| + |
| + base::FilePath library_dir() const { |
|
Lei Zhang
2013/07/17 02:21:35
This can return a const base::FilePath&
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + return library_dir_.path(); |
| + } |
| + |
| + base::FilePath XmlFile() const { |
| + return library_dir_.path().AppendASCII("library.xml"); |
| + } |
| + |
| + protected: |
| + // Get the initial set of library entries, called by SetUp. If no entries |
| + // are returned the xml file is not created. |
| + virtual std::vector<LibraryEntry> SetUpLibrary() { |
| + return std::vector<LibraryEntry>(); |
| + } |
| + |
| + // Start the test. The data provider is refreshed before calling StartTest |
| + // and the result of the refresh is passed in. |
| + virtual void StartTest(bool parse_success) = 0; |
| + |
| + void TestDone() { |
|
Lei Zhang
2013/07/17 02:21:35
make sure you are on the MTR.
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + chrome::ImportedMediaGalleryRegistry* imported_registry = |
| + chrome::ImportedMediaGalleryRegistry::GetInstance(); |
| + imported_registry->itunes_data_provider_.reset(); |
| + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| + quit_closure_); |
| + } |
| + |
| + private: |
| + void StartTestOnMediaTaskRunner() { |
|
Lei Zhang
2013/07/17 02:21:35
Check you are on the MTR.
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + chrome::ImportedMediaGalleryRegistry* imported_registry = |
| + chrome::ImportedMediaGalleryRegistry::GetInstance(); |
| + imported_registry->itunes_data_provider_.reset( |
| + new TestITunesDataProvider( |
| + XmlFile(), |
| + base::Bind(&ITunesDataProviderTest::OnLibraryChanged, |
| + base::Unretained(this)))); |
| + data_provider()->RefreshData(base::Bind(&ITunesDataProviderTest::StartTest, |
| + base::Unretained(this))); |
| + }; |
| + |
| + void OnLibraryChanged(void) { |
|
Lei Zhang
2013/07/17 02:21:35
nit: We usually don't write (void). Same on line 2
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + DCHECK( |
| + MediaFileSystemBackend::CurrentlyOnMediaTaskRunnerThread()); |
|
Lei Zhang
2013/07/17 02:21:35
nit: fits on previous line.
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + if (!library_changed_callback_.is_null()) { |
| + library_changed_callback_.Run(); |
| + library_changed_callback_.Reset(); |
| + } |
| + } |
| + |
| + void WriteLibraryInternal(const std::vector<LibraryEntry>& entries) { |
| + if (!entries.size()) |
| + return; |
| + std::string xml = "<plist><dict><key>Tracks</key><dict>\n"; |
| + for (size_t i = 0; i < entries.size(); ++i) { |
| + GURL location("file://localhost/" + entries[i].location.AsUTF8Unsafe()); |
| + // Visual studio doesn't like %zd, so cast to int instead. |
|
Lei Zhang
2013/07/17 02:21:35
Look for PRIuS in base/format_macros.h.
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + int id = static_cast<int>(i) + 1; |
| + std::string entry_string = base::StringPrintf( |
| + "<key>%d</key><dict>\n" |
| + " <key>Track ID</key><integer>%d</integer>\n" |
| + " <key>Location</key><string>%s</string>\n" |
| + " <key>Artist</key><string>%s</string>\n" |
| + " <key>Album</key><string>%s</string>\n" |
| + "</dict>\n", |
| + id, id, location.spec().c_str(), entries[i].artist.c_str(), |
| + entries[i].album.c_str()); |
| + xml += entry_string; |
| + } |
| + xml += "</dict></dict></plist>\n"; |
| + file_util::WriteFile(XmlFile(), xml.c_str(), xml.size()); |
|
Lei Zhang
2013/07/17 02:21:35
Make sure we wrote the right # of bytes. Ditto for
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + } |
| + |
| + base::ScopedTempDir library_dir_; |
| + |
| + base::Closure library_changed_callback_; |
| + |
| + base::Closure quit_closure_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderTest); |
| +}; |
| + |
| +class ITunesDataProviderBasicTest : public ITunesDataProviderTest { |
| + public: |
| + ITunesDataProviderBasicTest() {} |
| + virtual ~ITunesDataProviderBasicTest() {} |
| + |
| + virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE { |
| + base::FilePath track = library_dir().AppendASCII("Track.mp3"); |
| + std::vector<LibraryEntry> entries; |
| + entries.push_back(LibraryEntry("Artist", "Album", track)); |
| + return entries; |
| + } |
| + |
| + virtual void StartTest(bool parse_success) OVERRIDE { |
| + EXPECT_TRUE(parse_success); |
| + |
| + // KnownArtist |
| + EXPECT_TRUE(data_provider()->KnownArtist("Artist")); |
| + EXPECT_FALSE(data_provider()->KnownArtist("Artist2")); |
| + |
| + // KnownAlbum |
| + EXPECT_TRUE(data_provider()->KnownAlbum("Artist", "Album")); |
| + EXPECT_FALSE(data_provider()->KnownAlbum("Artist", "Album2")); |
| + EXPECT_FALSE(data_provider()->KnownAlbum("Artist2", "Album")); |
| + |
| + // GetTrackLocation |
| + base::FilePath track = |
| + library_dir().AppendASCII("Track.mp3").NormalizePathSeparators(); |
| + EXPECT_EQ(track.value(), |
| + data_provider()->GetTrackLocation( |
| + "Artist", "Album", |
| + "Track.mp3").NormalizePathSeparators().value()); |
| + EXPECT_TRUE(data_provider()->GetTrackLocation("Artist", "Album", |
| + "Track2.mp3").empty()); |
| + EXPECT_TRUE(data_provider()->GetTrackLocation("Artist", "Album2", |
| + "Track.mp3").empty()); |
| + EXPECT_TRUE(data_provider()->GetTrackLocation("Artist2", "Album", |
| + "Track.mp3").empty()); |
| + |
| + // GetArtistNames |
| + std::set<ITunesDataProvider::ArtistName> artists = |
| + data_provider()->GetArtistNames(); |
| + EXPECT_EQ(1U, artists.size()); |
|
Lei Zhang
2013/07/17 02:21:35
This should be an ASSERT_EQ(), otherwise the next
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + EXPECT_EQ(std::string("Artist"), *artists.begin()); |
|
Lei Zhang
2013/07/17 02:21:35
do you need the explicit std::string()? Ditto belo
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + |
| + // GetAlbumNames |
| + std::set<ITunesDataProvider::AlbumName> albums = |
| + data_provider()->GetAlbumNames("Artist"); |
| + EXPECT_EQ(1U, albums.size()); |
| + EXPECT_EQ(std::string("Album"), *albums.begin()); |
| + |
| + albums = data_provider()->GetAlbumNames("Artist2"); |
| + EXPECT_EQ(0U, albums.size()); |
| + |
| + // GetAlbum |
| + ITunesDataProvider::Album album = |
| + data_provider()->GetAlbum("Artist", "Album"); |
| + EXPECT_EQ(1U, album.size()); |
| + EXPECT_EQ(track.BaseName().AsUTF8Unsafe(), album.begin()->first); |
| + EXPECT_EQ(track.value(), |
| + album.begin()->second.NormalizePathSeparators().value()); |
| + |
| + album = data_provider()->GetAlbum("Artist", "Album2"); |
| + EXPECT_EQ(0U, album.size()); |
| + |
| + album = data_provider()->GetAlbum("Artist2", "Album"); |
| + EXPECT_EQ(0U, album.size()); |
| + |
| + TestDone(); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderBasicTest); |
| +}; |
| + |
| +class ITunesDataProviderRefreshTest : public ITunesDataProviderTest { |
| + public: |
| + ITunesDataProviderRefreshTest() {} |
| + virtual ~ITunesDataProviderRefreshTest() {} |
| + |
| + virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE { |
| + base::FilePath track = library_dir().AppendASCII("Track.mp3"); |
| + std::vector<LibraryEntry> entries; |
| + entries.push_back(LibraryEntry("Artist", "Album", track)); |
| + return entries; |
| + } |
| + |
| + virtual void StartTest(bool parse_success) OVERRIDE { |
| + EXPECT_TRUE(parse_success); |
| + |
| + // Initial contents. |
| + ExpectTrackLocation("Artist", "Album", "Track.mp3"); |
| + ExpectNoTrack("Artist2", "Album2", "Track2.mp3"); |
| + |
| + // New file. |
| + base::FilePath track2 = library_dir().AppendASCII("Track2.mp3"); |
| + std::vector<LibraryEntry> entries; |
| + entries.push_back(LibraryEntry("Artist2", "Album2", track2)); |
| + WriteLibrary(entries, |
| + base::Bind(&ITunesDataProviderRefreshTest::CheckAfterWrite, |
| + base::Unretained(this))); |
| + } |
| + |
| + void CheckAfterWrite(void) { |
| + // Content the same. |
| + ExpectTrackLocation("Artist", "Album", "Track.mp3"); |
| + ExpectNoTrack("Artist2", "Album2", "Track2.mp3"); |
| + |
| + data_provider()->RefreshData( |
| + base::Bind(&ITunesDataProviderRefreshTest::CheckRefresh, |
| + base::Unretained(this))); |
| + } |
| + |
| + void CheckRefresh(bool is_valid) { |
| + EXPECT_TRUE(is_valid); |
| + |
| + ExpectTrackLocation("Artist2", "Album2", "Track2.mp3"); |
| + ExpectNoTrack("Artist", "Album", "Track.mp3"); |
| + TestDone(); |
| + } |
| + |
| + private: |
| + void ExpectTrackLocation(const std::string& artist, const std::string& album, |
|
Lei Zhang
2013/07/17 02:21:35
If you put this and ExpectNoTrack() in ITunesDataP
vandebo (ex-Chrome)
2013/07/17 04:22:18
Done.
|
| + const std::string& track_name) { |
| + base::FilePath track = |
| + library_dir().AppendASCII(track_name).NormalizePathSeparators(); |
| + EXPECT_EQ(track.value(), |
| + data_provider()->GetTrackLocation( |
| + artist, album, track_name).NormalizePathSeparators().value()); |
| + } |
| + |
| + void ExpectNoTrack(const std::string& artist, const std::string& album, |
| + const std::string& track_name) { |
| + EXPECT_TRUE(data_provider()->GetTrackLocation( |
| + artist, album, track_name).empty()) << track_name; |
| + } |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderRefreshTest); |
| +}; |
| + |
| +class ITunesDataProviderInvalidTest : public ITunesDataProviderTest { |
| + public: |
| + ITunesDataProviderInvalidTest() {} |
| + virtual ~ITunesDataProviderInvalidTest() {} |
| + |
| + virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE { |
| + base::FilePath track = library_dir().AppendASCII("Track.mp3"); |
| + std::vector<LibraryEntry> entries; |
| + entries.push_back(LibraryEntry("Artist", "Album", track)); |
| + return entries; |
| + } |
| + |
| + virtual void StartTest(bool parse_success) OVERRIDE { |
| + EXPECT_TRUE(parse_success); |
| + |
| + SetLibraryChangeCallback( |
| + base::Bind(&ITunesDataProvider::RefreshData, |
| + base::Unretained(data_provider()), |
| + base::Bind(&ITunesDataProviderInvalidTest::CheckInvalid, |
| + base::Unretained(this)))); |
| + file_util::WriteFile(XmlFile(), " ", 1); |
| + } |
| + |
| + void CheckInvalid(bool is_valid) { |
| + EXPECT_FALSE(is_valid); |
| + TestDone(); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderInvalidTest); |
| +}; |
| + |
| +class ITunesDataProviderUniqueNameTest : public ITunesDataProviderTest { |
| + public: |
| + ITunesDataProviderUniqueNameTest() {} |
| + virtual ~ITunesDataProviderUniqueNameTest() {} |
| + |
| + virtual std::vector<LibraryEntry> SetUpLibrary() OVERRIDE { |
| + base::FilePath track = library_dir().AppendASCII("Track.mp3"); |
| + std::vector<LibraryEntry> entries; |
| + // Dupe album names should get uniquified with the track id, which in the |
| + // test framework is the vector index. |
| + entries.push_back(LibraryEntry("Artist", "Album", track)); |
| + entries.push_back(LibraryEntry("Artist", "Album", track)); |
| + entries.push_back(LibraryEntry("Artist", "Album2", track)); |
| + return entries; |
| + } |
| + |
| + virtual void StartTest(bool parse_success) OVERRIDE { |
| + EXPECT_TRUE(parse_success); |
| + |
| + base::FilePath track = |
| + library_dir().AppendASCII("Track.mp3").NormalizePathSeparators(); |
| + EXPECT_EQ(track.value(), |
| + data_provider()->GetTrackLocation( |
| + "Artist", "Album", |
| + "Track (1).mp3").NormalizePathSeparators().value()); |
| + EXPECT_EQ(track.value(), |
| + data_provider()->GetTrackLocation( |
| + "Artist", "Album", |
| + "Track (2).mp3").NormalizePathSeparators().value()); |
| + EXPECT_EQ(track.value(), |
| + data_provider()->GetTrackLocation( |
| + "Artist", "Album2", |
| + "Track.mp3").NormalizePathSeparators().value()); |
| + |
| + TestDone(); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ITunesDataProviderUniqueNameTest); |
| +}; |
| + |
| +IN_PROC_BROWSER_TEST_F(ITunesDataProviderBasicTest, BasicTest) { |
| + RunTestOnMediaTaskRunner(); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(ITunesDataProviderRefreshTest, RefreshTest) { |
| + RunTestOnMediaTaskRunner(); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(ITunesDataProviderInvalidTest, InvalidTest) { |
| + RunTestOnMediaTaskRunner(); |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(ITunesDataProviderUniqueNameTest, UniqueNameTest) { |
| + RunTestOnMediaTaskRunner(); |
| +} |
| + |
| +} // namespace itunes |