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