From c886d489576cd0bc33d7d22d81981c794067946f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 23 Oct 2022 13:41:15 -0400 Subject: Add path API --- test/cpp/.clang-tidy | 13 ++ test/cpp/test_path_std.cpp | 496 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 509 insertions(+) create mode 100644 test/cpp/.clang-tidy create mode 100644 test/cpp/test_path_std.cpp (limited to 'test/cpp') diff --git a/test/cpp/.clang-tidy b/test/cpp/.clang-tidy new file mode 100644 index 0000000..9a3cd8c --- /dev/null +++ b/test/cpp/.clang-tidy @@ -0,0 +1,13 @@ +# Copyright 2020-2022 David Robillard +# SPDX-License-Identifier: 0BSD OR ISC + +Checks: > + -*-avoid-c-arrays, + -*-no-malloc, + -android-cloexec-fopen, + -cppcoreguidelines-owning-memory, + -fuchsia-default-arguments-calls, + -modernize-raw-string-literal, + -modernize-use-trailing-return-type, + -readability-implicit-bool-conversion, +InheritParentConfig: true diff --git a/test/cpp/test_path_std.cpp b/test/cpp/test_path_std.cpp new file mode 100644 index 0000000..f6767a6 --- /dev/null +++ b/test/cpp/test_path_std.cpp @@ -0,0 +1,496 @@ +// Copyright 2020-2022 David Robillard +// SPDX-License-Identifier: ISC + +/* + Tests that compare results with std::filesystem::path. Also serves as a + handy record of divergence between zix, the C++ standard library, and + different implementations of it. The inconsistencies are confined to + Windows. +*/ + +#undef NDEBUG + +#include "zix/path.h" +#include "zix/string_view.h" + +#include +#include +#include +#include +#include + +struct BinaryCase { + const char* lhs; + const char* rhs; +}; + +static const BinaryCase joins[] = { + {"", ""}, {"", "/b/"}, {"", "b"}, {"/", ""}, + {"..", ".."}, {"..", "name"}, {"..", "/"}, {"/", ".."}, + {"/", nullptr}, {"//host", ""}, {"//host", "a"}, {"//host/", "a"}, + {"/a", ""}, {"/a", "/b"}, {"/a", "/b/"}, {"/a", "b"}, + {"/a", "b/"}, {"/a", nullptr}, {"/a/", ""}, {"/a/", "b"}, + {"/a/", "b/"}, {"/a/", nullptr}, {"/a/b", nullptr}, {"/a/b/", ""}, + {"/a/b/", nullptr}, {"/a/c", "b"}, {"/a/c/", "/b/d"}, {"/a/c/", "b"}, + {"C:", ""}, {"C:/a", "/b"}, {"C:/a", "C:/b"}, {"C:/a", "C:b"}, + {"C:/a", "D:b"}, {"C:/a", "b"}, {"C:/a", "b/"}, {"C:/a", "c:/b"}, + {"C:/a", "c:b"}, {"C:\\a", "b"}, {"C:\\a", "b\\"}, {"C:a", "/b"}, + {"C:a", "C:/b"}, {"C:a", "C:\\b"}, {"C:a", "C:b"}, {"C:a", "b"}, + {"C:a", "c:/b"}, {"C:a", "c:\\b"}, {"C:a", "c:b"}, {"a", ""}, + {"a", "/b"}, {"a", "C:"}, {"a", "C:/b"}, {"a", "C:\\b"}, + {"a", "\\b"}, {"a", "b"}, {"a", "b/"}, {"a", nullptr}, + {"a/", ""}, {"a/", "/b"}, {"a/", "b"}, {"a/", "b/"}, + {"a/", nullptr}, {"a/b", ""}, {"a/b", nullptr}, {"a/b/", ""}, + {"a/b/", nullptr}, {"a\\", "\\b"}, {"a\\", "b"}, {nullptr, "/b"}, + {nullptr, "/b/c"}, {nullptr, "b"}, {nullptr, "b/c"}, {nullptr, nullptr}, +}; + +static const BinaryCase lexical_relatives[] = { + {nullptr, nullptr}, + + {"", ""}, + {"", "."}, + {".", "."}, + {"../", "../"}, + {"../", "./"}, + {"../", "a"}, + {"../../a", "../b"}, + {"../a", "../b"}, + {"/", "/a/b"}, + {"/", "/a/b/c"}, + {"/", "a"}, + {"/", "a/b"}, + {"/", "a/b/c"}, + {"//host", "//host"}, + {"//host/", "//host/"}, + {"//host/a/b", "//host/a/b"}, + {"/a", "/b/c/"}, + {"/a/", "/a/b"}, + {"/a/", "/b/c"}, + {"/a/", "/b/c/"}, + {"/a/", "b"}, + {"/a/", "b/c/"}, + {"/a/b", "a/b"}, + {"/a/b/c", "/a/b/d/"}, + {"/a/b/c", "/a/b/d/e/"}, + {"/a/b/c", "/a/d"}, + {"C:", "C:a.txt"}, + {"C:", "D:a.txt"}, + {"C:../", "C:../"}, + {"C:../", "C:./"}, + {"C:../", "C:a"}, + {"C:../../a", "C:../b"}, + {"C:../a", "C:../b"}, + {"C:/", "C:a.txt"}, + {"C:/", "D:a.txt"}, + {"C:/D/", "C:F"}, + {"C:/D/", "C:F.txt"}, + {"C:/D/S/", "F"}, + {"C:/D/S/", "F.txt"}, + {"C:/Dir/", "C:/Dir/File.txt"}, + {"C:/Dir/", "C:File.txt"}, + {"C:/Dir/File.txt", "C:/Dir/Sub/"}, + {"C:/Dir/File.txt", "C:/Other.txt"}, + {"C:/Dir/Sub/", "File.txt"}, + {"C:/a.txt", "C:/b/c.txt"}, + {"C:/a/", "C:/a/b.txt"}, + {"C:/a/", "C:b.txt"}, + {"C:/a/b.txt", "C:/a/b/"}, + {"C:/a/b.txt", "C:/d.txt"}, + {"C:/a/b/", "d.txt"}, + {"C:/b/", "C:a.txt"}, + {"C:/b/c/", "a.txt"}, + {"C:F", "D:G"}, + {"C:File.txt", "D:Other.txt"}, + {"C:a.txt", "C:b.txt"}, + {"C:a.txt", "D:"}, + {"C:a.txt", "D:/"}, + {"C:a.txt", "D:e.txt"}, + {"C:a/b/c", "C:../"}, + {"C:a/b/c", "C:../../"}, + {"a", "a"}, + {"a", "a/b/c"}, + {"a", "b/c"}, + {"a/b", "a/b"}, + {"a/b", "c/d"}, + {"a/b/c", "../"}, + {"a/b/c", "../../"}, + {"a/b/c", "a/b/c"}, + {"a/b/c", "a/b/c/x/y"}, + {"a/b/c/", "a/b/c/"}, + +// Network paths that aren't supported by MinGW +#if !(defined(_WIN32) && defined(__GLIBCXX__)) + {"//host", "//host/"}, + {"//host", "a"}, + {"//host", "a"}, + {"//host/", "a"}, + {"//host/", "a"}, +#endif +}; + +static const char* const paths[] = { + // Valid paths handled consistently on all platforms + "", + ".", + "..", + "../", + "../..", + "../../", + "../../a", + "../a", + "../name", + "..\\..\\a", + "..\\a", + "..name", + "./", + "./.", + "./..", + ".//a//.//./b/.//", + "./a/././b/./", + "./name", + ".hidden", + ".hidden.txt", + "/", + "/.", + "/..", + "/../", + "/../..", + "/../../", + "/../a", + "/../a/../..", + "//", + "///", + "///dir/", + "///dir///", + "///dir///name", + "///dir///sub/////", + "///name", + "/a", + "/a/", + "/a/b", + "/a/b/", + "/a\\", + "/a\\b", + "/a\\b/", + "/dir/", + "/dir/.", + "/dir/..", + "/dir/../..", + "/dir/.hidden", + "/dir//name", + "/dir//sub/suub/", + "/dir/name", + "/dir/name.tar.gz", + "/dir/name.txt", + "/dir/name\\", + "/dir/sub/", + "/dir/sub/./", + "/dir/sub//", + "/dir/sub///", + "/dir/sub//name", + "/dir/sub/name", + "/dir/sub/suub/", + "/dir/sub/suub/../", + "/dir/sub/suub/../d", + "/dir/sub/suub/../d/", + "/dir/sub/suub/suuub/", + "/dir/sub\\name", + "/name", + "/name.", + "/name.txt", + "/name.txt.", + "C:", + "C:.", + "C:..", + "C:/", + "C:/.", + "C:/..", + "C:/../../name", + "C:/../name", + "C:/..dir/..name", + "C:/..name", + "C:/./name", + "C:/.dir/../name", + "C:/.dir/.hidden", + "C:/.hidden", + "C:/dir/", + "C:/dir/.", + "C:/dir/..", + "C:/dir/name", + "C:/dir/sub/", + "C:/dir/sub/name", + "C:/dir/sub/suub/", + "C:/dir/sub/suub/suuub/", + "C:/name", + "C:/name.", + "C:/name.txt", + "C:/name\\horror", + "C:/name\\horror/", + "C:\\", + "C:\\a", + "C:\\a/", + "C:\\a/b", + "C:\\a/b\\", + "C:\\a\\", + "C:\\a\\b", + "C:\\a\\b\\", + "C:\\a\\b\\c", + "C:\\a\\b\\d\\", + "C:\\a\\b\\d\\e\\", + "C:\\b", + "C:\\b\\c\\", + "C:a", + "C:dir/", + "C:dir/name", + "C:dir\\", + "C:name", + "C:name/", + "C:name\\horror", + "D|\\dir\\name", + "D|\\name", + "D|name", + "Z:/a/b", + "Z:\\a\\b", + "Z:b", + "\\", + "\\a\\/b\\/c\\", + "\\a\\b\\c\\", + "\\b", + "a", + "a.", + "a..txt", + "a.txt", + "a/b", + "a/b\\", + "c:/name", + "c:\\name", + "c:name", + "dir/", + "dir/.", + "dir/..", + "dir/../", + "dir/../b", + "dir/../b/../..///", + "dir/../b/..//..///../", + "dir/../sub/../name", + "dir/./", + "dir/.///b/../", + "dir/./b", + "dir/./b/.", + "dir/./b/..", + "dir/./sub/./name", + "dir///b", + "dir//b", + "dir/\\b", + "dir/b", + "dir/b.", + "dir/name", + "dir/name.", + "dir/name.tar.gz", + "dir/name.txt", + "dir/name.txt.", + "dir/name\\with\\backslashes", + "dir/sub/", + "dir/sub/.", + "dir/sub/..", + "dir/sub/../", + "dir/sub/../..", + "dir/sub/../../", + "dir/sub/../name", + "dir/sub/./", + "dir/sub/./..", + "dir/sub/./../", + "dir/sub/./name", + "dir/sub//", + "dir/sub///", + "dir/sub/name", + "dir/sub/suub/../..", + "dir/sub/suub/../../", + "dir/weird