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.
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/run_loop.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
18 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h"
19 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
20 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "content/public/test/test_file_system_options.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "webkit/browser/fileapi/async_file_util.h"
26 #include "webkit/browser/fileapi/external_mount_points.h"
27 #include "webkit/browser/fileapi/file_system_context.h"
28 #include "webkit/browser/fileapi/file_system_operation_context.h"
29 #include "webkit/browser/fileapi/file_system_operation_runner.h"
30 #include "webkit/browser/quota/mock_special_storage_policy.h"
32 using fileapi::FileSystemOperationContext;
33 using fileapi::FileSystemOperation;
34 using fileapi::FileSystemURL;
40 void ReadDirectoryTestHelperCallback(
41 base::RunLoop* run_loop,
42 FileSystemOperation::FileEntryList* contents,
44 base::File::Error error,
45 const FileSystemOperation::FileEntryList& file_list,
48 *completed = !has_more && error == base::File::FILE_OK;
49 *contents = file_list;
53 void ReadDirectoryTestHelper(fileapi::FileSystemOperationRunner* runner,
54 const FileSystemURL& url,
55 FileSystemOperation::FileEntryList* contents,
59 base::RunLoop run_loop;
60 runner->ReadDirectory(
61 url, base::Bind(&ReadDirectoryTestHelperCallback, &run_loop, contents,
68 class TestIPhotoDataProvider : public IPhotoDataProvider {
70 explicit TestIPhotoDataProvider(const base::FilePath& fake_library_path)
71 : IPhotoDataProvider(fake_library_path) {
72 EXPECT_TRUE(fake_auto_add_dir_.CreateUniqueTempDir());
75 virtual ~TestIPhotoDataProvider() {}
77 virtual void RefreshData(const ReadyCallback& ready_callback) OVERRIDE {
78 ready_callback.Run(true /* success */);
81 virtual std::vector<std::string> GetAlbumNames() const OVERRIDE {
82 std::vector<std::string> names;
83 names.push_back("Album1");
84 names.push_back("has_originals");
88 virtual std::map<std::string, base::FilePath> GetAlbumContents(
89 const std::string& album) const OVERRIDE {
90 std::map<std::string, base::FilePath> contents;
91 contents["a.jpg"] = library_path().AppendASCII("a.jpg");
95 virtual base::FilePath GetPhotoLocationInAlbum(
96 const std::string& album,
97 const std::string& filename) const OVERRIDE {
98 return library_path().AppendASCII("a.jpg");
101 virtual bool HasOriginals(const std::string& album) const OVERRIDE {
102 return (album == "has_originals");
105 virtual std::map<std::string, base::FilePath> GetOriginals(
106 const std::string& album) const OVERRIDE {
107 std::map<std::string, base::FilePath> contents;
108 contents["a.jpg"] = library_path().AppendASCII("orig.jpg");
112 virtual base::FilePath GetOriginalPhotoLocation(
113 const std::string& album,
114 const std::string& filename) const OVERRIDE {
115 return library_path().AppendASCII("orig.jpg");
119 base::ScopedTempDir fake_auto_add_dir_;
122 class TestIPhotoFileUtil : public IPhotoFileUtil {
124 explicit TestIPhotoFileUtil(MediaPathFilter* media_path_filter,
125 IPhotoDataProvider* data_provider)
126 : IPhotoFileUtil(media_path_filter),
127 data_provider_(data_provider) {
129 virtual ~TestIPhotoFileUtil() {}
132 virtual IPhotoDataProvider* GetDataProvider() OVERRIDE {
133 return data_provider_;
136 IPhotoDataProvider* data_provider_;
139 class TestMediaFileSystemBackend : public MediaFileSystemBackend {
141 TestMediaFileSystemBackend(const base::FilePath& profile_path,
142 IPhotoFileUtil* iphoto_file_util)
143 : MediaFileSystemBackend(
145 MediaFileSystemBackend::MediaTaskRunner().get()),
146 test_file_util_(iphoto_file_util) {}
148 virtual fileapi::AsyncFileUtil*
149 GetAsyncFileUtil(fileapi::FileSystemType type) OVERRIDE {
150 if (type != fileapi::kFileSystemTypeIphoto)
153 return test_file_util_.get();
157 scoped_ptr<fileapi::AsyncFileUtil> test_file_util_;
160 class IPhotoFileUtilTest : public testing::Test {
163 : io_thread_(content::BrowserThread::IO, &message_loop_) {
165 virtual ~IPhotoFileUtilTest() {}
167 void SetUpDataProvider() {
168 ASSERT_TRUE(fake_library_dir_.CreateUniqueTempDir());
172 fake_library_dir_.path().AppendASCII("a.jpg"),
178 fake_library_dir_.path().AppendASCII("orig.jpg"),
182 iphoto_data_provider_.reset(
183 new TestIPhotoDataProvider(fake_library_dir_.path()));
186 virtual void SetUp() OVERRIDE {
187 ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
189 scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
190 new quota::MockSpecialStoragePolicy();
192 // Initialize fake IPhotoDataProvider on media task runner thread.
193 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
195 base::Bind(&IPhotoFileUtilTest::SetUpDataProvider,
196 base::Unretained(this)));
197 base::WaitableEvent event(true, false /* initially_signalled */);
198 MediaFileSystemBackend::MediaTaskRunner()->PostTask(
200 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
203 media_path_filter_.reset(new MediaPathFilter());
204 ScopedVector<fileapi::FileSystemBackend> additional_providers;
205 additional_providers.push_back(new TestMediaFileSystemBackend(
207 new TestIPhotoFileUtil(media_path_filter_.get(),
208 iphoto_data_provider_.get())));
210 file_system_context_ = new fileapi::FileSystemContext(
211 base::MessageLoopProxy::current().get(),
212 base::MessageLoopProxy::current().get(),
213 fileapi::ExternalMountPoints::CreateRefCounted().get(),
214 storage_policy.get(),
216 additional_providers.Pass(),
217 std::vector<fileapi::URLRequestAutoMountHandler>(),
219 content::CreateAllowFileAccessOptions());
223 void TestNonexistentFolder(const std::string& path_append) {
224 FileSystemOperation::FileEntryList contents;
225 FileSystemURL url = CreateURL(path_append);
226 bool completed = false;
227 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
229 ASSERT_FALSE(completed);
232 FileSystemURL CreateURL(const std::string& virtual_path) const {
233 return file_system_context_->CreateCrackedFileSystemURL(
234 GURL("http://www.example.com"), fileapi::kFileSystemTypeIphoto,
235 base::FilePath::FromUTF8Unsafe(virtual_path));
238 fileapi::FileSystemOperationRunner* operation_runner() const {
239 return file_system_context_->operation_runner();
242 scoped_refptr<fileapi::FileSystemContext> file_system_context() const {
243 return file_system_context_;
246 TestIPhotoDataProvider* data_provider() const {
247 return iphoto_data_provider_.get();
251 base::MessageLoop message_loop_;
252 content::TestBrowserThread io_thread_;
254 base::ScopedTempDir profile_dir_;
255 base::ScopedTempDir fake_library_dir_;
257 scoped_refptr<fileapi::FileSystemContext> file_system_context_;
258 scoped_ptr<MediaPathFilter> media_path_filter_;
259 scoped_ptr<TestIPhotoDataProvider> iphoto_data_provider_;
261 DISALLOW_COPY_AND_ASSIGN(IPhotoFileUtilTest);
264 TEST_F(IPhotoFileUtilTest, RootContents) {
265 FileSystemOperation::FileEntryList contents;
266 FileSystemURL url = CreateURL("");
267 bool completed = false;
268 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
270 ASSERT_TRUE(completed);
271 ASSERT_EQ(1u, contents.size());
273 EXPECT_TRUE(contents.front().is_directory);
275 EXPECT_EQ(base::FilePath::FromUTF8Unsafe(kIPhotoAlbumsDir).value(),
276 contents.back().name);
279 TEST_F(IPhotoFileUtilTest, AlbumsDirectoryContents) {
280 FileSystemOperation::FileEntryList contents;
281 FileSystemURL url = CreateURL(kIPhotoAlbumsDir);
282 bool completed = false;
283 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
285 ASSERT_TRUE(completed);
286 ASSERT_EQ(2u, contents.size());
288 EXPECT_TRUE(contents.front().is_directory);
290 EXPECT_EQ("Album1", contents.front().name);
291 EXPECT_EQ("has_originals", contents.back().name);
294 TEST_F(IPhotoFileUtilTest, AlbumContents) {
295 FileSystemOperation::FileEntryList contents;
296 FileSystemURL url = CreateURL(std::string(kIPhotoAlbumsDir) + "/Album1");
297 bool completed = false;
298 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
300 ASSERT_TRUE(completed);
301 ASSERT_EQ(1u, contents.size());
303 EXPECT_FALSE(contents.front().is_directory);
305 EXPECT_EQ("a.jpg", contents.back().name);
308 TEST_F(IPhotoFileUtilTest, BadAccess) {
309 FileSystemOperation::FileEntryList contents;
310 FileSystemURL url = CreateURL("None");
311 bool completed = false;
312 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
313 ASSERT_FALSE(completed);
314 ASSERT_EQ(0u, contents.size());
316 url = CreateURL(std::string(kIPhotoAlbumsDir) + "/NoAlbum");
318 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
319 ASSERT_FALSE(completed);
320 ASSERT_EQ(0u, contents.size());
323 TEST_F(IPhotoFileUtilTest, Originals) {
324 FileSystemOperation::FileEntryList contents;
326 CreateURL(std::string(kIPhotoAlbumsDir) + "/has_originals");
327 bool completed = false;
328 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
330 ASSERT_TRUE(completed);
331 ASSERT_EQ(2u, contents.size());
332 EXPECT_TRUE(contents.front().is_directory);
333 EXPECT_EQ("Originals", contents.front().name);
334 EXPECT_FALSE(contents.back().is_directory);
335 EXPECT_EQ("a.jpg", contents.back().name);
337 url = CreateURL(std::string(kIPhotoAlbumsDir) + "/has_originals/Originals");
339 ReadDirectoryTestHelper(operation_runner(), url, &contents, &completed);
340 ASSERT_TRUE(completed);
341 ASSERT_EQ(1u, contents.size());
343 EXPECT_FALSE(contents.front().is_directory);
344 EXPECT_EQ("a.jpg", contents.front().name);
347 } // namespace iphoto