1 #include <sys/stat.h>
2 
3 #include <cstdlib>
4 #include <cstring>
5 #include <string>
6 
7 #include "gtest/gtest.h"
8 #include "gtest/internal/gtest-port.h"
9 
10 #if GTEST_HAS_FILE_SYSTEM
11 
12 namespace {
13 
14 class SetEnv {
15  public:
16   // Sets the environment value with name `name` to `value`, unless `value` is
17   // nullptr, in which case it unsets it. Restores the original value on
18   // destruction.
19   SetEnv(const char* name, const char* value) : name_(name) {
20     const char* old_value = getenv(name);
21     if (old_value != nullptr) {
22       saved_value_ = old_value;
23       have_saved_value_ = true;
24     }
25     if (value == nullptr) {
26       GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name));
27     } else {
28       GTEST_CHECK_POSIX_SUCCESS_(setenv(name, value, 1 /*overwrite*/));
29     }
30   }
31 
32   ~SetEnv() {
33     if (have_saved_value_) {
34       GTEST_CHECK_POSIX_SUCCESS_(
35           setenv(name_.c_str(), saved_value_.c_str(), 1 /*overwrite*/));
36     } else {
37       GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name_.c_str()));
38     }
39   }
40 
41  private:
42   std::string name_;
43   bool have_saved_value_ = false;
44   std::string saved_value_;
45 };
46 
47 class MakeTempDir {
48  public:
49   // Creates a directory with a unique name including `testname`.
50   // The destructor removes it.
51   explicit MakeTempDir(const std::string& testname) {
52     // mkdtemp requires that the last 6 characters of the input pattern
53     // are Xs, and the string is modified by replacing those characters.
54     std::string pattern = "/tmp/" + testname + "_XXXXXX";
55     GTEST_CHECK_(mkdtemp(pattern.data()) != nullptr);
56     dirname_ = pattern;
57   }
58 
59   ~MakeTempDir() { GTEST_CHECK_POSIX_SUCCESS_(rmdir(dirname_.c_str())); }
60 
61   const char* DirName() const { return dirname_.c_str(); }
62 
63  private:
64   std::string dirname_;
65 };
66 
67 bool StartsWith(const std::string& str, const std::string& prefix) {
68   return str.substr(0, prefix.size()) == prefix;
69 }
70 
71 TEST(TempDirTest, InEnvironment) {
72   // Since the test infrastructure might be verifying directory existence or
73   // even creating subdirectories, we need to be careful that the directories we
74   // specify are actually valid.
75   MakeTempDir temp_dir("TempDirTest_InEnvironment");
76   SetEnv set_env("TEST_TMPDIR", temp_dir.DirName());
77   EXPECT_TRUE(StartsWith(testing::TempDir(), temp_dir.DirName()));
78 }
79 
80 TEST(TempDirTest, NotInEnvironment) {
81   SetEnv set_env("TEST_TMPDIR", nullptr);
82   EXPECT_NE(testing::TempDir(), "");
83 }
84 
85 TEST(SrcDirTest, InEnvironment) {
86   // Since the test infrastructure might be verifying directory existence or
87   // even creating subdirectories, we need to be careful that the directories we
88   // specify are actually valid.
89   MakeTempDir temp_dir("SrcDirTest_InEnvironment");
90   SetEnv set_env("TEST_SRCDIR", temp_dir.DirName());
91   EXPECT_TRUE(StartsWith(testing::SrcDir(), temp_dir.DirName()));
92 }
93 
94 TEST(SrcDirTest, NotInEnvironment) {
95   SetEnv set_env("TEST_SRCDIR", nullptr);
96   EXPECT_NE(testing::SrcDir(), "");
97 }
98 
99 #endif  // GTEST_HAS_FILE_SYSTEM
100 
101 }  // namespace
102