diff --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h --- a/libcxx/test/support/filesystem_test_helper.h +++ b/libcxx/test/support/filesystem_test_helper.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "make_string.h" #include "test_macros.h" @@ -30,6 +31,27 @@ # include #endif +#if !defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) +namespace random_utils { +inline char to_hex(int ch) { + return ch < 10 ? static_cast('0' + ch) + : static_cast('a' + (ch - 10)); +} + +inline char random_hex_char() { + static std::mt19937 rd{std::random_device{}()}; + static std::uniform_int_distribution mrand{0, 15}; + return to_hex(mrand(rd)); +} +std::string random_string(int n) { + std::string ret; + for (int i = 0; i < n; i++) + ret.push_back(random_hex_char()); + return ret; +} +} // end namespace random_utils +#endif + namespace utils { #ifdef _WIN32 inline int mkdir(const char* path, int mode) { (void)mode; return ::_mkdir(path); } @@ -292,14 +314,16 @@ private: // This could potentially introduce a filesystem race if multiple - // scoped_test_envs were created concurrently in the same test (hence - // sharing the same cwd). However, it is fairly unlikely to happen as - // we generally don't use scoped_test_env from multiple threads, so - // this is deemed acceptable. + // scoped_test_envs were created concurrently in the same test or if + // multiple tests with the same file name run concurrently. If a random + // device is available, append a short random string. static inline fs::path available_cwd_path() { fs::path const cwd = utils::getcwd(); fs::path const tmp = fs::temp_directory_path(); std::string base = cwd.filename().string(); +#if !defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) + base += "-" + random_utils::random_string(4); +#endif int i = 0; fs::path p = tmp / (base + "-static_env." + std::to_string(i)); while (utils::exists(p.string())) {