1 // Copyright 2014 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 "chrome/browser/media_galleries/media_folder_finder.h"
10 #include "base/base_paths.h"
11 #include "base/bind.h"
12 #include "base/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/test/scoped_path_override.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "chrome/browser/media_galleries/media_scan_types.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
24 class MediaFolderFinderTest
: public testing::Test
{
26 MediaFolderFinderTest() {
29 virtual ~MediaFolderFinderTest() {
32 virtual void SetUp() OVERRIDE
{
33 ASSERT_TRUE(fake_dir_
.CreateUniqueTempDir());
36 virtual void TearDown() OVERRIDE
{
37 ASSERT_EQ(NULL
, media_folder_finder_
.get());
41 void CreateMediaFolderFinder(
42 const std::vector
<base::FilePath
> roots
,
43 bool expected_success
,
44 const MediaFolderFinder::MediaFolderFinderResults
& expected_results
) {
45 EXPECT_EQ(NULL
, media_folder_finder_
.get());
46 received_results_
= false;
47 expected_success_
= expected_success
;
48 expected_results_
= expected_results
;
49 media_folder_finder_
.reset(
50 new MediaFolderFinder(base::Bind(&MediaFolderFinderTest::OnGotResults
,
51 base::Unretained(this))));
52 media_folder_finder_
->SetRootsForTesting(roots
);
56 media_folder_finder_
->StartScan();
59 void DeleteMediaFolderFinder() {
60 EXPECT_TRUE(media_folder_finder_
.get() != NULL
);
61 media_folder_finder_
.reset();
64 bool received_results() const {
65 return received_results_
;
68 const base::FilePath
& fake_dir() const {
69 return fake_dir_
.path();
72 void CreateTestDir(const base::FilePath
& parent_dir
) {
73 if (parent_dir
== fake_dir())
76 ASSERT_TRUE(fake_dir().IsParent(parent_dir
));
77 ASSERT_TRUE(base::CreateDirectory(parent_dir
));
80 void CreateTestFile(const base::FilePath
& parent_dir
,
81 MediaGalleryScanFileType type
,
84 MediaFolderFinder::MediaFolderFinderResults
* results
) {
85 CreateTestDir(parent_dir
);
87 std::string extension
;
89 MediaGalleryScanResult
& result
= (*results
)[parent_dir
];
91 case MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
:
94 result
.image_count
+= count
;
96 case MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO
:
99 result
.audio_count
+= count
;
101 case MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO
:
104 result
.video_count
+= count
;
106 case MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
:
109 if (IsEmptyScanResult(result
))
110 results
->erase(parent_dir
);
119 for (size_t i
= 0; i
< count
; ++i
) {
120 base::FilePath
test_file(parent_dir
.AppendASCII("dummy." + extension
));
122 base::GetUniquePathNumber(test_file
, base::FilePath::StringType());
123 if (uniquifier
> 0) {
124 test_file
= test_file
.InsertBeforeExtensionASCII(
125 base::StringPrintf(" (%d)", uniquifier
));
126 filesize
+= uniquifier
;
129 std::string dummy_data
;
130 dummy_data
.resize(filesize
);
133 base::WriteFile(test_file
, dummy_data
.c_str(), filesize
);
134 ASSERT_GE(bytes_written
, 0);
135 ASSERT_EQ(filesize
, static_cast<size_t>(bytes_written
));
140 base::RunLoop().RunUntilIdle();
141 content::BrowserThread::GetBlockingPool()->FlushForTesting();
144 void RunLoopUntilReceivedCallback() {
145 while (!received_results())
152 const MediaFolderFinder::MediaFolderFinderResults
& results
) {
153 received_results_
= true;
154 EXPECT_EQ(expected_success_
, success
);
155 std::set
<base::FilePath
> expected_keys
=
156 GetKeysFromResults(expected_results_
);
157 ASSERT_EQ(expected_keys
, GetKeysFromResults(results
));
158 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it
=
160 it
!= results
.end(); ++it
) {
161 const base::FilePath
& folder
= it
->first
;
162 const MediaGalleryScanResult
& expected
= it
->second
;
163 const MediaGalleryScanResult
& actual
= results
.find(folder
)->second
;
164 EXPECT_EQ(expected
.image_count
, actual
.image_count
)
165 << " Image count for " << folder
.value();
166 EXPECT_EQ(expected
.audio_count
, actual
.audio_count
)
167 << " Audio count for " << folder
.value();
168 EXPECT_EQ(expected
.video_count
, actual
.video_count
)
169 << " Video count for " << folder
.value();
173 std::set
<base::FilePath
> GetKeysFromResults(
174 const MediaFolderFinder::MediaFolderFinderResults
& results
) {
175 std::set
<base::FilePath
> keys
;
176 for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it
=
178 it
!= results
.end(); ++it
) {
179 keys
.insert(it
->first
);
184 content::TestBrowserThreadBundle thread_bundle_
;
186 base::ScopedTempDir fake_dir_
;
188 scoped_ptr
<MediaFolderFinder
> media_folder_finder_
;
190 bool expected_success_
;
191 MediaFolderFinder::MediaFolderFinderResults expected_results_
;
192 bool received_results_
;
194 DISALLOW_COPY_AND_ASSIGN(MediaFolderFinderTest
);
197 TEST_F(MediaFolderFinderTest
, NoScan
) {
198 MediaFolderFinder::MediaFolderFinderResults expected_results
;
199 std::vector
<base::FilePath
> folders
;
200 folders
.push_back(fake_dir());
201 CreateMediaFolderFinder(folders
, false, expected_results
);
202 DeleteMediaFolderFinder();
203 EXPECT_TRUE(received_results());
206 TEST_F(MediaFolderFinderTest
, ScanAndCancel
) {
207 MediaFolderFinder::MediaFolderFinderResults expected_results
;
208 std::vector
<base::FilePath
> folders
;
209 folders
.push_back(fake_dir());
210 CreateMediaFolderFinder(folders
, false, expected_results
);
212 DeleteMediaFolderFinder();
214 EXPECT_TRUE(received_results());
217 TEST_F(MediaFolderFinderTest
, ScanNothing
) {
218 MediaFolderFinder::MediaFolderFinderResults expected_results
;
219 std::vector
<base::FilePath
> folders
;
220 CreateMediaFolderFinder(folders
, true, expected_results
);
222 RunLoopUntilReceivedCallback();
223 DeleteMediaFolderFinder();
226 TEST_F(MediaFolderFinderTest
, EmptyScan
) {
227 MediaFolderFinder::MediaFolderFinderResults expected_results
;
228 std::vector
<base::FilePath
> folders
;
229 folders
.push_back(fake_dir());
230 CreateMediaFolderFinder(folders
, true, expected_results
);
232 RunLoopUntilReceivedCallback();
233 DeleteMediaFolderFinder();
236 TEST_F(MediaFolderFinderTest
, ScanMediaFiles
) {
237 MediaFolderFinder::MediaFolderFinderResults expected_results
;
238 std::vector
<base::FilePath
> folders
;
239 folders
.push_back(fake_dir());
241 base::FilePath dir1
= fake_dir().AppendASCII("dir1");
242 base::FilePath dir2
= fake_dir().AppendASCII("dir2");
243 base::FilePath dir2_3
= dir2
.AppendASCII("dir2_3");
244 base::FilePath dir2_4
= dir2
.AppendASCII("dir2_4");
245 base::FilePath dir2_4_5
= dir2_4
.AppendASCII("dir2_4_5");
246 base::FilePath dir2_4_empty
= dir2_4
.AppendASCII("dir2_4_empty");
247 base::FilePath dir_empty
= fake_dir().AppendASCII("dir_empty");
249 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 2, true,
251 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, false,
253 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
, 1, false,
255 CreateTestFile(dir2_3
, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO
, 4, true,
257 CreateTestFile(dir2_3
, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO
, 3, false,
259 CreateTestFile(dir2_4
, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
, 5, false,
261 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 2, true,
263 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO
, 4, true,
265 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO
, 1, true,
267 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 5, false,
269 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO
, 3, false,
271 CreateTestFile(dir2_4_5
, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
, 3, true,
273 CreateTestDir(dir2_4_empty
);
274 CreateTestDir(dir_empty
);
276 CreateMediaFolderFinder(folders
, true, expected_results
);
278 RunLoopUntilReceivedCallback();
279 DeleteMediaFolderFinder();
282 TEST_F(MediaFolderFinderTest
, SkipHiddenFiles
) {
283 MediaFolderFinder::MediaFolderFinderResults expected_results
;
284 std::vector
<base::FilePath
> folders
;
285 folders
.push_back(fake_dir());
287 base::FilePath hidden_dir
= fake_dir().AppendASCII(".hidden");
289 CreateTestFile(hidden_dir
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 2, true,
291 expected_results
.erase(hidden_dir
);
293 CreateMediaFolderFinder(folders
, true, expected_results
);
295 RunLoopUntilReceivedCallback();
296 DeleteMediaFolderFinder();
299 TEST_F(MediaFolderFinderTest
, ScanIgnoresSmallMediaFiles
) {
300 MediaFolderFinder::MediaFolderFinderResults expected_results
;
301 std::vector
<base::FilePath
> folders
;
302 folders
.push_back(fake_dir());
304 base::FilePath dir1
= fake_dir().AppendASCII("dir1");
305 base::FilePath dir2
= fake_dir().AppendASCII("dir2");
306 base::FilePath dir_empty
= fake_dir().AppendASCII("dir_empty");
308 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 2, true,
310 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO
, 1, false,
312 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
, 1, false,
314 CreateTestFile(dir2
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, false,
316 CreateTestFile(dir2
, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO
, 3, false,
318 CreateTestFile(dir2
, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO
, 5, false,
320 CreateTestFile(dir2
, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN
, 1, true,
322 CreateTestDir(dir_empty
);
323 ASSERT_EQ(1U, expected_results
.erase(dir2
));
325 CreateMediaFolderFinder(folders
, true, expected_results
);
327 RunLoopUntilReceivedCallback();
328 DeleteMediaFolderFinder();
331 TEST_F(MediaFolderFinderTest
, Overlap
) {
332 MediaFolderFinder::MediaFolderFinderResults expected_results
;
333 std::vector
<base::FilePath
> folders
;
334 folders
.push_back(fake_dir());
335 folders
.push_back(fake_dir());
337 base::FilePath dir1
= fake_dir().AppendASCII("dir1");
338 folders
.push_back(dir1
);
339 folders
.push_back(dir1
);
341 CreateTestFile(dir1
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
344 CreateMediaFolderFinder(folders
, true, expected_results
);
346 RunLoopUntilReceivedCallback();
347 DeleteMediaFolderFinder();
350 TEST_F(MediaFolderFinderTest
, Prune
) {
351 MediaFolderFinder::MediaFolderFinderResults expected_results
;
352 std::vector
<base::FilePath
> folders
;
353 folders
.push_back(fake_dir());
356 int pruned_dir_key
= base::DIR_IE_INTERNET_CACHE
;
357 #elif defined(OS_MACOSX)
358 int pruned_dir_key
= chrome::DIR_USER_LIBRARY
;
360 int pruned_dir_key
= base::DIR_CACHE
;
363 base::FilePath fake_pruned_dir
= fake_dir().AppendASCII("dir1");
364 base::ScopedPathOverride
scoped_fake_pruned_dir_override(pruned_dir_key
,
367 CreateTestFile(fake_dir(), MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
369 CreateTestFile(fake_pruned_dir
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
372 base::FilePath test_dir
= fake_pruned_dir
.AppendASCII("dir2");
373 CreateTestFile(test_dir
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
376 // |fake_pruned_dir| and |test_dir| are pruned.
377 expected_results
.erase(fake_pruned_dir
);
378 expected_results
.erase(test_dir
);
380 CreateMediaFolderFinder(folders
, true, expected_results
);
382 RunLoopUntilReceivedCallback();
383 DeleteMediaFolderFinder();
386 TEST_F(MediaFolderFinderTest
, Graylist
) {
387 MediaFolderFinder::MediaFolderFinderResults expected_results
;
388 std::vector
<base::FilePath
> folders
;
389 folders
.push_back(fake_dir());
391 base::FilePath fake_home_dir
= fake_dir().AppendASCII("dir1");
392 base::FilePath test_dir
= fake_home_dir
.AppendASCII("dir2");
393 base::ScopedPathOverride
scoped_fake_home_dir_override(base::DIR_HOME
,
396 CreateTestFile(fake_dir(), MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
398 CreateTestFile(fake_home_dir
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
400 CreateTestFile(test_dir
, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE
, 1, true,
403 // |fake_home_dir| and its ancestors do not show up in results.
404 expected_results
.erase(fake_dir());
405 expected_results
.erase(fake_home_dir
);
407 CreateMediaFolderFinder(folders
, true, expected_results
);
409 RunLoopUntilReceivedCallback();
410 DeleteMediaFolderFinder();