1 // Copyright (c) 2012 The Chromium OS 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 "scoped_temp_path.h" 6 7 #include <string.h> // for strlen. 8 #include <sys/stat.h> 9 10 #include <vector> 11 12 #include "base/logging.h" 13 #include "compat/string.h" 14 #include "compat/test.h" 15 16 namespace { 17 18 // For testing the creation of multiple temp paths. 19 const int kNumMultiplePaths = 32; 20 21 // When testing non-empty directories, populate them with this many files. 22 const int kNumFilesPerNonEmptyDirectory = 10; 23 24 // The length of the path template suffix used internally by ScopedTempPath and 25 // derived classes. 26 const size_t kTemplateSuffixSize = strlen("XXXXXX"); 27 28 // Temporary paths use this prefix by default. Copied from scoped_temp_path.cc. 29 const char kTempPathTemplatePrefix[] = "/tmp/quipper."; 30 31 // Tests if |path| exists on the file system. 32 bool PathExists(const string& path) { 33 struct stat buf; 34 // stat() returns 0 on success, i.e. if the path exists and is valid. 35 return !stat(path.c_str(), &buf); 36 } 37 38 // Creates some files in a directory. Returns the number of files created. 39 int PopulateDirectoryWithFiles(const string& dir, int num_files) { 40 // The last six characters of the file template must be "XXXXXX". 41 const char kPathTemplateSuffix[] = "/testXXXXXX"; 42 43 // The string providing the path template for creating temp files must not be 44 // constant, so allocate some space here. 45 size_t buf_size = dir.size() + strlen(kPathTemplateSuffix) + 1; 46 char* path_template = new char[buf_size]; 47 48 int num_files_created = 0; 49 for (int i = 0; i < num_files; ++i) { 50 // Construct the mutable path template. 51 snprintf(path_template, buf_size, "%s%s", dir.c_str(), kPathTemplateSuffix); 52 // Create the file and make sure it is valid. 53 int fd = mkstemp(path_template); 54 if (fd == -1) { 55 LOG(ERROR) << "Could not create file, errno=" << errno; 56 continue; 57 } 58 ++num_files_created; 59 close(fd); 60 } 61 delete[] path_template; 62 63 return num_files_created; 64 } 65 66 } // namespace 67 68 namespace quipper { 69 70 // Create one file and make sure it is deleted when out of scope. 71 TEST(ScopedTempPathTest, OneFile) { 72 string path; 73 { 74 ScopedTempFile temp_file; 75 path = temp_file.path(); 76 EXPECT_TRUE(PathExists(path)) << path; 77 EXPECT_EQ(strlen(kTempPathTemplatePrefix) + kTemplateSuffixSize, 78 path.size()); 79 EXPECT_EQ(kTempPathTemplatePrefix, 80 path.substr(0, strlen(kTempPathTemplatePrefix))); 81 } 82 EXPECT_FALSE(PathExists(path)) << path; 83 } 84 85 // Create a file with a custom template filename. 86 TEST(ScopedTempPathTest, CustomFileTemplate) { 87 string path; 88 { 89 const string prefix = "/tmp/foobar."; 90 ScopedTempFile temp_file(prefix); 91 path = temp_file.path(); 92 EXPECT_TRUE(PathExists(path)) << path; 93 EXPECT_EQ(prefix.size() + kTemplateSuffixSize, path.size()); 94 EXPECT_EQ(prefix, path.substr(0, prefix.size())); 95 } 96 EXPECT_FALSE(PathExists(path)) << path; 97 } 98 99 // Create many files and make sure they are deleted when out of scope. 100 TEST(ScopedTempPathTest, MultipleFiles) { 101 std::vector<string> paths(kNumMultiplePaths); 102 { 103 std::vector<ScopedTempFile> temp_files(kNumMultiplePaths); 104 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 105 paths[i] = temp_files[i].path(); 106 EXPECT_TRUE(PathExists(paths[i])) << paths[i]; 107 } 108 } 109 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 110 EXPECT_FALSE(PathExists(paths[i])) << paths[i]; 111 } 112 } 113 114 // Create one empty directory and make sure it is deleted when out of scope. 115 TEST(ScopedTempPathTest, OneEmptyDir) { 116 string path; 117 { 118 ScopedTempDir temp_path; 119 path = temp_path.path(); 120 EXPECT_TRUE(PathExists(path)) << path; 121 EXPECT_EQ('/', path.back()) << "Should append a slash"; 122 EXPECT_EQ(strlen(kTempPathTemplatePrefix) + kTemplateSuffixSize + 1, 123 path.size()); 124 EXPECT_EQ(kTempPathTemplatePrefix, 125 path.substr(0, strlen(kTempPathTemplatePrefix))); 126 } 127 EXPECT_FALSE(PathExists(path)) << path; 128 } 129 130 // Create a file with a custom template dirname. 131 TEST(ScopedTempPathTest, CustomDirTemplate) { 132 string path; 133 { 134 const string prefix = "/tmp/foobar."; 135 ScopedTempDir temp_path(prefix); 136 path = temp_path.path(); 137 EXPECT_TRUE(PathExists(path)) << path; 138 EXPECT_EQ('/', path.back()) << "Should append a slash"; 139 // Check prefix matches: 140 EXPECT_EQ(prefix.size() + kTemplateSuffixSize + 1, path.size()); 141 EXPECT_EQ(prefix, path.substr(0, prefix.size())); 142 } 143 EXPECT_FALSE(PathExists(path)) << path; 144 } 145 146 // Create many empty directories and make sure they are deleted when out of 147 // scope. 148 TEST(ScopedTempPathTest, MultipleEmptyDirs) { 149 std::vector<string> paths(kNumMultiplePaths); 150 { 151 std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths); 152 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 153 paths[i] = temp_dirs[i].path(); 154 EXPECT_TRUE(PathExists(paths[i])) << paths[i]; 155 } 156 } 157 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 158 EXPECT_FALSE(PathExists(paths[i])) << paths[i]; 159 } 160 } 161 162 // Create a directory with some files in it, and make sure it is deleted when 163 // out of scope. 164 TEST(ScopedTempPathTest, OneNonEmptyDir) { 165 string path; 166 { 167 ScopedTempDir temp_path; 168 path = temp_path.path(); 169 EXPECT_TRUE(PathExists(path)) << path; 170 // Populate the directory with files. 171 EXPECT_EQ(kNumFilesPerNonEmptyDirectory, 172 PopulateDirectoryWithFiles(path, kNumFilesPerNonEmptyDirectory)); 173 } 174 EXPECT_FALSE(PathExists(path)) << path; 175 } 176 177 // Create many empty directories with files in them, and make sure they are 178 // deleted when out of scope. 179 TEST(ScopedTempPathTest, MultipleNonEmptyDirs) { 180 std::vector<string> paths(kNumMultiplePaths); 181 { 182 std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths); 183 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 184 paths[i] = temp_dirs[i].path(); 185 EXPECT_TRUE(PathExists(paths[i])) << paths[i]; 186 // Populate the directory with files. 187 EXPECT_EQ( 188 kNumFilesPerNonEmptyDirectory, 189 PopulateDirectoryWithFiles(paths[i], kNumFilesPerNonEmptyDirectory)); 190 } 191 } 192 for (size_t i = 0; i < kNumMultiplePaths; ++i) { 193 EXPECT_FALSE(PathExists(paths[i])) << paths[i]; 194 } 195 } 196 197 } // namespace quipper 198