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.
PathExists(const string & path)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.
PopulateDirectoryWithFiles(const string & dir,int num_files)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.
TEST(ScopedTempPathTest,OneFile)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.
TEST(ScopedTempPathTest,CustomFileTemplate)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.
TEST(ScopedTempPathTest,MultipleFiles)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.
TEST(ScopedTempPathTest,OneEmptyDir)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.
TEST(ScopedTempPathTest,CustomDirTemplate)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.
TEST(ScopedTempPathTest,MultipleEmptyDirs)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.
TEST(ScopedTempPathTest,OneNonEmptyDir)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.
TEST(ScopedTempPathTest,MultipleNonEmptyDirs)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