Skip to content

Commit

Permalink
Defined a testing::SrcDir() function that returns the name of a direc…
Browse files Browse the repository at this point in the history
…tory

where ancillary data files can be found.

PiperOrigin-RevId: 487896836
Change-Id: Ie6b1ba734e900fa33872b63090879ee6efe33411
  • Loading branch information
Abseil Team authored and copybara-github committed Nov 11, 2022
1 parent 44c0364 commit 912db74
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 11 deletions.
11 changes: 9 additions & 2 deletions googletest/include/gtest/gtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -2201,10 +2201,17 @@ constexpr bool StaticAssertTypeEq() noexcept {
#define TEST_F(test_fixture, test_name) GTEST_TEST_F(test_fixture, test_name)
#endif

// Returns a path to temporary directory.
// Tries to determine an appropriate directory for the platform.
// Returns a path to a temporary directory, which should be writable. It is
// implementation-dependent whether or not the path is terminated by the
// directory-separator character.
GTEST_API_ std::string TempDir();

// Returns a path to a directory that contains ancillary data files that might
// be used by tests. It is implementation dependent whether or not the path is
// terminated by the directory-separator character. The directory and the files
// in it should be considered read-only.
GTEST_API_ std::string SrcDir();

#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand Down
43 changes: 34 additions & 9 deletions googletest/src/gtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6754,12 +6754,13 @@ void InitGoogleTest() {
#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
}

#if !defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
// Return value of first environment variable that is set and contains
// a non-empty string. If there are none, return the "fallback" string.
// Since we like the temporary directory to have a directory separator suffix,
// add it if not provided in the environment variable value.
static std::string GetTempDirFromEnv(
#if !defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_) || \
!defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
// Returns the value of the first environment variable that is set and contains
// a non-empty string. If there are none, returns the "fallback" string. Adds
// the director-separator character as a suffix if not provided in the
// environment variable value.
static std::string GetDirFromEnv(
std::initializer_list<const char*> environment_variables,
const char* fallback, char separator) {
for (const char* variable_name : environment_variables) {
Expand All @@ -6779,11 +6780,35 @@ std::string TempDir() {
#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
return GTEST_CUSTOM_TEMPDIR_FUNCTION_();
#elif GTEST_OS_WINDOWS || GTEST_OS_WINDOWS_MOBILE
return GetTempDirFromEnv({"TEST_TMPDIR", "TEMP"}, "\\temp\\", '\\');
return GetDirFromEnv({"TEST_TMPDIR", "TEMP"}, "\\temp\\", '\\');
#elif GTEST_OS_LINUX_ANDROID
return GetTempDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/data/local/tmp/", '/');
return GetDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/data/local/tmp/", '/');
#else
return GetTempDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/tmp/", '/');
return GetDirFromEnv({"TEST_TMPDIR", "TMPDIR"}, "/tmp/", '/');
#endif
}

This comment has been minimized.

Copy link
@StepsOnes

StepsOnes Nov 12, 2022

ЛОЛ


#if !defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
// Returns the directory path (including terminating separator) of the current
// executable as derived from argv[0].
static std::string GetCurrentExecutableDirectory() {
internal::FilePath argv_0(internal::GetArgvs()[0]);
return argv_0.RemoveFileName().string();
}
#endif

std::string SrcDir() {
#if defined(GTEST_CUSTOM_SRCDIR_FUNCTION_)
return GTEST_CUSTOM_SRCDIR_FUNCTION_();
#elif GTEST_OS_WINDOWS || GTEST_OS_WINDOWS_MOBILE
return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
'\\');
#elif GTEST_OS_LINUX_ANDROID
return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
'/');
#else
return GetDirFromEnv({"TEST_SRCDIR"}, GetCurrentExecutableDirectory().c_str(),
'/');
#endif
}

Expand Down
97 changes: 97 additions & 0 deletions googletest/test/gtest_dirs_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <sys/stat.h>

#include <cstdlib>
#include <cstring>
#include <string>

#include "gtest/gtest.h"
#include "gtest/internal/gtest-port.h"

namespace {

class SetEnv {
public:
// Sets the environment value with name `name` to `value`, unless `value` is
// nullptr, in which case it unsets it. Restores the original value on
// destruction.
SetEnv(const char* name, const char* value) : name_(name) {
const char* old_value = getenv(name);
if (old_value != nullptr) {
saved_value_ = old_value;
have_saved_value_ = true;
}
if (value == nullptr) {
GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name));
} else {
GTEST_CHECK_POSIX_SUCCESS_(setenv(name, value, 1 /*overwrite*/));
}
}

~SetEnv() {
if (have_saved_value_) {
GTEST_CHECK_POSIX_SUCCESS_(
setenv(name_.c_str(), saved_value_.c_str(), 1 /*overwrite*/));
} else {
GTEST_CHECK_POSIX_SUCCESS_(unsetenv(name_.c_str()));
}
}

private:
std::string name_;
bool have_saved_value_ = false;
std::string saved_value_;
};

class MakeTempDir {
public:
// Creates a directory with a unique name including `testname`.
// The destructor removes it.
explicit MakeTempDir(const std::string& testname) {
// mkdtemp requires that the last 6 characters of the input pattern
// are Xs, and the string is modified by replacing those characters.
std::string pattern = "/tmp/" + testname + "_XXXXXX";
GTEST_CHECK_(mkdtemp(pattern.data()) != nullptr);
dirname_ = pattern;
}

~MakeTempDir() { GTEST_CHECK_POSIX_SUCCESS_(rmdir(dirname_.c_str())); }

const char* DirName() const { return dirname_.c_str(); }

private:
std::string dirname_;
};

bool StartsWith(const std::string& str, const std::string& prefix) {
return str.substr(0, prefix.size()) == prefix;
}

TEST(TempDirTest, InEnvironment) {
// Since the test infrastructure might be verifying directory existence or
// even creating subdirectories, we need to be careful that the directories we
// specify are actually valid.
MakeTempDir temp_dir("TempDirTest_InEnvironment");
SetEnv set_env("TEST_TMPDIR", temp_dir.DirName());
EXPECT_TRUE(StartsWith(testing::TempDir(), temp_dir.DirName()));
}

TEST(TempDirTest, NotInEnvironment) {
SetEnv set_env("TEST_TMPDIR", nullptr);
EXPECT_NE(testing::TempDir(), "");
}

TEST(SrcDirTest, InEnvironment) {
// Since the test infrastructure might be verifying directory existence or
// even creating subdirectories, we need to be careful that the directories we
// specify are actually valid.
MakeTempDir temp_dir("SrcDirTest_InEnvironment");
SetEnv set_env("TEST_SRCDIR", temp_dir.DirName());
EXPECT_TRUE(StartsWith(testing::SrcDir(), temp_dir.DirName()));
}

TEST(SrcDirTest, NotInEnvironment) {
SetEnv set_env("TEST_SRCDIR", nullptr);
EXPECT_NE(testing::SrcDir(), "");
}

} // namespace

0 comments on commit 912db74

Please sign in to comment.