[libc-commits] [libc] [libc][realpath][test] Create test files/directories (PR #209369)
Jackson Stogel via libc-commits
libc-commits at lists.llvm.org
Fri Jul 17 10:54:24 PDT 2026
================
@@ -12,23 +12,148 @@
//===----------------------------------------------------------------------===//
#include "hdr/errno_macros.h"
+#include "hdr/func/free.h"
#include "hdr/limits_macros.h"
#include "hdr/types/size_t.h"
#include "src/__support/CPP/string.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/CPP/utility.h"
#include "src/__support/OSUtil/path.h"
+#include "src/__support/fixedvector.h"
+#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/fcntl/openat.h"
#include "src/stdlib/realpath.h"
+#include "src/string/strdup.h"
+#include "src/sys/stat/mkdirat.h"
+#include "src/unistd/close.h"
+#include "src/unistd/getpid.h"
+#include "src/unistd/unlinkat.h"
#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
namespace cpp = LIBC_NAMESPACE::cpp;
namespace path = LIBC_NAMESPACE::path;
-using LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::FixedVector;
+using LIBC_NAMESPACE::testing::tlog;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
// This test assumes the following values, so fail early if they mismatch.
static_assert(path::SEPARATOR == '/');
static_assert(path::CURRENT_DIR_COMPONENT == ".");
static_assert(path::PARENT_DIR_COMPONENT == "..");
+// Size of a path separator.
+constexpr size_t PATH_SEP_SIZE = 1;
+
+// Creates the given directory if it does not exist. Returns zero on success.
+[[nodiscard]] int ensure_directory_exists(int dirfd, const char *path,
+ mode_t mode = 0755) {
+ if (LIBC_NAMESPACE::mkdirat(dirfd, path, mode) == 0)
+ return 0;
+ if (libc_errno == EEXIST)
+ libc_errno = 0;
+
+ if (libc_errno != 0) {
+ tlog << "Failed to create temp directory: " << path << "\n";
+ return -1;
+ }
+ return 0;
+}
+
+// A test directory that removes itself on destruction.
+class TestDir {
+ // The test directory's absolute path.
+ cpp::string path_;
+
+ // File descriptor of the test directory.
+ int fd_ = -1;
+
+ // Files created in this directory tree.
+ // Use a C string instead of cpp::string because FixedVector
+ // only supports trivially destructable types.
+ FixedVector<char *, 64> files_;
+
+ // Subdirectories created in this directory tree.
+ FixedVector<char *, 64> dirs_;
+
+public:
+ TestDir() = default;
+
+ // Initializes this TestDir container with the given path.
+ void initialize(cpp::string directory_path, int dirfd) {
+ LIBC_ASSERT(fd_ == -1);
+ path_ = directory_path;
+ fd_ = dirfd;
+ }
+
+ ~TestDir() {
+ if (path_.empty())
+ return;
+
+ for (size_t i = 0; i < files_.size(); i++) {
+ LIBC_NAMESPACE::unlinkat(fd_, files_[i], 0);
+ ::free(files_[i]);
+ }
+
+ // Remove directories in reverse order so they'll be empty.
+ for (size_t i = dirs_.size(); i > 0; i--) {
+ LIBC_NAMESPACE::unlinkat(fd_, dirs_[i - 1], AT_REMOVEDIR);
+ ::free(dirs_[i - 1]);
+ }
+
+ LIBC_NAMESPACE::close(fd_);
+ LIBC_NAMESPACE::unlinkat(AT_FDCWD, path_.c_str(), AT_REMOVEDIR);
+ }
+
+ TestDir(TestDir &other) = delete;
+ TestDir &operator=(TestDir &other) = delete;
+ TestDir(TestDir &&other) = delete;
+ TestDir &operator=(TestDir &&other) = delete;
+
+ // Returns the absolute path of `relpath` in this test directory.
+ cpp::string abspath(cpp::string_view relpath) const {
----------------
jtstogel wrote:
Done
https://github.com/llvm/llvm-project/pull/209369
More information about the libc-commits
mailing list