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
12namespace {
13
14class 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
47class 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
67bool StartsWith(const std::string& str, const std::string& prefix) {
68  return str.substr(0, prefix.size()) == prefix;
69}
70
71TEST(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
80TEST(TempDirTest, NotInEnvironment) {
81  SetEnv set_env("TEST_TMPDIR", nullptr);
82  EXPECT_NE(testing::TempDir(), "");
83}
84
85TEST(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
94TEST(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