// Copyright (c) 2012 The Chromium OS 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 "scoped_temp_path.h"
#include <string.h> // for strlen.
#include <sys/stat.h>
#include <vector>
#include "base/logging.h"
#include "compat/string.h"
#include "compat/test.h"
namespace {
// For testing the creation of multiple temp paths.
const int kNumMultiplePaths = 32;
// When testing non-empty directories, populate them with this many files.
const int kNumFilesPerNonEmptyDirectory = 10;
// The length of the path template suffix used internally by ScopedTempPath and
// derived classes.
const size_t kTemplateSuffixSize = strlen("XXXXXX");
// Temporary paths use this prefix by default. Copied from scoped_temp_path.cc.
const char kTempPathTemplatePrefix[] = "/tmp/quipper.";
// Tests if |path| exists on the file system.
bool PathExists(const string& path) {
struct stat buf;
// stat() returns 0 on success, i.e. if the path exists and is valid.
return !stat(path.c_str(), &buf);
}
// Creates some files in a directory. Returns the number of files created.
int PopulateDirectoryWithFiles(const string& dir, int num_files) {
// The last six characters of the file template must be "XXXXXX".
const char kPathTemplateSuffix[] = "/testXXXXXX";
// The string providing the path template for creating temp files must not be
// constant, so allocate some space here.
size_t buf_size = dir.size() + strlen(kPathTemplateSuffix) + 1;
char* path_template = new char[buf_size];
int num_files_created = 0;
for (int i = 0; i < num_files; ++i) {
// Construct the mutable path template.
snprintf(path_template, buf_size, "%s%s", dir.c_str(), kPathTemplateSuffix);
// Create the file and make sure it is valid.
int fd = mkstemp(path_template);
if (fd == -1) {
LOG(ERROR) << "Could not create file, errno=" << errno;
continue;
}
++num_files_created;
close(fd);
}
delete[] path_template;
return num_files_created;
}
} // namespace
namespace quipper {
// Create one file and make sure it is deleted when out of scope.
TEST(ScopedTempPathTest, OneFile) {
string path;
{
ScopedTempFile temp_file;
path = temp_file.path();
EXPECT_TRUE(PathExists(path)) << path;
EXPECT_EQ(strlen(kTempPathTemplatePrefix) + kTemplateSuffixSize,
path.size());
EXPECT_EQ(kTempPathTemplatePrefix,
path.substr(0, strlen(kTempPathTemplatePrefix)));
}
EXPECT_FALSE(PathExists(path)) << path;
}
// Create a file with a custom template filename.
TEST(ScopedTempPathTest, CustomFileTemplate) {
string path;
{
const string prefix = "/tmp/foobar.";
ScopedTempFile temp_file(prefix);
path = temp_file.path();
EXPECT_TRUE(PathExists(path)) << path;
EXPECT_EQ(prefix.size() + kTemplateSuffixSize, path.size());
EXPECT_EQ(prefix, path.substr(0, prefix.size()));
}
EXPECT_FALSE(PathExists(path)) << path;
}
// Create many files and make sure they are deleted when out of scope.
TEST(ScopedTempPathTest, MultipleFiles) {
std::vector<string> paths(kNumMultiplePaths);
{
std::vector<ScopedTempFile> temp_files(kNumMultiplePaths);
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
paths[i] = temp_files[i].path();
EXPECT_TRUE(PathExists(paths[i])) << paths[i];
}
}
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
EXPECT_FALSE(PathExists(paths[i])) << paths[i];
}
}
// Create one empty directory and make sure it is deleted when out of scope.
TEST(ScopedTempPathTest, OneEmptyDir) {
string path;
{
ScopedTempDir temp_path;
path = temp_path.path();
EXPECT_TRUE(PathExists(path)) << path;
EXPECT_EQ('/', path.back()) << "Should append a slash";
EXPECT_EQ(strlen(kTempPathTemplatePrefix) + kTemplateSuffixSize + 1,
path.size());
EXPECT_EQ(kTempPathTemplatePrefix,
path.substr(0, strlen(kTempPathTemplatePrefix)));
}
EXPECT_FALSE(PathExists(path)) << path;
}
// Create a file with a custom template dirname.
TEST(ScopedTempPathTest, CustomDirTemplate) {
string path;
{
const string prefix = "/tmp/foobar.";
ScopedTempDir temp_path(prefix);
path = temp_path.path();
EXPECT_TRUE(PathExists(path)) << path;
EXPECT_EQ('/', path.back()) << "Should append a slash";
// Check prefix matches:
EXPECT_EQ(prefix.size() + kTemplateSuffixSize + 1, path.size());
EXPECT_EQ(prefix, path.substr(0, prefix.size()));
}
EXPECT_FALSE(PathExists(path)) << path;
}
// Create many empty directories and make sure they are deleted when out of
// scope.
TEST(ScopedTempPathTest, MultipleEmptyDirs) {
std::vector<string> paths(kNumMultiplePaths);
{
std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths);
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
paths[i] = temp_dirs[i].path();
EXPECT_TRUE(PathExists(paths[i])) << paths[i];
}
}
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
EXPECT_FALSE(PathExists(paths[i])) << paths[i];
}
}
// Create a directory with some files in it, and make sure it is deleted when
// out of scope.
TEST(ScopedTempPathTest, OneNonEmptyDir) {
string path;
{
ScopedTempDir temp_path;
path = temp_path.path();
EXPECT_TRUE(PathExists(path)) << path;
// Populate the directory with files.
EXPECT_EQ(kNumFilesPerNonEmptyDirectory,
PopulateDirectoryWithFiles(path, kNumFilesPerNonEmptyDirectory));
}
EXPECT_FALSE(PathExists(path)) << path;
}
// Create many empty directories with files in them, and make sure they are
// deleted when out of scope.
TEST(ScopedTempPathTest, MultipleNonEmptyDirs) {
std::vector<string> paths(kNumMultiplePaths);
{
std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths);
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
paths[i] = temp_dirs[i].path();
EXPECT_TRUE(PathExists(paths[i])) << paths[i];
// Populate the directory with files.
EXPECT_EQ(
kNumFilesPerNonEmptyDirectory,
PopulateDirectoryWithFiles(paths[i], kNumFilesPerNonEmptyDirectory));
}
}
for (size_t i = 0; i < kNumMultiplePaths; ++i) {
EXPECT_FALSE(PathExists(paths[i])) << paths[i];
}
}
} // namespace quipper