Home | History | Annotate | Download | only in media_galleries
      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.
      4 
      5 #include "chrome/browser/media_galleries/media_folder_finder.h"
      6 
      7 #include <set>
      8 #include <string>
      9 
     10 #include "base/base_paths.h"
     11 #include "base/bind.h"
     12 #include "base/files/file_util.h"
     13 #include "base/files/scoped_temp_dir.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "base/test/scoped_path_override.h"
     16 #include "base/threading/sequenced_worker_pool.h"
     17 #include "chrome/browser/media_galleries/media_scan_types.h"
     18 #include "chrome/common/chrome_paths.h"
     19 #include "content/public/browser/browser_thread.h"
     20 #include "content/public/test/test_browser_thread_bundle.h"
     21 #include "content/public/test/test_utils.h"
     22 
     23 class MediaFolderFinderTest : public testing::Test {
     24  public:
     25   MediaFolderFinderTest() {
     26   }
     27 
     28   virtual ~MediaFolderFinderTest() {
     29   }
     30 
     31   virtual void SetUp() OVERRIDE {
     32     ASSERT_TRUE(fake_dir_.CreateUniqueTempDir());
     33   }
     34 
     35   virtual void TearDown() OVERRIDE {
     36     ASSERT_EQ(NULL, media_folder_finder_.get());
     37   }
     38 
     39  protected:
     40   void CreateMediaFolderFinder(
     41       const std::vector<base::FilePath> roots,
     42       bool expected_success,
     43       const MediaFolderFinder::MediaFolderFinderResults& expected_results) {
     44     EXPECT_EQ(NULL, media_folder_finder_.get());
     45     received_results_ = false;
     46     expected_success_ = expected_success;
     47     expected_results_ = expected_results;
     48     media_folder_finder_.reset(
     49         new MediaFolderFinder(base::Bind(&MediaFolderFinderTest::OnGotResults,
     50                                          base::Unretained(this))));
     51     media_folder_finder_->SetRootsForTesting(roots);
     52   }
     53 
     54   void StartScan() {
     55     media_folder_finder_->StartScan();
     56   }
     57 
     58   void DeleteMediaFolderFinder() {
     59     EXPECT_TRUE(media_folder_finder_.get() != NULL);
     60     media_folder_finder_.reset();
     61   }
     62 
     63   bool received_results() const {
     64     return received_results_;
     65   }
     66 
     67   const base::FilePath& fake_dir() const {
     68     return fake_dir_.path();
     69   }
     70 
     71   void CreateTestDir(const base::FilePath& parent_dir) {
     72     if (parent_dir == fake_dir())
     73       return;
     74 
     75     ASSERT_TRUE(fake_dir().IsParent(parent_dir));
     76     ASSERT_TRUE(base::CreateDirectory(parent_dir));
     77   }
     78 
     79   void CreateTestFile(const base::FilePath& parent_dir,
     80                       MediaGalleryScanFileType type,
     81                       size_t count,
     82                       bool big,
     83                       MediaFolderFinder::MediaFolderFinderResults* results) {
     84     CreateTestDir(parent_dir);
     85 
     86     std::string extension;
     87     size_t filesize;
     88     MediaGalleryScanResult& result = (*results)[parent_dir];
     89     switch (type) {
     90       case MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE:
     91         extension = "jpg";
     92         filesize = 10;
     93         result.image_count += count;
     94         break;
     95       case MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO:
     96         extension = "wav";
     97         filesize = 20;
     98         result.audio_count += count;
     99         break;
    100       case MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO:
    101         extension = "avi";
    102         filesize = 30;
    103         result.video_count += count;
    104         break;
    105       case MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN:
    106         extension = "txt";
    107         filesize = 10;
    108         if (IsEmptyScanResult(result))
    109           results->erase(parent_dir);
    110         break;
    111       default:
    112         NOTREACHED();
    113         return;
    114     }
    115     if (big)
    116       filesize *= 100000;
    117 
    118     for (size_t i = 0; i < count; ++i) {
    119       base::FilePath test_file(parent_dir.AppendASCII("dummy." + extension));
    120       int uniquifier =
    121           base::GetUniquePathNumber(test_file, base::FilePath::StringType());
    122       if (uniquifier > 0) {
    123         test_file = test_file.InsertBeforeExtensionASCII(
    124             base::StringPrintf(" (%d)", uniquifier));
    125         filesize += uniquifier;
    126       }
    127 
    128       std::string dummy_data;
    129       dummy_data.resize(filesize);
    130 
    131       int bytes_written =
    132           base::WriteFile(test_file, dummy_data.c_str(), filesize);
    133       ASSERT_GE(bytes_written, 0);
    134       ASSERT_EQ(filesize, static_cast<size_t>(bytes_written));
    135     }
    136   }
    137 
    138   void RunLoopUntilReceivedCallback() {
    139     while (!received_results())
    140       content::RunAllBlockingPoolTasksUntilIdle();
    141   }
    142 
    143  private:
    144   void OnGotResults(
    145       bool success,
    146       const MediaFolderFinder::MediaFolderFinderResults& results) {
    147     received_results_ = true;
    148     EXPECT_EQ(expected_success_, success);
    149     std::set<base::FilePath> expected_keys =
    150         GetKeysFromResults(expected_results_);
    151     ASSERT_EQ(expected_keys, GetKeysFromResults(results));
    152     for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it =
    153              results.begin();
    154          it != results.end(); ++it) {
    155       const base::FilePath& folder = it->first;
    156       const MediaGalleryScanResult& expected = it->second;
    157       const MediaGalleryScanResult& actual = results.find(folder)->second;
    158       EXPECT_EQ(expected.image_count, actual.image_count)
    159           << " Image count for " << folder.value();
    160       EXPECT_EQ(expected.audio_count, actual.audio_count)
    161           << " Audio count for " << folder.value();
    162       EXPECT_EQ(expected.video_count, actual.video_count)
    163           << " Video count for " << folder.value();
    164     }
    165   }
    166 
    167   std::set<base::FilePath> GetKeysFromResults(
    168       const MediaFolderFinder::MediaFolderFinderResults& results) {
    169     std::set<base::FilePath> keys;
    170     for (MediaFolderFinder::MediaFolderFinderResults::const_iterator it =
    171              results.begin();
    172          it != results.end(); ++it) {
    173       keys.insert(it->first);
    174     }
    175     return keys;
    176   }
    177 
    178   content::TestBrowserThreadBundle thread_bundle_;
    179 
    180   base::ScopedTempDir fake_dir_;
    181 
    182   scoped_ptr<MediaFolderFinder> media_folder_finder_;
    183 
    184   bool expected_success_;
    185   MediaFolderFinder::MediaFolderFinderResults expected_results_;
    186   bool received_results_;
    187 
    188   DISALLOW_COPY_AND_ASSIGN(MediaFolderFinderTest);
    189 };
    190 
    191 TEST_F(MediaFolderFinderTest, NoScan) {
    192   MediaFolderFinder::MediaFolderFinderResults expected_results;
    193   std::vector<base::FilePath> folders;
    194   folders.push_back(fake_dir());
    195   CreateMediaFolderFinder(folders, false, expected_results);
    196   DeleteMediaFolderFinder();
    197   EXPECT_TRUE(received_results());
    198 }
    199 
    200 TEST_F(MediaFolderFinderTest, ScanAndCancel) {
    201   MediaFolderFinder::MediaFolderFinderResults expected_results;
    202   std::vector<base::FilePath> folders;
    203   folders.push_back(fake_dir());
    204   CreateMediaFolderFinder(folders, false, expected_results);
    205   StartScan();
    206   DeleteMediaFolderFinder();
    207   content::RunAllBlockingPoolTasksUntilIdle();
    208   EXPECT_TRUE(received_results());
    209 }
    210 
    211 TEST_F(MediaFolderFinderTest, ScanNothing) {
    212   MediaFolderFinder::MediaFolderFinderResults expected_results;
    213   std::vector<base::FilePath> folders;
    214   CreateMediaFolderFinder(folders, true, expected_results);
    215   StartScan();
    216   RunLoopUntilReceivedCallback();
    217   DeleteMediaFolderFinder();
    218 }
    219 
    220 TEST_F(MediaFolderFinderTest, EmptyScan) {
    221   MediaFolderFinder::MediaFolderFinderResults expected_results;
    222   std::vector<base::FilePath> folders;
    223   folders.push_back(fake_dir());
    224   CreateMediaFolderFinder(folders, true, expected_results);
    225   StartScan();
    226   RunLoopUntilReceivedCallback();
    227   DeleteMediaFolderFinder();
    228 }
    229 
    230 TEST_F(MediaFolderFinderTest, ScanMediaFiles) {
    231   MediaFolderFinder::MediaFolderFinderResults expected_results;
    232   std::vector<base::FilePath> folders;
    233   folders.push_back(fake_dir());
    234 
    235   base::FilePath dir1 = fake_dir().AppendASCII("dir1");
    236   base::FilePath dir2 = fake_dir().AppendASCII("dir2");
    237   base::FilePath dir2_3 = dir2.AppendASCII("dir2_3");
    238   base::FilePath dir2_4 = dir2.AppendASCII("dir2_4");
    239   base::FilePath dir2_4_5 = dir2_4.AppendASCII("dir2_4_5");
    240   base::FilePath dir2_4_empty = dir2_4.AppendASCII("dir2_4_empty");
    241   base::FilePath dir_empty = fake_dir().AppendASCII("dir_empty");
    242 
    243   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 2, true,
    244                  &expected_results);
    245   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, false,
    246                  &expected_results);
    247   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN, 1, false,
    248                  &expected_results);
    249   CreateTestFile(dir2_3, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO, 4, true,
    250                  &expected_results);
    251   CreateTestFile(dir2_3, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO, 3, false,
    252                  &expected_results);
    253   CreateTestFile(dir2_4, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN, 5, false,
    254                  &expected_results);
    255   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 2, true,
    256                  &expected_results);
    257   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO, 4, true,
    258                  &expected_results);
    259   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO, 1, true,
    260                  &expected_results);
    261   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 5, false,
    262                  &expected_results);
    263   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO, 3, false,
    264                  &expected_results);
    265   CreateTestFile(dir2_4_5, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN, 3, true,
    266                  &expected_results);
    267   CreateTestDir(dir2_4_empty);
    268   CreateTestDir(dir_empty);
    269 
    270   CreateMediaFolderFinder(folders, true, expected_results);
    271   StartScan();
    272   RunLoopUntilReceivedCallback();
    273   DeleteMediaFolderFinder();
    274 }
    275 
    276 TEST_F(MediaFolderFinderTest, SkipHiddenFiles) {
    277   MediaFolderFinder::MediaFolderFinderResults expected_results;
    278   std::vector<base::FilePath> folders;
    279   folders.push_back(fake_dir());
    280 
    281   base::FilePath hidden_dir = fake_dir().AppendASCII(".hidden");
    282 
    283   CreateTestFile(hidden_dir, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 2, true,
    284                  &expected_results);
    285   expected_results.erase(hidden_dir);
    286 
    287   CreateMediaFolderFinder(folders, true, expected_results);
    288   StartScan();
    289   RunLoopUntilReceivedCallback();
    290   DeleteMediaFolderFinder();
    291 }
    292 
    293 TEST_F(MediaFolderFinderTest, ScanIgnoresSmallMediaFiles) {
    294   MediaFolderFinder::MediaFolderFinderResults expected_results;
    295   std::vector<base::FilePath> folders;
    296   folders.push_back(fake_dir());
    297 
    298   base::FilePath dir1 = fake_dir().AppendASCII("dir1");
    299   base::FilePath dir2 = fake_dir().AppendASCII("dir2");
    300   base::FilePath dir_empty = fake_dir().AppendASCII("dir_empty");
    301 
    302   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 2, true,
    303                  &expected_results);
    304   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO, 1, false,
    305                  &expected_results);
    306   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN, 1, false,
    307                  &expected_results);
    308   CreateTestFile(dir2, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, false,
    309                  &expected_results);
    310   CreateTestFile(dir2, MEDIA_GALLERY_SCAN_FILE_TYPE_AUDIO, 3, false,
    311                  &expected_results);
    312   CreateTestFile(dir2, MEDIA_GALLERY_SCAN_FILE_TYPE_VIDEO, 5, false,
    313                  &expected_results);
    314   CreateTestFile(dir2, MEDIA_GALLERY_SCAN_FILE_TYPE_UNKNOWN, 1, true,
    315                  &expected_results);
    316   CreateTestDir(dir_empty);
    317   ASSERT_EQ(1U, expected_results.erase(dir2));
    318 
    319   CreateMediaFolderFinder(folders, true, expected_results);
    320   StartScan();
    321   RunLoopUntilReceivedCallback();
    322   DeleteMediaFolderFinder();
    323 }
    324 
    325 TEST_F(MediaFolderFinderTest, Overlap) {
    326   MediaFolderFinder::MediaFolderFinderResults expected_results;
    327   std::vector<base::FilePath> folders;
    328   folders.push_back(fake_dir());
    329   folders.push_back(fake_dir());
    330 
    331   base::FilePath dir1 = fake_dir().AppendASCII("dir1");
    332   folders.push_back(dir1);
    333   folders.push_back(dir1);
    334 
    335   CreateTestFile(dir1, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    336                  &expected_results);
    337 
    338   CreateMediaFolderFinder(folders, true, expected_results);
    339   StartScan();
    340   RunLoopUntilReceivedCallback();
    341   DeleteMediaFolderFinder();
    342 }
    343 
    344 TEST_F(MediaFolderFinderTest, Prune) {
    345   MediaFolderFinder::MediaFolderFinderResults expected_results;
    346   std::vector<base::FilePath> folders;
    347   folders.push_back(fake_dir());
    348 
    349 #if defined(OS_WIN)
    350   int pruned_dir_key = base::DIR_IE_INTERNET_CACHE;
    351 #elif defined(OS_MACOSX)
    352   int pruned_dir_key = chrome::DIR_USER_LIBRARY;
    353 #else
    354   int pruned_dir_key = base::DIR_CACHE;
    355 #endif
    356 
    357   base::FilePath fake_pruned_dir = fake_dir().AppendASCII("dir1");
    358   base::ScopedPathOverride scoped_fake_pruned_dir_override(pruned_dir_key,
    359                                                            fake_pruned_dir);
    360 
    361   CreateTestFile(fake_dir(), MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    362                  &expected_results);
    363   CreateTestFile(fake_pruned_dir, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    364                  &expected_results);
    365 
    366   base::FilePath test_dir = fake_pruned_dir.AppendASCII("dir2");
    367   CreateTestFile(test_dir, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    368                  &expected_results);
    369 
    370   // |fake_pruned_dir| and |test_dir| are pruned.
    371   expected_results.erase(fake_pruned_dir);
    372   expected_results.erase(test_dir);
    373 
    374   CreateMediaFolderFinder(folders, true, expected_results);
    375   StartScan();
    376   RunLoopUntilReceivedCallback();
    377   DeleteMediaFolderFinder();
    378 }
    379 
    380 TEST_F(MediaFolderFinderTest, Graylist) {
    381   MediaFolderFinder::MediaFolderFinderResults expected_results;
    382   std::vector<base::FilePath> folders;
    383   folders.push_back(fake_dir());
    384 
    385   base::FilePath fake_home_dir = fake_dir().AppendASCII("dir1");
    386   base::FilePath test_dir = fake_home_dir.AppendASCII("dir2");
    387   base::ScopedPathOverride scoped_fake_home_dir_override(base::DIR_HOME,
    388                                                          fake_home_dir);
    389 
    390   CreateTestFile(fake_dir(), MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    391                  &expected_results);
    392   CreateTestFile(fake_home_dir, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    393                  &expected_results);
    394   CreateTestFile(test_dir, MEDIA_GALLERY_SCAN_FILE_TYPE_IMAGE, 1, true,
    395                  &expected_results);
    396 
    397   // |fake_home_dir| and its ancestors do not show up in results.
    398   expected_results.erase(fake_dir());
    399   expected_results.erase(fake_home_dir);
    400 
    401   CreateMediaFolderFinder(folders, true, expected_results);
    402   StartScan();
    403   RunLoopUntilReceivedCallback();
    404   DeleteMediaFolderFinder();
    405 }
    406