Home | History | Annotate | Download | only in quipper
      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