itunes_file_util_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 <set> 6#include <string> 7#include <vector> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "base/file_util.h" 12#include "base/files/scoped_temp_dir.h" 13#include "base/run_loop.h" 14#include "base/synchronization/waitable_event.h" 15#include "base/time/time.h" 16#include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h" 17#include "chrome/browser/media_galleries/fileapi/itunes_file_util.h" 18#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" 19#include "chrome/browser/media_galleries/fileapi/media_path_filter.h" 20#include "content/public/browser/browser_thread.h" 21#include "content/public/test/test_browser_thread.h" 22#include "content/public/test/test_file_system_options.h" 23#include "testing/gtest/include/gtest/gtest.h" 24#include "webkit/browser/fileapi/async_file_util.h" 25#include "webkit/browser/fileapi/external_mount_points.h" 26#include "webkit/browser/fileapi/file_system_context.h" 27#include "webkit/browser/fileapi/file_system_operation_context.h" 28#include "webkit/browser/fileapi/file_system_operation_runner.h" 29#include "webkit/browser/quota/mock_special_storage_policy.h" 30 31using fileapi::FileSystemFileUtil; 32using fileapi::FileSystemOperationContext; 33using fileapi::FileSystemOperation; 34using fileapi::FileSystemURL; 35 36namespace itunes { 37 38namespace { 39 40void ReadDirectoryTestHelperCallback( 41 base::RunLoop* run_loop, 42 FileSystemOperation::FileEntryList* contents, 43 bool* completed, base::PlatformFileError error, 44 const FileSystemOperation::FileEntryList& file_list, 45 bool has_more) { 46 DCHECK(!*completed); 47 *completed = !has_more && error == base::PLATFORM_FILE_OK; 48 *contents = file_list; 49 run_loop->Quit(); 50} 51 52void ReadDirectoryTestHelper(fileapi::FileSystemOperationRunner* runner, 53 const FileSystemURL& url, 54 FileSystemOperation::FileEntryList* contents, 55 bool* completed) { 56 DCHECK(contents); 57 DCHECK(completed); 58 base::RunLoop run_loop; 59 runner->ReadDirectory( 60 url, base::Bind(&ReadDirectoryTestHelperCallback, &run_loop, contents, 61 completed)); 62 run_loop.Run(); 63} 64 65} // namespace 66 67class TestITunesDataProvider : public ITunesDataProvider { 68 public: 69 explicit TestITunesDataProvider(const base::FilePath& fake_library_path) 70 : ITunesDataProvider(fake_library_path) { 71 EXPECT_TRUE(fake_auto_add_dir_.CreateUniqueTempDir()); 72 } 73 74 virtual ~TestITunesDataProvider() {} 75 76 virtual void RefreshData(const ReadyCallback& ready_callback) OVERRIDE { 77 ready_callback.Run(true /* success */); 78 } 79 80 virtual const base::FilePath& auto_add_path() const OVERRIDE { 81 return fake_auto_add_dir_.path(); 82 } 83 84 void SetProvideAutoAddDir(bool provide_auto_add_dir) { 85 if (provide_auto_add_dir) { 86 if (!fake_auto_add_dir_.IsValid()) 87 ASSERT_TRUE(fake_auto_add_dir_.CreateUniqueTempDir()); 88 } else { 89 ASSERT_TRUE(fake_auto_add_dir_.Delete()); 90 } 91 } 92 93 private: 94 base::ScopedTempDir fake_auto_add_dir_; 95}; 96 97class TestITunesFileUtil : public ITunesFileUtil { 98 public: 99 explicit TestITunesFileUtil(MediaPathFilter* media_path_filter, 100 ITunesDataProvider* data_provider) 101 : ITunesFileUtil(media_path_filter), 102 data_provider_(data_provider) { 103 } 104 virtual ~TestITunesFileUtil() {} 105 106 private: 107 virtual ITunesDataProvider* GetDataProvider() OVERRIDE { 108 return data_provider_; 109 } 110 111 ITunesDataProvider* data_provider_; 112}; 113 114class TestMediaFileSystemBackend : public MediaFileSystemBackend { 115 public: 116 TestMediaFileSystemBackend(const base::FilePath& profile_path, 117 ITunesFileUtil* itunes_file_util) 118 : MediaFileSystemBackend( 119 profile_path, 120 MediaFileSystemBackend::MediaTaskRunner().get()), 121 test_file_util_(itunes_file_util) {} 122 123 virtual fileapi::AsyncFileUtil* 124 GetAsyncFileUtil(fileapi::FileSystemType type) OVERRIDE { 125 if (type != fileapi::kFileSystemTypeItunes) 126 return NULL; 127 128 return test_file_util_.get(); 129 } 130 131 private: 132 scoped_ptr<fileapi::AsyncFileUtil> test_file_util_; 133}; 134 135class ItunesFileUtilTest : public testing::Test { 136 public: 137 ItunesFileUtilTest() 138 : io_thread_(content::BrowserThread::IO, &message_loop_) { 139 } 140 virtual ~ItunesFileUtilTest() {} 141 142 void SetUpDataProvider() { 143 ASSERT_TRUE(fake_library_dir_.CreateUniqueTempDir()); 144 ASSERT_EQ( 145 0, 146 file_util::WriteFile( 147 fake_library_dir_.path().AppendASCII(kITunesLibraryXML), 148 NULL, 149 0)); 150 151 itunes_data_provider_.reset( 152 new TestITunesDataProvider(fake_library_dir_.path())); 153 } 154 155 virtual void SetUp() OVERRIDE { 156 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); 157 158 scoped_refptr<quota::SpecialStoragePolicy> storage_policy = 159 new quota::MockSpecialStoragePolicy(); 160 161 // Initialize fake ItunesDataProvider on media task runner thread. 162 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 163 FROM_HERE, 164 base::Bind(&ItunesFileUtilTest::SetUpDataProvider, 165 base::Unretained(this))); 166 base::WaitableEvent event(true, false /* initially_signalled */); 167 MediaFileSystemBackend::MediaTaskRunner()->PostTask( 168 FROM_HERE, 169 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); 170 event.Wait(); 171 172 media_path_filter_.reset(new MediaPathFilter()); 173 ScopedVector<fileapi::FileSystemBackend> additional_providers; 174 additional_providers.push_back(new TestMediaFileSystemBackend( 175 profile_dir_.path(), 176 new TestITunesFileUtil(media_path_filter_.get(), 177 itunes_data_provider_.get()))); 178 179 file_system_context_ = new fileapi::FileSystemContext( 180 base::MessageLoopProxy::current().get(), 181 base::MessageLoopProxy::current().get(), 182 fileapi::ExternalMountPoints::CreateRefCounted().get(), 183 storage_policy.get(), 184 NULL, 185 additional_providers.Pass(), 186 profile_dir_.path(), 187 fileapi::CreateAllowFileAccessOptions()); 188 } 189 190 protected: 191 void TestNonexistentFolder(const std::string& path_append) { 192 FileSystemOperation::FileEntryList contents; 193 FileSystemURL url = CreateURL(path_append); 194 bool completed = false; 195 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 196 197 ASSERT_FALSE(completed); 198 } 199 200 FileSystemURL CreateURL(const std::string& virtual_path) const { 201 return file_system_context_->CreateCrackedFileSystemURL( 202 GURL("http://www.example.com"), fileapi::kFileSystemTypeItunes, 203 base::FilePath::FromUTF8Unsafe(virtual_path)); 204 } 205 206 fileapi::FileSystemOperationRunner* operation_runner() const { 207 return file_system_context_->operation_runner(); 208 } 209 210 scoped_refptr<fileapi::FileSystemContext> file_system_context() const { 211 return file_system_context_; 212 } 213 214 TestITunesDataProvider* data_provider() const { 215 return itunes_data_provider_.get(); 216 } 217 218 private: 219 base::MessageLoop message_loop_; 220 content::TestBrowserThread io_thread_; 221 222 base::ScopedTempDir profile_dir_; 223 base::ScopedTempDir fake_library_dir_; 224 225 scoped_refptr<fileapi::FileSystemContext> file_system_context_; 226 scoped_ptr<MediaPathFilter> media_path_filter_; 227 scoped_ptr<TestITunesDataProvider> itunes_data_provider_; 228 229 DISALLOW_COPY_AND_ASSIGN(ItunesFileUtilTest); 230}; 231 232TEST_F(ItunesFileUtilTest, RootContents) { 233 FileSystemOperation::FileEntryList contents; 234 FileSystemURL url = CreateURL(""); 235 bool completed = false; 236 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 237 238 ASSERT_TRUE(completed); 239 ASSERT_EQ(2u, contents.size()); 240 241 EXPECT_FALSE(contents.front().is_directory); 242 EXPECT_TRUE(contents.back().is_directory); 243 244 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kITunesLibraryXML).value(), 245 contents.front().name); 246 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kITunesMediaDir).value(), 247 contents.back().name); 248} 249 250TEST_F(ItunesFileUtilTest, ItunesMediaDirectoryContentsNoAutoAdd) { 251 data_provider()->SetProvideAutoAddDir(false); 252 253 FileSystemOperation::FileEntryList contents; 254 FileSystemURL url = CreateURL(kITunesMediaDir); 255 bool completed = false; 256 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 257 258 ASSERT_TRUE(completed); 259 ASSERT_EQ(1u, contents.size()); 260 261 EXPECT_TRUE(contents.front().is_directory); 262 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kITunesMusicDir).value(), 263 contents.back().name); 264} 265 266TEST_F(ItunesFileUtilTest, ItunesMediaDirectoryContentsAutoAdd) { 267 data_provider()->SetProvideAutoAddDir(true); 268 269 FileSystemOperation::FileEntryList contents; 270 FileSystemURL url = CreateURL(kITunesMediaDir); 271 bool completed = false; 272 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 273 274 ASSERT_TRUE(completed); 275 ASSERT_EQ(2u, contents.size()); 276 277 EXPECT_TRUE(contents.front().is_directory); 278 EXPECT_TRUE(contents.back().is_directory); 279 280 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kITunesAutoAddDir).value(), 281 contents.front().name); 282 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kITunesMusicDir).value(), 283 contents.back().name); 284} 285 286TEST_F(ItunesFileUtilTest, ItunesAutoAddDirEnumerate) { 287 data_provider()->SetProvideAutoAddDir(true); 288 ASSERT_EQ(0, file_util::WriteFile( 289 data_provider()->auto_add_path().AppendASCII("baz.ogg"), NULL, 0)); 290 291 FileSystemOperation::FileEntryList contents; 292 FileSystemURL url = CreateURL( 293 std::string(kITunesMediaDir) + "/" + kITunesAutoAddDir); 294 bool completed = false; 295 296 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 297 ASSERT_TRUE(completed); 298 ASSERT_EQ(1u, contents.size()); 299 EXPECT_FALSE(contents.front().is_directory); 300 EXPECT_EQ(base::FilePath().AppendASCII("baz.ogg").value(), 301 contents.front().name); 302} 303 304TEST_F(ItunesFileUtilTest, ItunesAutoAddDirEnumerateNested) { 305 data_provider()->SetProvideAutoAddDir(true); 306 base::FilePath nested_dir = 307 data_provider()->auto_add_path().AppendASCII("foo").AppendASCII("bar"); 308 ASSERT_TRUE(file_util::CreateDirectory(nested_dir)); 309 ASSERT_EQ(0, 310 file_util::WriteFile(nested_dir.AppendASCII("baz.ogg"), NULL, 0)); 311 312 FileSystemOperation::FileEntryList contents; 313 FileSystemURL url = CreateURL( 314 std::string(kITunesMediaDir) + "/" + kITunesAutoAddDir); 315 bool completed = false; 316 317 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 318 ASSERT_TRUE(completed); 319 ASSERT_EQ(1u, contents.size()); 320 EXPECT_TRUE(contents.front().is_directory); 321 EXPECT_EQ(base::FilePath().AppendASCII("foo").value(), contents.front().name); 322 323 contents.clear(); 324 url = CreateURL( 325 std::string(kITunesMediaDir) + "/" + kITunesAutoAddDir + "/foo"); 326 completed = false; 327 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 328 ASSERT_TRUE(completed); 329 ASSERT_EQ(1u, contents.size()); 330 EXPECT_TRUE(contents.front().is_directory); 331 EXPECT_EQ(base::FilePath().AppendASCII("bar").value(), contents.front().name); 332 333 contents.clear(); 334 url = CreateURL( 335 std::string(kITunesMediaDir) + "/" + kITunesAutoAddDir + "/foo/bar"); 336 completed = false; 337 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed); 338 ASSERT_TRUE(completed); 339 ASSERT_EQ(1u, contents.size()); 340 EXPECT_FALSE(contents.front().is_directory); 341 EXPECT_EQ(base::FilePath().AppendASCII("baz.ogg").value(), 342 contents.front().name); 343} 344 345} // namespace itunes 346