Home | History | Annotate | Download | only in util
      1 // Copyright (c) 2011 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 <windows.h>
      6 #include <wincrypt.h>
      7 
      8 #include "base/file_util.h"
      9 #include "base/files/scoped_temp_dir.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "chrome/installer/util/self_cleaning_temp_dir.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace {
     16 
     17 // Returns a string of 8 characters consisting of the letter 'R' followed by
     18 // seven random hex digits.
     19 std::wstring GetRandomFilename() {
     20   uint8 data[4];
     21   HCRYPTPROV crypt_ctx = NULL;
     22 
     23   // Get four bytes of randomness.  Use CAPI rather than the CRT since I've
     24   // seen the latter trivially repeat.
     25   EXPECT_NE(FALSE, CryptAcquireContext(&crypt_ctx, NULL, NULL, PROV_RSA_FULL,
     26                                         CRYPT_VERIFYCONTEXT));
     27   EXPECT_NE(FALSE, CryptGenRandom(crypt_ctx, arraysize(data), &data[0]));
     28   EXPECT_NE(FALSE, CryptReleaseContext(crypt_ctx, 0));
     29 
     30   // Hexify the value.
     31   std::string result(base::HexEncode(&data[0], arraysize(data)));
     32   EXPECT_EQ(8, result.size());
     33 
     34   // Replace the first digit with the letter 'R' (for "random", get it?).
     35   result[0] = 'R';
     36 
     37   return base::ASCIIToWide(result);
     38 }
     39 
     40 }  // namespace
     41 
     42 namespace installer {
     43 
     44 class SelfCleaningTempDirTest : public testing::Test {
     45 };
     46 
     47 // Test the implementation of GetTopDirToCreate when given the root of a
     48 // volume.
     49 TEST_F(SelfCleaningTempDirTest, TopLevel) {
     50   base::FilePath base_dir;
     51   SelfCleaningTempDir::GetTopDirToCreate(base::FilePath(L"C:\\"), &base_dir);
     52   EXPECT_TRUE(base_dir.empty());
     53 }
     54 
     55 // Test the implementation of GetTopDirToCreate when given a non-existant dir
     56 // under the root of a volume.
     57 TEST_F(SelfCleaningTempDirTest, TopLevelPlusOne) {
     58   base::FilePath base_dir;
     59   base::FilePath parent_dir(L"C:\\");
     60   parent_dir = parent_dir.Append(GetRandomFilename());
     61   SelfCleaningTempDir::GetTopDirToCreate(parent_dir, &base_dir);
     62   EXPECT_EQ(parent_dir, base_dir);
     63 }
     64 
     65 // Test that all intermediate dirs are cleaned up if they're empty when
     66 // Delete() is called.
     67 TEST_F(SelfCleaningTempDirTest, RemoveUnusedOnDelete) {
     68   // Make a directory in which we'll work.
     69   base::ScopedTempDir work_dir;
     70   EXPECT_TRUE(work_dir.CreateUniqueTempDir());
     71 
     72   // Make up some path under the temp dir.
     73   base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
     74   SelfCleaningTempDir temp_dir;
     75   EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
     76   EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
     77   EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
     78   EXPECT_TRUE(temp_dir.Delete());
     79   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
     80   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
     81   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
     82   EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
     83   EXPECT_TRUE(work_dir.Delete());
     84   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
     85 }
     86 
     87 // Test that two clients can work in the same area.
     88 TEST_F(SelfCleaningTempDirTest, TwoClients) {
     89   // Make a directory in which we'll work.
     90   base::ScopedTempDir work_dir;
     91   EXPECT_TRUE(work_dir.CreateUniqueTempDir());
     92 
     93   // Make up some path under the temp dir.
     94   base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
     95   SelfCleaningTempDir temp_dir1;
     96   SelfCleaningTempDir temp_dir2;
     97   // First client is created.
     98   EXPECT_TRUE(temp_dir1.Initialize(parent_temp_dir, L"Three"));
     99   // Second client is created in the same space.
    100   EXPECT_TRUE(temp_dir2.Initialize(parent_temp_dir, L"Three"));
    101   // Both clients are where they are expected.
    102   EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir1.path());
    103   EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir2.path());
    104   EXPECT_TRUE(base::DirectoryExists(temp_dir1.path()));
    105   EXPECT_TRUE(base::DirectoryExists(temp_dir2.path()));
    106   // Second client goes away.
    107   EXPECT_TRUE(temp_dir2.Delete());
    108   // The first is now useless.
    109   EXPECT_FALSE(base::DirectoryExists(temp_dir1.path()));
    110   // But the intermediate dirs are still present
    111   EXPECT_TRUE(base::DirectoryExists(parent_temp_dir));
    112   // Now the first goes away.
    113   EXPECT_TRUE(temp_dir1.Delete());
    114   // And cleans up after itself.
    115   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
    116   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
    117   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
    118   EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
    119   EXPECT_TRUE(work_dir.Delete());
    120   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
    121 }
    122 
    123 // Test that all intermediate dirs are cleaned up if they're empty when the
    124 // destructor is called.
    125 TEST_F(SelfCleaningTempDirTest, RemoveUnusedOnDestroy) {
    126   // Make a directory in which we'll work.
    127   base::ScopedTempDir work_dir;
    128   EXPECT_TRUE(work_dir.CreateUniqueTempDir());
    129 
    130   // Make up some path under the temp dir.
    131   base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
    132   {
    133     SelfCleaningTempDir temp_dir;
    134     EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
    135     EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
    136     EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
    137   }
    138   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
    139   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
    140   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
    141   EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
    142   EXPECT_TRUE(work_dir.Delete());
    143   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
    144 }
    145 
    146 // Test that intermediate dirs are left behind if they're not empty when the
    147 // destructor is called.
    148 TEST_F(SelfCleaningTempDirTest, LeaveUsedOnDestroy) {
    149   static const char kHiHon[] = "hi, hon";
    150 
    151   // Make a directory in which we'll work.
    152   base::ScopedTempDir work_dir;
    153   EXPECT_TRUE(work_dir.CreateUniqueTempDir());
    154 
    155   // Make up some path under the temp dir.
    156   base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
    157   {
    158     SelfCleaningTempDir temp_dir;
    159     EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
    160     EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
    161     EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
    162     // Drop a file somewhere.
    163     EXPECT_EQ(arraysize(kHiHon) - 1,
    164               base::WriteFile(parent_temp_dir.Append(GetRandomFilename()),
    165                               kHiHon, arraysize(kHiHon) - 1));
    166   }
    167   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
    168   EXPECT_TRUE(base::DirectoryExists(parent_temp_dir));
    169   EXPECT_TRUE(work_dir.Delete());
    170   EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
    171 }
    172 
    173 }  // namespace installer
    174