diff --git a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/bad_symlink b/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/bad_symlink deleted file mode 120000 --- a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/bad_symlink +++ /dev/null @@ -1 +0,0 @@ -dne \ No newline at end of file diff --git a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 b/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 deleted file mode 120000 --- a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 +++ /dev/null @@ -1 +0,0 @@ -dir3 \ No newline at end of file diff --git a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_dir b/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_dir deleted file mode 120000 --- a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_dir +++ /dev/null @@ -1 +0,0 @@ -dir1 \ No newline at end of file diff --git a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_empty_file b/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_empty_file deleted file mode 120000 --- a/libcxx/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_empty_file +++ /dev/null @@ -1 +0,0 @@ -empty_file \ No newline at end of file diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -121,6 +121,8 @@ TEST_CASE(path_ctor_dne) { using namespace fs; + static_test_env static_env; + { std::error_code ec = GetTestEC(); directory_entry ent(StaticEnv::DNE, ec); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -112,6 +112,7 @@ TEST_CASE(error_reporting) { using namespace fs; + static_test_env static_env; scoped_test_env env; const path dir = env.create_dir("dir"); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -110,6 +110,7 @@ TEST_CASE(error_reporting) { using namespace fs; + static_test_env static_env; scoped_test_env env; const path dir = env.create_dir("dir"); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -84,6 +84,7 @@ TEST_CASE(error_reporting) { using namespace fs; + static_test_env static_env; scoped_test_env env; const path dir = env.create_dir("dir"); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -60,6 +60,7 @@ TEST_CASE(test_construction_from_bad_path) { + static_test_env static_env; std::error_code ec; directory_options opts = directory_options::none; const directory_iterator endIt; @@ -169,6 +170,7 @@ TEST_CASE(test_open_on_directory_succeeds) { + static_test_env static_env; const path testDir = StaticEnv::Dir; std::set dir_contents(std::begin(StaticEnv::DirIterationList), std::end( StaticEnv::DirIterationList)); @@ -190,6 +192,7 @@ TEST_CASE(test_open_on_file_fails) { + static_test_env static_env; const path testFile = StaticEnv::File; const directory_iterator endIt{}; { @@ -225,6 +228,7 @@ TEST_CASE(test_open_on_symlink) { + static_test_env static_env; const path symlinkToDir = StaticEnv::SymlinkToDir; std::set dir_contents; for (path const& p : StaticEnv::DirIterationList) { diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -43,6 +43,7 @@ TEST_CASE(test_prefix_increment) { + static_test_env static_env; const path testDir = StaticEnv::Dir; const std::set dir_contents(std::begin(StaticEnv::RecDirIterationList), std::end( StaticEnv::RecDirIterationList)); @@ -66,6 +67,7 @@ TEST_CASE(test_postfix_increment) { + static_test_env static_env; const path testDir = StaticEnv::Dir; const std::set dir_contents(std::begin(StaticEnv::RecDirIterationList), std::end( StaticEnv::RecDirIterationList)); @@ -89,6 +91,7 @@ TEST_CASE(test_increment_method) { + static_test_env static_env; const path testDir = StaticEnv::Dir; const std::set dir_contents(std::begin(StaticEnv::RecDirIterationList), std::end( StaticEnv::RecDirIterationList)); @@ -113,6 +116,7 @@ TEST_CASE(test_follow_symlinks) { + static_test_env static_env; const path testDir = StaticEnv::Dir; auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList; diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp @@ -43,6 +43,7 @@ TEST_CASE(test_ranged_for_loop) { + static_test_env static_env; const path testDir = StaticEnv::Dir; std::set dir_contents(std::begin(StaticEnv::RecDirIterationList), std::end( StaticEnv::RecDirIterationList)); diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp @@ -47,6 +47,7 @@ // Each scope tests one of the cases. TEST_CASE(test_canonical) { + static_test_env static_env; CWDGuard guard; // has_root_name() && has_root_directory() const path Root = StaticEnv::Root; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp @@ -36,6 +36,7 @@ } TEST_CASE(equivalent_test) { + static_test_env static_env; struct TestCase { path lhs; path rhs; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -55,6 +55,7 @@ TEST_CASE(symlink_test_case) { + static_test_env static_env; const path p = StaticEnv::File; const path p2 = StaticEnv::SymlinkToFile; TEST_CHECK(file_size(p) == file_size(p2)); @@ -62,6 +63,7 @@ TEST_CASE(file_size_error_cases) { + static_test_env static_env; struct { path p; std::errc expected_err; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp @@ -69,6 +69,7 @@ TEST_CASE(static_env_test) { + static_test_env static_env; TEST_CHECK(is_directory(StaticEnv::Dir)); TEST_CHECK(is_directory(StaticEnv::SymlinkToDir)); TEST_CHECK(!is_directory(StaticEnv::File)); diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -45,6 +45,7 @@ TEST_CASE(test_is_empty_directory) { + static_test_env static_env; TEST_CHECK(!is_empty(StaticEnv::Dir)); TEST_CHECK(!is_empty(StaticEnv::SymlinkToDir)); } diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp @@ -63,6 +63,7 @@ TEST_CASE(static_env_test) { + static_test_env static_env; struct TestCase { path p; bool expect; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -350,6 +350,7 @@ TEST_CASE(read_last_write_time_static_env_test) { + static_test_env static_env; using C = file_time_type::clock; file_time_type min = file_time_type::min(); { diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp @@ -54,18 +54,21 @@ } TEST_CASE(test_signature_4) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir)); } TEST_CASE(test_signature_5) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir / "dir2/."); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir / "dir2")); } TEST_CASE(test_signature_6) { + static_test_env static_env; // FIXME? If the trailing separator occurs in a part of the path that exists, // it is omitted. Otherwise it is added to the end of the result. fs::path p(StaticEnv::SymlinkToDir / "dir2/./"); @@ -74,24 +77,28 @@ } TEST_CASE(test_signature_7) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir / "dir2/DNE/./"); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir / "dir2/DNE/")); } TEST_CASE(test_signature_8) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir / "dir2"); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir2)); } TEST_CASE(test_signature_9) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/.."); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir2 / "")); } TEST_CASE(test_signature_10) { + static_test_env static_env; fs::path p(StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2"); const fs::path output = fs::weakly_canonical(p); TEST_CHECK(output == std::string(StaticEnv::Dir2 / "DNE/DNE2")); diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp @@ -80,6 +80,8 @@ TEST_CASE(basic_space_test) { + static_test_env static_env; + // All the test cases should reside on the same filesystem and therefore // should have the same expected result. Compute this expected result // one and check that it looks semi-sane. diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp @@ -103,6 +103,7 @@ TEST_CASE(status_file_types_test) { + static_test_env static_env; scoped_test_env env; struct TestCase { path p; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp @@ -110,6 +110,7 @@ TEST_CASE(symlink_status_file_types_test) { + static_test_env static_env; scoped_test_env env; struct TestCase { path p; diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp @@ -27,6 +27,9 @@ int main(int, char**) { + + static_test_env static_env; + // clang-format off struct { std::string input; 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 @@ -3,7 +3,7 @@ #include "filesystem_include.h" -#include // for ftruncate +#include // for ftruncate, symlink, unlink #include #include // for printf @@ -105,6 +105,13 @@ makePath("dir1/dir2/symlink_to_dir3/file5"), }; +static const std::pair SymlinkList[] = { + {"dne", makePath("bad_symlink")}, + {"dir1", makePath("symlink_to_dir")}, + {"empty_file", makePath("symlink_to_empty_file")}, + {"dir3", makePath("dir1/dir2/symlink_to_dir3")} +}; + } // namespace StaticEnv namespace random_utils { @@ -121,6 +128,39 @@ } // namespace random_utils +/// A RAII object that prepares the 'static_test_env' directory for usage in +/// tests. +/// +/// Namely, it creates some symlinks that tests expect to be present. +/// We do it here instead of storing them in the repo to be +/// cross-toolchain-friendly. The primary use case for this are Windows-hosted +/// cross-toolchains. +/// Windows doesn't really have a concept of symlinks. So, when the monorepo +/// is cloned, those symlinks turn to ordinary text files. +/// If we cross-compiled libc++ for some symlink-friendly system +/// (e. g. Linux) and ran tests on the target system, some tests would fail. +/// Instead, we create symlinks here, when a test is already being executed. +class static_test_env { +public: + static_test_env() { + for (const auto *link = std::begin(StaticEnv::SymlinkList); + link != std::end(StaticEnv::SymlinkList); + ++link) { + int ret = ::symlink(link->first.c_str(), link->second.c_str()); + assert(ret == 0); + } + } + + ~static_test_env() { + for (const auto *link = std::begin(StaticEnv::SymlinkList); + link != std::end(StaticEnv::SymlinkList); + ++link) { + int ret = ::unlink(link->second.c_str()); + assert(ret == 0); + } + } +}; + struct scoped_test_env { scoped_test_env() : test_root(random_path()) {