From ae74a13eb1d43f657a8816d3acca5196a8f870a3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 4 Sep 2022 19:40:34 -0500 Subject: [PATCH] test: improve file-win32, file-posix test coverage (#3761) --- libtransmission/file-posix.cc | 237 +++++++------------------- libtransmission/file-win32.cc | 55 +++--- libtransmission/file.h | 11 -- tests/libtransmission/file-test.cc | 181 ++++++++++++++++---- tests/libtransmission/test-fixtures.h | 11 +- 5 files changed, 253 insertions(+), 242 deletions(-) diff --git a/libtransmission/file-posix.cc b/libtransmission/file-posix.cc index 5303beff8..cdad8be93 100644 --- a/libtransmission/file-posix.cc +++ b/libtransmission/file-posix.cc @@ -116,29 +116,6 @@ static void set_system_error_if_file_found(tr_error** error, int code) } } -static constexpr auto stat_to_sys_path_info(struct stat const& sb) -{ - auto info = tr_sys_path_info{}; - - if (S_ISREG(sb.st_mode)) - { - info.type = TR_SYS_PATH_IS_FILE; - } - else if (S_ISDIR(sb.st_mode)) - { - info.type = TR_SYS_PATH_IS_DIRECTORY; - } - else - { - info.type = TR_SYS_PATH_IS_OTHER; - } - - info.size = static_cast(sb.st_size); - info.last_modified_at = sb.st_mtime; - - return info; -} - static void set_file_for_single_pass(tr_sys_file_t handle) { /* Set hints about the lookahead buffer and caching. It's okay @@ -167,126 +144,6 @@ static void set_file_for_single_pass(tr_sys_file_t handle) errno = err; } -#ifndef HAVE_MKDIRP - -static bool create_path_require_dir(char const* path, tr_error** error) -{ - struct stat sb; - - if (stat(path, &sb) == -1) - { - set_system_error(error, errno); - return false; - } - - if ((sb.st_mode & S_IFMT) != S_IFDIR) - { - tr_error_set(error, ENOTDIR, fmt::format(FMT_STRING("File is in the way: {:s}"), path)); - return false; - } - - return true; -} - -static bool create_path(char const* path_in, int permissions, tr_error** error) -{ - /* make a temporary copy of path */ - auto path = tr_pathbuf{ path_in }; - - /* walk past the root */ - char* p = std::data(path); - - while (*p == TR_PATH_DELIMITER) - { - ++p; - } - - char* path_end = p + strlen(p); - - while (path_end > path && *path_end == TR_PATH_DELIMITER) - { - --path_end; - } - - char* pp = nullptr; - bool ret = false; - tr_error* my_error = nullptr; - - /* Go one level up on each iteration and attempt to create */ - for (pp = path_end; pp != nullptr; pp = strrchr(p, TR_PATH_DELIMITER)) - { - *pp = '\0'; - - ret = mkdir(path, permissions) != -1; - - if (ret) - { - break; - } - - if (errno == EEXIST) - { - ret = create_path_require_dir(path, &my_error); - - if (ret) - { - break; - } - - goto FAILURE; - } - - if (errno != ENOENT) - { - set_system_error(&my_error, errno); - goto FAILURE; - } - } - - if (ret && pp == path_end) - { - goto CLEANUP; - } - - /* Go one level down on each iteration and attempt to create */ - for (pp = pp == nullptr ? p + strlen(p) : pp; pp < path_end; pp += strlen(pp)) - { - *pp = TR_PATH_DELIMITER; - - if (mkdir(path, permissions) == -1) - { - break; - } - } - - ret = create_path_require_dir(path, &my_error); - - if (ret) - { - goto CLEANUP; - } - -FAILURE: - - TR_ASSERT(!ret); - TR_ASSERT(my_error != nullptr); - - tr_logAddError(fmt::format( - _("Couldn't create '{path}': {error} ({error_code})"), - fmt::arg("path", path), - fmt::arg("error", my_error->message), - fmt::arg("error_code", my_error->code))); - tr_error_propagate(error, &my_error); - -CLEANUP: - - TR_ASSERT(my_error == nullptr); - - return ret; -} - -#endif - bool tr_sys_path_exists(char const* path, tr_error** error) { TR_ASSERT(path != nullptr); @@ -317,13 +174,31 @@ std::optional tr_sys_path_get_info(std::string_view path, int ok = lstat(szpath, &sb) != -1; } - if (ok) + if (!ok) { - return stat_to_sys_path_info(sb); + set_system_error(error, errno); + return {}; } - set_system_error(error, errno); - return {}; + auto info = tr_sys_path_info{}; + + if (S_ISREG(sb.st_mode)) + { + info.type = TR_SYS_PATH_IS_FILE; + } + else if (S_ISDIR(sb.st_mode)) + { + info.type = TR_SYS_PATH_IS_DIRECTORY; + } + else + { + info.type = TR_SYS_PATH_IS_OTHER; + } + + info.size = static_cast(sb.st_size); + info.last_modified_at = sb.st_mtime; + + return info; } bool tr_sys_path_is_relative(std::string_view path) @@ -459,6 +334,13 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, tr_error** err #else /* USE_COPYFILE */ + auto const info = tr_sys_path_get_info(src_path, 0, error); + if (!info) + { + tr_error_prefix(error, "Unable to get information on source file: "); + return false; + } + /* Other OSes require us to copy between file descriptors, so open them. */ tr_sys_file_t const in = tr_sys_file_open(src_path, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, error); if (in == TR_BAD_SYS_FILE) @@ -467,14 +349,6 @@ bool tr_sys_path_copy(char const* src_path, char const* dst_path, tr_error** err return false; } - auto const info = tr_sys_file_get_info(in, error); - if (!info) - { - tr_error_prefix(error, "Unable to get information on source file: "); - tr_sys_file_close(in); - return false; - } - tr_sys_file_t const out = tr_sys_file_open( dst_path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, @@ -685,19 +559,6 @@ bool tr_sys_file_close(tr_sys_file_t handle, tr_error** error) return ret; } -std::optional tr_sys_file_get_info(tr_sys_file_t handle, tr_error** error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - if (struct stat sb; fstat(handle, &sb) != -1) - { - return stat_to_sys_path_info(sb); - } - - set_system_error(error, errno); - return {}; -} - bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t* bytes_read, tr_error** error) { TR_ASSERT(handle != TR_BAD_SYS_FILE); @@ -1143,6 +1004,40 @@ std::string tr_sys_dir_get_current(tr_error** error) } } +#ifndef HAVE_MKDIRP + +static bool tr_mkdirp_(std::string_view path, int permissions, tr_error** error) +{ + auto walk = path.find_first_not_of('/'); // walk past the root + auto subpath = tr_pathbuf{}; + + while (walk < std::size(path)) + { + auto const end = path.find('/', walk); + subpath.assign(path.substr(0, end)); + auto const info = tr_sys_path_get_info(subpath, 0); + if (info && !info->isFolder()) + { + tr_error_set(error, ENOTDIR, fmt::format(FMT_STRING("File is in the way: {:s}"), path)); + return false; + } + if (!info && mkdir(subpath, permissions) == -1) + { + set_system_error(error, errno); + return false; + } + if (end == std::string_view::npos) + { + break; + } + walk = end + 1; + } + + return true; +} + +#endif + bool tr_sys_dir_create(char const* path, int flags, int permissions, tr_error** error) { TR_ASSERT(path != nullptr); @@ -1155,7 +1050,7 @@ bool tr_sys_dir_create(char const* path, int flags, int permissions, tr_error** #ifdef HAVE_MKDIRP ret = mkdirp(path, permissions) != -1; #else - ret = create_path(path, permissions, &my_error); + ret = tr_mkdirp_(path, permissions, &my_error); #endif } else @@ -1165,9 +1060,7 @@ bool tr_sys_dir_create(char const* path, int flags, int permissions, tr_error** if (!ret && errno == EEXIST) { - struct stat sb; - - if (stat(path, &sb) != -1 && S_ISDIR(sb.st_mode)) + if (auto const info = tr_sys_path_get_info(path); info && info->type == TR_SYS_PATH_IS_DIRECTORY) { tr_error_clear(&my_error); ret = true; diff --git a/libtransmission/file-win32.cc b/libtransmission/file-win32.cc index 850c4bb91..8d5d8f17a 100644 --- a/libtransmission/file-win32.cc +++ b/libtransmission/file-win32.cc @@ -255,6 +255,12 @@ static bool create_dir(std::string_view path, int flags, int /*permissions*/, bo DWORD error_code = ERROR_SUCCESS; auto const wide_path = path_to_native_path(path); + // already exists (no-op) + if (auto const info = tr_sys_path_get_info(path); info && info->isFolder()) + { + return true; + } + if ((flags & TR_SYS_DIR_CREATE_PARENTS) != 0) { error_code = SHCreateDirectoryExW(nullptr, wide_path.c_str(), nullptr); @@ -375,6 +381,24 @@ bool tr_sys_path_exists(char const* path, tr_error** error) return ret; } +static std::optional tr_sys_file_get_info_(tr_sys_file_t handle, tr_error** error) +{ + TR_ASSERT(handle != TR_BAD_SYS_FILE); + + auto attributes = BY_HANDLE_FILE_INFORMATION{}; + if (GetFileInformationByHandle(handle, &attributes)) + { + return stat_to_sys_path_info( + attributes.dwFileAttributes, + attributes.nFileSizeLow, + attributes.nFileSizeHigh, + attributes.ftLastWriteTime); + } + + set_system_error(error, GetLastError()); + return {}; +} + std::optional tr_sys_path_get_info(std::string_view path, int flags, tr_error** error) { if (auto const wide_path = path_to_native_path(path); std::empty(wide_path)) @@ -397,7 +421,7 @@ std::optional tr_sys_path_get_info(std::string_view path, int handle = CreateFileW(wide_path.c_str(), 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); handle != INVALID_HANDLE_VALUE) { - auto ret = tr_sys_file_get_info(handle, error); + auto ret = tr_sys_file_get_info_(handle, error); CloseHandle(handle); return ret; } @@ -929,24 +953,6 @@ bool tr_sys_file_close(tr_sys_file_t handle, tr_error** error) return ret; } -std::optional tr_sys_file_get_info(tr_sys_file_t handle, tr_error** error) -{ - TR_ASSERT(handle != TR_BAD_SYS_FILE); - - auto attributes = BY_HANDLE_FILE_INFORMATION{}; - if (GetFileInformationByHandle(handle, &attributes)) - { - return stat_to_sys_path_info( - attributes.dwFileAttributes, - attributes.nFileSizeLow, - attributes.nFileSizeHigh, - attributes.ftLastWriteTime); - } - - set_system_error(error, GetLastError()); - return {}; -} - bool tr_sys_file_read(tr_sys_file_t handle, void* buffer, uint64_t size, uint64_t* bytes_read, tr_error** error) { TR_ASSERT(handle != TR_BAD_SYS_FILE); @@ -1248,16 +1254,17 @@ tr_sys_dir_t tr_sys_dir_open(char const* path, tr_error** error) { TR_ASSERT(path != nullptr); -#ifndef __clang__ - /* Clang gives "static_assert expression is not an integral constant expression" error */ - static_assert(TR_BAD_SYS_DIR == nullptr, "values should match"); -#endif + if (auto const info = tr_sys_path_get_info(path, 0); !info || !info->isFolder()) + { + set_system_error(error, ERROR_DIRECTORY); + return TR_BAD_SYS_DIR; + } auto pattern = path_to_native_path(path); if (std::empty(pattern)) { set_system_error(error, GetLastError()); - return nullptr; + return TR_BAD_SYS_DIR; } auto* const ret = new tr_sys_dir_win32{}; diff --git a/libtransmission/file.h b/libtransmission/file.h index b4906b1d8..78b267e10 100644 --- a/libtransmission/file.h +++ b/libtransmission/file.h @@ -362,17 +362,6 @@ tr_sys_file_t tr_sys_file_open_temp(char* path_template, struct tr_error** error */ bool tr_sys_file_close(tr_sys_file_t handle, struct tr_error** error = nullptr); -/** - * @brief Portability wrapper for `fstat()`. - * - * @param[in] handle Valid file descriptor. - * @param[out] error Pointer to error object. Optional, pass `nullptr` if you - * are not interested in error details. - * - * @return info on success, or nullopt with `error` set accordingly. - */ -[[nodiscard]] std::optional tr_sys_file_get_info(tr_sys_file_t handle, struct tr_error** error = nullptr); - /** * @brief Portability wrapper for `read()`. * diff --git a/tests/libtransmission/file-test.cc b/tests/libtransmission/file-test.cc index 9f7ed5028..736b67be6 100644 --- a/tests/libtransmission/file-test.cc +++ b/tests/libtransmission/file-test.cc @@ -235,17 +235,6 @@ TEST_F(FileTest, getInfo) EXPECT_GE(info->last_modified_at, t - 1); EXPECT_LE(info->last_modified_at, time(nullptr) + 1); - // Good file info (by handle) - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0); - info = tr_sys_file_get_info(fd, &err); - EXPECT_TRUE(info); - EXPECT_EQ(nullptr, err) << *err; - EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type); - EXPECT_EQ(4, info->size); - EXPECT_GE(info->last_modified_at, t - 1); - EXPECT_LE(info->last_modified_at, time(nullptr) + 1); - tr_sys_file_close(fd); - tr_sys_path_remove(path1); // Good directory info @@ -280,16 +269,11 @@ TEST_F(FileTest, getInfo) EXPECT_GE(info->last_modified_at, t - 1); EXPECT_LE(info->last_modified_at, time(nullptr) + 1); - // Good file info (by handle) - fd = tr_sys_file_open(path1, TR_SYS_FILE_READ, 0); - info = tr_sys_file_get_info(fd, &err); + // Symlink + info = tr_sys_path_get_info(path1, TR_SYS_PATH_NO_FOLLOW, &err); EXPECT_TRUE(info); EXPECT_EQ(nullptr, err) << *err; - EXPECT_EQ(TR_SYS_PATH_IS_FILE, info->type); - EXPECT_EQ(4, info->size); - EXPECT_GE(info->last_modified_at, t - 1); - EXPECT_LE(info->last_modified_at, time(nullptr) + 1); - tr_sys_file_close(fd); + EXPECT_EQ(TR_SYS_PATH_IS_OTHER, info->type); tr_sys_path_remove(path2); tr_sys_path_remove(path1); @@ -315,6 +299,50 @@ TEST_F(FileTest, getInfo) } } +TEST_F(FileTest, readFile) +{ + auto const test_dir = createTestDir(currentTestName()); + + auto const path = tr_pathbuf{ test_dir, "/a.txt"sv }; + auto constexpr Contents = "hello, world!"sv; + createFileWithContents(path, Contents); + + auto n_bytes_read = uint64_t{}; + tr_error* err = nullptr; + auto buf = std::array{}; + auto fd = tr_sys_file_open(path, TR_SYS_FILE_READ, 0); + EXPECT_NE(TR_BAD_SYS_FILE, fd); + + // successful read + EXPECT_TRUE(tr_sys_file_read(fd, std::data(buf), std::size(buf), &n_bytes_read, &err)); + EXPECT_EQ(Contents, std::string_view(std::data(buf), n_bytes_read)); + EXPECT_EQ(std::size(Contents), n_bytes_read); + EXPECT_EQ(nullptr, err) << *err; + + // successful read_at + auto const offset = 1U; + EXPECT_TRUE(tr_sys_file_read_at(fd, std::data(buf), std::size(buf), offset, &n_bytes_read, &err)); + auto constexpr Expected = Contents.substr(offset); + EXPECT_EQ(Expected, std::string_view(std::data(buf), n_bytes_read)); + EXPECT_EQ(std::size(Expected), n_bytes_read); + EXPECT_EQ(nullptr, err) << *err; + + tr_sys_file_close(fd); + + // read from closed file + n_bytes_read = 0; + EXPECT_FALSE(tr_sys_file_read(fd, std::data(buf), std::size(buf), &n_bytes_read, &err)); + EXPECT_EQ(0, n_bytes_read); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); + + // read_at from closed file + EXPECT_FALSE(tr_sys_file_read_at(fd, std::data(buf), std::size(buf), offset, &n_bytes_read, &err)); + EXPECT_EQ(0, n_bytes_read); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); +} + TEST_F(FileTest, pathExists) { auto const test_dir = createTestDir(currentTestName()); @@ -1019,6 +1047,40 @@ TEST_F(FileTest, pathNativeSeparators) } } +TEST_F(FileTest, fileCopy) +{ + auto const test_dir = createTestDir(currentTestName()); + + auto const path1 = tr_pathbuf{ test_dir, "/a.txt" }; + auto const path2 = tr_pathbuf{ test_dir, "/b.txt" }; + auto constexpr Contents = "hello, world!"sv; + + // no source file + tr_error* err = nullptr; + EXPECT_FALSE(tr_sys_path_copy(path1, path2, &err)); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); + + createFileWithContents(path1, Contents); + + // source file exists but is inaccessible + chmod(path1, 0); + EXPECT_FALSE(tr_sys_path_copy(path1, test_dir, &err)); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); + chmod(path1, 0600); + + // source file exists but target is invalid + EXPECT_FALSE(tr_sys_path_copy(path1, test_dir, &err)); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); + + // source and target are valid + createFileWithContents(path1, Contents); + EXPECT_TRUE(tr_sys_path_copy(path1, path2, &err)); + EXPECT_EQ(nullptr, err); +} + TEST_F(FileTest, fileOpen) { auto const test_dir = createTestDir(currentTestName()); @@ -1089,7 +1151,7 @@ TEST_F(FileTest, fileOpen) fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_TRUNCATE, 0600, &err); EXPECT_NE(TR_BAD_SYS_FILE, fd); EXPECT_EQ(nullptr, err) << *err; - info = tr_sys_file_get_info(fd); + info = tr_sys_path_get_info(path1); EXPECT_TRUE(info); EXPECT_EQ(0U, info->size); tr_sys_file_close(fd); @@ -1106,25 +1168,25 @@ TEST_F(FileTest, fileTruncate) { auto const test_dir = createTestDir(currentTestName()); - auto const path1 = tr_pathbuf{ test_dir, "/a"sv }; - auto fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600); + auto const path = tr_pathbuf{ test_dir, "/a"sv }; + auto fd = tr_sys_file_open(path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600); tr_error* err = nullptr; EXPECT_TRUE(tr_sys_file_truncate(fd, 10, &err)); EXPECT_EQ(nullptr, err) << *err; - auto info = tr_sys_file_get_info(fd); + auto info = tr_sys_path_get_info(path); EXPECT_TRUE(info); EXPECT_EQ(10U, info->size); EXPECT_TRUE(tr_sys_file_truncate(fd, 20, &err)); EXPECT_EQ(nullptr, err) << *err; - info = tr_sys_file_get_info(fd); + info = tr_sys_path_get_info(path); EXPECT_TRUE(info); EXPECT_EQ(20U, info->size); EXPECT_TRUE(tr_sys_file_truncate(fd, 0, &err)); EXPECT_EQ(nullptr, err) << *err; - info = tr_sys_file_get_info(fd); + info = tr_sys_path_get_info(path); EXPECT_TRUE(info); EXPECT_EQ(0U, info->size); @@ -1133,22 +1195,27 @@ TEST_F(FileTest, fileTruncate) tr_sys_file_close(fd); - info = tr_sys_path_get_info(path1); + info = tr_sys_path_get_info(path); EXPECT_TRUE(info); EXPECT_EQ(50U, info->size); - fd = tr_sys_file_open(path1, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600); + fd = tr_sys_file_open(path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE, 0600); EXPECT_TRUE(tr_sys_file_truncate(fd, 25, &err)); EXPECT_EQ(nullptr, err) << *err; tr_sys_file_close(fd); - info = tr_sys_path_get_info(path1); + info = tr_sys_path_get_info(path); EXPECT_TRUE(info); EXPECT_EQ(25U, info->size); - tr_sys_path_remove(path1); + // try to truncate a closed file + EXPECT_FALSE(tr_sys_file_truncate(fd, 10, &err)); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); + + tr_sys_path_remove(path); } TEST_F(FileTest, filePreallocate) @@ -1163,7 +1230,7 @@ TEST_F(FileTest, filePreallocate) if (tr_sys_file_preallocate(fd, prealloc_size, 0, &err)) { EXPECT_EQ(nullptr, err) << *err; - auto info = tr_sys_file_get_info(fd); + auto info = tr_sys_path_get_info(path1); EXPECT_TRUE(info); EXPECT_EQ(prealloc_size, info->size); } @@ -1184,7 +1251,7 @@ TEST_F(FileTest, filePreallocate) if (tr_sys_file_preallocate(fd, prealloc_size, TR_SYS_FILE_PREALLOC_SPARSE, &err)) { EXPECT_EQ(nullptr, err) << *err; - auto info = tr_sys_file_get_info(fd); + auto info = tr_sys_path_get_info(path1); EXPECT_TRUE(info); EXPECT_EQ(prealloc_size, info->size); } @@ -1251,6 +1318,22 @@ TEST_F(FileTest, dirCreate) tr_sys_path_remove(path1); } +TEST_F(FileTest, dirCreateTemp) +{ + auto const test_dir = createTestDir(currentTestName()); + + tr_error* err = nullptr; + auto path = tr_pathbuf{ test_dir, "/test-XXXXXX" }; + EXPECT_TRUE(tr_sys_dir_create_temp(std::data(path), &err)); + EXPECT_EQ(nullptr, err) << *err; + tr_sys_path_remove(path); + + path.assign(test_dir, "/path-does-not-exist/test-XXXXXX"); + EXPECT_FALSE(tr_sys_dir_create_temp(std::data(path), &err)); + EXPECT_NE(nullptr, err); + tr_error_clear(&err); +} + TEST_F(FileTest, dirRead) { auto const test_dir = createTestDir(currentTestName()); @@ -1280,6 +1363,42 @@ TEST_F(FileTest, dirRead) EXPECT_TRUE(have2); } +TEST_F(FileTest, dirOpen) +{ + auto const test_dir = createTestDir(currentTestName()); + + auto const file = tr_pathbuf{ test_dir, "/foo.fxt" }; + auto constexpr Contents = "hello, world!"sv; + createFileWithContents(file, std::data(Contents), std::size(Contents)); + + // path does not exist + tr_error* err = nullptr; + auto odir = tr_sys_dir_open("/no/such/path", &err); + EXPECT_EQ(TR_BAD_SYS_DIR, odir); + EXPECT_NE(err, nullptr); + tr_error_clear(&err); + + // path is not a directory + odir = tr_sys_dir_open(file, &err); + EXPECT_EQ(TR_BAD_SYS_DIR, odir); + EXPECT_NE(err, nullptr); + tr_error_clear(&err); + + // path exists and is readable + odir = tr_sys_dir_open(test_dir); + EXPECT_NE(TR_BAD_SYS_DIR, odir); + auto files = std::set{}; + char const* filename = nullptr; + while ((filename = tr_sys_dir_read_name(odir, &err))) + { + files.insert(filename); + } + EXPECT_EQ(3U, files.size()); + EXPECT_EQ(nullptr, err) << *err; + EXPECT_TRUE(tr_sys_dir_close(odir, &err)); + EXPECT_EQ(nullptr, err) << *err; +} + } // namespace test } // namespace libtransmission diff --git a/tests/libtransmission/test-fixtures.h b/tests/libtransmission/test-fixtures.h index df3dd91fe..b4c1ffb48 100644 --- a/tests/libtransmission/test-fixtures.h +++ b/tests/libtransmission/test-fixtures.h @@ -127,7 +127,6 @@ protected: auto path = tr_sys_dir_get_current(&error); if (error != nullptr) { - std::cerr << "tr_sys_dir_get_current error: '" << error->message << "'" << std::endl; tr_error_free(error); } return path; @@ -184,9 +183,13 @@ protected: auto dir = tr_pathbuf{ path }; dir.popdir(); - tr_error* error = nullptr; - tr_sys_dir_create(dir, TR_SYS_DIR_CREATE_PARENTS, 0700, &error); - EXPECT_EQ(nullptr, error) << "path[" << path << "] dir[" << dir << "] " << *error; + if (auto const info = tr_sys_path_get_info(path); !info) + { + tr_error* error = nullptr; + tr_sys_dir_create(dir, TR_SYS_DIR_CREATE_PARENTS, 0700, &error); + EXPECT_EQ(nullptr, error) << "path[" << path << "] dir[" << dir << "] " << *error; + tr_error_clear(&error); + } errno = tmperr; }