root/chrome/installer/util/self_cleaning_temp_dir_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetRandomFilename
  2. TEST_F
  3. TEST_F
  4. TEST_F
  5. TEST_F
  6. TEST_F
  7. TEST_F

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <wincrypt.h>

#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/installer/util/self_cleaning_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// Returns a string of 8 characters consisting of the letter 'R' followed by
// seven random hex digits.
std::wstring GetRandomFilename() {
  uint8 data[4];
  HCRYPTPROV crypt_ctx = NULL;

  // Get four bytes of randomness.  Use CAPI rather than the CRT since I've
  // seen the latter trivially repeat.
  EXPECT_NE(FALSE, CryptAcquireContext(&crypt_ctx, NULL, NULL, PROV_RSA_FULL,
                                        CRYPT_VERIFYCONTEXT));
  EXPECT_NE(FALSE, CryptGenRandom(crypt_ctx, arraysize(data), &data[0]));
  EXPECT_NE(FALSE, CryptReleaseContext(crypt_ctx, 0));

  // Hexify the value.
  std::string result(base::HexEncode(&data[0], arraysize(data)));
  EXPECT_EQ(8, result.size());

  // Replace the first digit with the letter 'R' (for "random", get it?).
  result[0] = 'R';

  return base::ASCIIToWide(result);
}

}  // namespace

namespace installer {

class SelfCleaningTempDirTest : public testing::Test {
};

// Test the implementation of GetTopDirToCreate when given the root of a
// volume.
TEST_F(SelfCleaningTempDirTest, TopLevel) {
  base::FilePath base_dir;
  SelfCleaningTempDir::GetTopDirToCreate(base::FilePath(L"C:\\"), &base_dir);
  EXPECT_TRUE(base_dir.empty());
}

// Test the implementation of GetTopDirToCreate when given a non-existant dir
// under the root of a volume.
TEST_F(SelfCleaningTempDirTest, TopLevelPlusOne) {
  base::FilePath base_dir;
  base::FilePath parent_dir(L"C:\\");
  parent_dir = parent_dir.Append(GetRandomFilename());
  SelfCleaningTempDir::GetTopDirToCreate(parent_dir, &base_dir);
  EXPECT_EQ(parent_dir, base_dir);
}

// Test that all intermediate dirs are cleaned up if they're empty when
// Delete() is called.
TEST_F(SelfCleaningTempDirTest, RemoveUnusedOnDelete) {
  // Make a directory in which we'll work.
  base::ScopedTempDir work_dir;
  EXPECT_TRUE(work_dir.CreateUniqueTempDir());

  // Make up some path under the temp dir.
  base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
  SelfCleaningTempDir temp_dir;
  EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
  EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
  EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
  EXPECT_TRUE(temp_dir.Delete());
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
  EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
  EXPECT_TRUE(work_dir.Delete());
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
}

// Test that two clients can work in the same area.
TEST_F(SelfCleaningTempDirTest, TwoClients) {
  // Make a directory in which we'll work.
  base::ScopedTempDir work_dir;
  EXPECT_TRUE(work_dir.CreateUniqueTempDir());

  // Make up some path under the temp dir.
  base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
  SelfCleaningTempDir temp_dir1;
  SelfCleaningTempDir temp_dir2;
  // First client is created.
  EXPECT_TRUE(temp_dir1.Initialize(parent_temp_dir, L"Three"));
  // Second client is created in the same space.
  EXPECT_TRUE(temp_dir2.Initialize(parent_temp_dir, L"Three"));
  // Both clients are where they are expected.
  EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir1.path());
  EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir2.path());
  EXPECT_TRUE(base::DirectoryExists(temp_dir1.path()));
  EXPECT_TRUE(base::DirectoryExists(temp_dir2.path()));
  // Second client goes away.
  EXPECT_TRUE(temp_dir2.Delete());
  // The first is now useless.
  EXPECT_FALSE(base::DirectoryExists(temp_dir1.path()));
  // But the intermediate dirs are still present
  EXPECT_TRUE(base::DirectoryExists(parent_temp_dir));
  // Now the first goes away.
  EXPECT_TRUE(temp_dir1.Delete());
  // And cleans up after itself.
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
  EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
  EXPECT_TRUE(work_dir.Delete());
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
}

// Test that all intermediate dirs are cleaned up if they're empty when the
// destructor is called.
TEST_F(SelfCleaningTempDirTest, RemoveUnusedOnDestroy) {
  // Make a directory in which we'll work.
  base::ScopedTempDir work_dir;
  EXPECT_TRUE(work_dir.CreateUniqueTempDir());

  // Make up some path under the temp dir.
  base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
  {
    SelfCleaningTempDir temp_dir;
    EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
    EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
    EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
  }
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir));
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName()));
  EXPECT_TRUE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
  EXPECT_TRUE(work_dir.Delete());
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
}

// Test that intermediate dirs are left behind if they're not empty when the
// destructor is called.
TEST_F(SelfCleaningTempDirTest, LeaveUsedOnDestroy) {
  static const char kHiHon[] = "hi, hon";

  // Make a directory in which we'll work.
  base::ScopedTempDir work_dir;
  EXPECT_TRUE(work_dir.CreateUniqueTempDir());

  // Make up some path under the temp dir.
  base::FilePath parent_temp_dir(work_dir.path().Append(L"One").Append(L"Two"));
  {
    SelfCleaningTempDir temp_dir;
    EXPECT_TRUE(temp_dir.Initialize(parent_temp_dir, L"Three"));
    EXPECT_EQ(parent_temp_dir.Append(L"Three"), temp_dir.path());
    EXPECT_TRUE(base::DirectoryExists(temp_dir.path()));
    // Drop a file somewhere.
    EXPECT_EQ(arraysize(kHiHon) - 1,
              base::WriteFile(parent_temp_dir.Append(GetRandomFilename()),
                              kHiHon, arraysize(kHiHon) - 1));
  }
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.Append(L"Three")));
  EXPECT_TRUE(base::DirectoryExists(parent_temp_dir));
  EXPECT_TRUE(work_dir.Delete());
  EXPECT_FALSE(base::DirectoryExists(parent_temp_dir.DirName().DirName()));
}

}  // namespace installer

/* [<][>][^][v][top][bottom][index][help] */