perf: tr_sys_path_dirname() returns a std::string_view (#2990)

* refactor: use nodejs impl of path.win32.dirname()

* refactor: use nodejs impl of path.posix.dirname()
This commit is contained in:
Charles Kerr
2022-05-21 11:10:58 -05:00
committed by GitHub
parent 2e25370cc5
commit 690cf50e53
10 changed files with 270 additions and 95 deletions

View File

@@ -8,6 +8,7 @@
#include <ostream>
#include <string>
#include <string_view>
#include <utility>
#ifndef _WIN32
#include <sys/types.h>
@@ -181,6 +182,32 @@ protected:
}
}
static void testPathXname(
XnameTestData const* data,
size_t data_size,
std::string_view (*func)(std::string_view, tr_error**))
{
for (size_t i = 0; i < data_size; ++i)
{
tr_error* err = nullptr;
auto const name = func(data[i].input, &err);
std::cerr << __FILE__ << ':' << __LINE__ << " in [" << data[i].input << "] out [" << name << ']' << std::endl;
if (data[i].output != nullptr)
{
EXPECT_NE(""sv, name);
EXPECT_EQ(nullptr, err) << *err;
EXPECT_EQ(std::string{ data[i].output }, name);
}
else
{
EXPECT_EQ(""sv, name);
EXPECT_NE(nullptr, err);
tr_error_clear(&err);
}
}
}
static void testDirReadImpl(tr_pathbuf const& path, bool* have1, bool* have2)
{
*have1 = *have2 = false;
@@ -687,7 +714,7 @@ TEST_F(FileTest, pathResolve)
#endif
}
TEST_F(FileTest, pathBasenameDirname)
TEST_F(FileTest, pathBasename)
{
auto const common_xname_tests = std::vector<XnameTestData>{
XnameTestData{ "/", "/" },
@@ -725,7 +752,7 @@ TEST_F(FileTest, pathBasenameDirname)
};
testPathXname(common_xname_tests.data(), common_xname_tests.size(), tr_sys_path_basename);
testPathXname(common_xname_tests.data(), common_xname_tests.size(), tr_sys_path_dirname);
// testPathXname(common_xname_tests.data(), common_xname_tests.size(), tr_sys_path_dirname);
auto const basename_tests = std::vector<XnameTestData>{
XnameTestData{ "a", "a" },
@@ -751,36 +778,91 @@ TEST_F(FileTest, pathBasenameDirname)
};
testPathXname(basename_tests.data(), basename_tests.size(), tr_sys_path_basename);
}
auto const dirname_tests = std::vector<XnameTestData>{
XnameTestData{ "/a/b/c", "/a/b" },
{ "a/b/c", "a/b" },
{ "a/b/c/", "a/b" },
{ "a", "." },
{ "a/", "." },
TEST_F(FileTest, pathDirname)
{
#ifdef _WIN32
{ "C:\\a/b\\c", "C:\\a/b" },
{ "C:\\a/b\\c\\", "C:\\a/b" },
{ "C:\\a/b", "C:\\a" },
{ "C:/a", "C:" },
{ "C:", "C:" },
{ "C:/", "C:" },
{ "C:\\", "C:" },
{ "c:a/b", "c:a" },
{ "c:a", "c:." },
{ "c:.", "c:." },
{ "\\\\a\\b\\c", "\\\\a\\b" },
{ "\\\\a\\b\\c/", "\\\\a\\b" },
{ "//a/b", "//a" },
{ "//1.2.3.4/b", "//1.2.3.4" },
{ "\\\\a", "\\\\" },
{ "\\\\1.2.3.4", "\\\\" },
{ "\\\\", "\\\\" },
{ "a/b\\c", "a/b" },
static auto constexpr DirnameTests = std::array<std::pair<std::string_view, std::string_view>, 48>{ {
{ "C:\\a/b\\c"sv, "C:\\a/b"sv },
{ "C:\\a/b\\c\\"sv, "C:\\a/b"sv },
{ "C:\\a/b"sv, "C:\\a"sv },
{ "C:/a"sv, "C:/"sv },
{ "C:"sv, "C:"sv },
{ "C:/"sv, "C:/"sv },
{ "c:a/b"sv, "c:a"sv },
{ "c:a"sv, "c:"sv },
{ "\\\\a"sv, "\\"sv },
{ "\\\\1.2.3.4"sv, "\\"sv },
{ "\\\\"sv, "\\"sv },
{ "a/b\\c"sv, "a/b"sv },
// taken from Node.js unit tests
// https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/test/parallel/test-path-dirname.js
{ "c:\\"sv, "c:\\"sv },
{ "c:\\foo"sv, "c:\\"sv },
{ "c:\\foo\\"sv, "c:\\"sv },
{ "c:\\foo\\bar"sv, "c:\\foo"sv },
{ "c:\\foo\\bar\\"sv, "c:\\foo"sv },
{ "c:\\foo\\bar\\baz"sv, "c:\\foo\\bar"sv },
{ "c:\\foo bar\\baz"sv, "c:\\foo bar"sv },
{ "\\"sv, "\\"sv },
{ "\\foo"sv, "\\"sv },
{ "\\foo\\"sv, "\\"sv },
{ "\\foo\\bar"sv, "\\foo"sv },
{ "\\foo\\bar\\"sv, "\\foo"sv },
{ "\\foo\\bar\\baz"sv, "\\foo\\bar"sv },
{ "\\foo bar\\baz"sv, "\\foo bar"sv },
{ "c:"sv, "c:"sv },
{ "c:foo"sv, "c:"sv },
{ "c:foo\\"sv, "c:"sv },
{ "c:foo\\bar"sv, "c:foo"sv },
{ "c:foo\\bar\\"sv, "c:foo"sv },
{ "c:foo\\bar\\baz"sv, "c:foo\\bar"sv },
{ "c:foo bar\\baz"sv, "c:foo bar"sv },
{ "file:stream"sv, "."sv },
{ "dir\\file:stream"sv, "dir"sv },
{ "\\\\unc\\share"sv, "\\\\unc\\share"sv },
{ "\\\\unc\\share\\foo"sv, "\\\\unc\\share\\"sv },
{ "\\\\unc\\share\\foo\\"sv, "\\\\unc\\share\\"sv },
{ "\\\\unc\\share\\foo\\bar"sv, "\\\\unc\\share\\foo"sv },
{ "\\\\unc\\share\\foo\\bar\\"sv, "\\\\unc\\share\\foo"sv },
{ "\\\\unc\\share\\foo\\bar\\baz"sv, "\\\\unc\\share\\foo\\bar"sv },
{ "/a/b/"sv, "/a"sv },
{ "/a/b"sv, "/a"sv },
{ "/a"sv, "/"sv },
{ ""sv, "."sv },
{ "/"sv, "/"sv },
{ "////"sv, "/"sv },
{ "foo"sv, "."sv },
} };
#else
static auto constexpr DirnameTests = std::array<std::pair<std::string_view, std::string_view>, 15>{ {
// taken from Node.js unit tests
// https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/test/parallel/test-path-dirname.js
{ "/a/b/"sv, "/a"sv },
{ "/a/b"sv, "/a"sv },
{ "/a"sv, "/"sv },
{ ""sv, "."sv },
{ "/"sv, "/"sv },
{ "////"sv, "/"sv },
{ "//a"sv, "//"sv },
{ "foo"sv, "."sv },
// taken from dirname(3) manpage
{ "usr"sv, "."sv },
{ "/usr/lib", "/usr"sv },
{ "/usr/"sv, "/"sv },
{ "/usr/"sv, "/"sv },
{ "/"sv, "/"sv },
{ "."sv, "."sv },
{ ".."sv, "."sv },
} };
#endif
};
testPathXname(dirname_tests.data(), dirname_tests.size(), tr_sys_path_dirname);
for (auto const& [input, expected] : DirnameTests)
{
EXPECT_EQ(expected, tr_sys_path_dirname(input)) << "input[" << input << "] expected [" << expected << "] actual ["
<< tr_sys_path_dirname(input) << ']' << std::endl;
}
/* TODO: is_same(dirname(x) + '/' + basename(x), x) */
}

View File

@@ -180,10 +180,11 @@ protected:
createFileWithContents(filename, std::data(Content), std::size(Content));
paths.emplace(filename);
while (!tr_sys_path_is_same(parent, filename))
auto walk = std::string_view{ filename.sv() };
while (!tr_sys_path_is_same(parent, std::string{ walk }.c_str()))
{
filename = tr_sys_path_dirname(filename);
paths.emplace(filename);
walk = tr_sys_path_dirname(walk);
paths.emplace(walk);
}
}
@@ -301,7 +302,7 @@ TEST_F(RemoveTest, LeavesNonJunkAlone)
EXPECT_EQ(expected_tree, getSubtreeContents(parent));
files.remove(parent, "tmpdir_prefix"sv, sysPathRemove);
expected_tree = { parent, tr_sys_path_dirname(nonjunk_file), nonjunk_file.c_str() };
expected_tree = { parent, std::string{ tr_sys_path_dirname(nonjunk_file) }, nonjunk_file.c_str() };
EXPECT_EQ(expected_tree, getSubtreeContents(parent));
}

View File

@@ -350,7 +350,7 @@ TEST_F(RenameTest, multifileTorrent)
str = tr_torrentFindFile(tor, 2);
EXPECT_NE(nullptr, str);
tr_sys_path_remove(str);
tr_sys_path_remove(tr_sys_path_dirname(str).c_str());
tr_sys_path_remove(std::string{ tr_sys_path_dirname(str) }.c_str());
tr_free(str);
sync();
blockingTorrentVerify(tor);

View File

@@ -35,7 +35,7 @@ std::string getTestProgramPath(std::string const& filename)
{
auto const exe_path = makeString(tr_sys_path_resolve(testing::internal::GetArgvs().front().data()));
auto const exe_dir = tr_sys_path_dirname(exe_path);
return exe_dir + TR_PATH_DELIMITER + filename;
return std::string{ exe_dir } + TR_PATH_DELIMITER + filename;
}
class SubprocessTest

View File

@@ -184,7 +184,7 @@ protected:
auto const dir = tr_sys_path_dirname(path);
tr_error* error = nullptr;
tr_sys_dir_create(dir.data(), TR_SYS_DIR_CREATE_PARENTS, 0700, &error);
tr_sys_dir_create(std::string{ dir }.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0700, &error);
EXPECT_EQ(nullptr, error) << "path[" << path << "] dir[" << dir << "] " << *error;
errno = tmperr;
@@ -411,7 +411,7 @@ protected:
auto const filename = tr_pathbuf{ base, '/', subpath, suffix };
auto const dirname = tr_sys_path_dirname(filename);
tr_sys_dir_create(dirname.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0700);
tr_sys_dir_create(std::string{ dirname }.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0700);
auto fd = tr_sys_file_open(filename, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600);
auto const file_size = metainfo->fileSize(i);