#include "StdAfx.h" #include "tl/abs_path.h" #include "tl/rel_path.h" #include "tl/utest.h" #include "TestHelpers.h" #include "tl/abs_path_view.h" TL_DECLARE_STRING_LITERAL(posix_root_tag, "/"); TL_DECLARE_STRING_VECTOR(posix_parse_separators, "/"); TL_DECLARE_STRING_LITERAL(posix_format_separator, "/"); using posix_system = tl::simple_path_system; TL_DECLARE_STRING_LITERAL(unc_root_tag, "\\\\"); TL_DECLARE_STRING_VECTOR(unc_parse_separators, "\\", "/"); TL_DECLARE_STRING_LITERAL(unc_format_separator, "\\"); using unc_system = tl::simple_path_system; using test_abs_path = tl::abs_path>; using test_rel_path = test_abs_path::rel_path_type; using test_abs_path_view = tl::abs_path_view>; using test_rel_path_view = test_abs_path_view::rel_path_view_type; #define PATH_TEST_EQ(a, b) EXPECT_EQ(test_abs_path(a), test_abs_path(b)) UTEST(thread_safety, thread_safety) { std::thread thread1; std::thread thread2; thread1 = std::thread([] { test_rel_path path; for (volatile size_t i = 0; i < 1000; i++) { path = "a/b/c/d"; char result = 'a' + static_cast(i % 20); char buf[2] = { result , 0 }; path += (const char*)buf; } }); thread2 = std::thread([] { test_rel_path path; for (volatile size_t i = 0; i < 1000; i++) { path = "a/b/c/d"; char result = 'a' + static_cast(i % 20); char buf[2] = { result , 0 }; path += (const char*)buf; } }); if (thread1.joinable()) { thread1.join(); } if (thread2.joinable()) { thread2.join(); } } UTEST(Path, Path) { { test_abs_path path; EXPECT_TRUE(path.empty()); EXPECT_EQ(path.size(), 0); } { test_abs_path path("/a"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_TRUE(path.is()); EXPECT_EQ(path[0], "a"); test_abs_path path2("/a"); test_abs_path path3("/"); EXPECT_EQ(path, path2); EXPECT_NE(path, path3); test_abs_path path4("\\\\"); EXPECT_NE(path3, path4); } { test_abs_path path("/a/"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_TRUE(path.is()); EXPECT_EQ(path[0], "a"); } { test_abs_path path("\\\\a"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_TRUE(path.is()); EXPECT_EQ(path[0], "a"); } { test_abs_path path("\\\\a\\"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_TRUE(path.is()); EXPECT_EQ(path[0], "a"); } { test_abs_path path("/a/b"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 2); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); } { //Note - Here we test that the posix path only uses / as separator test_abs_path path("/a\\b"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_EQ(path[0], "a\\b"); } { test_abs_path path("/"); path += "a"; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 1); EXPECT_EQ(path[0], "a"); } { test_abs_path path; { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); path += "a"; } EXPECT_TRUE(path.empty()); EXPECT_EQ(path.size(), 0); } { test_abs_path path; path += "/a/b"; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 2); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); } { test_abs_path path; { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); path += "a"; } path += "/a/b"; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 2); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); } { test_abs_path path("\\\\"); path += "a"; path += "b/c/d"; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 4); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); EXPECT_EQ(path[3], "d"); } { test_abs_path path("/"); path += "a/b"; path += "c"; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 3); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); EXPECT_EQ(path[2], "c"); } { test_abs_path path("/"); path += ("a/b" + tl::string("/df")); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 3); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); EXPECT_EQ(path[2], "df"); } { test_abs_path path(tl::string("/")); path += "a/b"; path += "c"; path += ".."; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 2); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); path += "../.."; EXPECT_EQ(path.size(), 0); EXPECT_TRUE(path.empty()); EXPECT_TRUE(path.is()); } { test_abs_path path(tl::string("\\\\")); path += "a/b"; EXPECTED_ASSERT_GUARD("Invalid path"); path += "../../.."; EXPECT_TRUE(path.empty()); } { test_abs_path path(tl::string("\\\\")); EXPECTED_ASSERT_GUARD("Invalid path"); path.push_back(".."); EXPECT_TRUE(path.empty()); } { test_abs_path path(tl::string("/")); EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path newPath = path + "../.."; EXPECT_TRUE(newPath.empty()); } { test_abs_path path(tl::string("/")); EXPECTED_ASSERT_GUARD("Invalid path"); auto pathParent = path.parent(); EXPECT_TRUE(pathParent.empty()); } { test_abs_path path(tl::string("\\\\")); EXPECTED_ASSERT_GUARD("Invalid path"); auto pathParent = path.parent(); EXPECT_TRUE(pathParent.empty()); } { test_abs_path path(tl::string("/")); EXPECTED_ASSERT_GUARD("Invalid path"); auto pathParent = path.parent(); EXPECT_TRUE(pathParent.empty()); } { test_abs_path path(tl::string("/a/b/c/d")); test_abs_path newPath = path.parent(2); EXPECT_EQ(newPath, test_abs_path("/a/b")); } { test_abs_path path(tl::string("/a")); EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path newPath = path.parent(2); EXPECT_TRUE(newPath.empty()); } { test_abs_path path("/a/b/c/../d"); EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 3); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); EXPECT_EQ(path[2], "d"); path.push_back(".."); EXPECT_EQ(path.size(), 2); path.push_back("../.."); EXPECT_EQ(path.size(), 3); EXPECT_TRUE(path.is()); } { test_abs_path path("\\\\a/b/c/d"); auto p = path.subpath(0, 0); EXPECT_EQ(p, test_rel_path("a/b/c/d")); } { test_abs_path path("/a/b/c/d"); auto p = path.subpath(1, 0); EXPECT_EQ(p, test_rel_path("b/c/d")); } { test_abs_path path("\\\\a/b/c/d"); auto p = path.subpath(0, -1); EXPECT_EQ(p, test_rel_path("a/b/c")); } { test_abs_path path("/a/b/c/d"); auto p = path.subpath(0, 2); EXPECT_EQ(p, test_rel_path("a/b")); } { test_abs_path path("\\\\a/b/c"); auto p = path.parent(); EXPECT_EQ(p.str(), "\\\\a\\b"); } { test_abs_path path("/a"); auto p = path.parent(); EXPECT_EQ(p.str(), "/"); EXPECT_NE(p.str(), "\\\\"); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path path(".."); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path path("."); } { EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path path(""); auto p = path.parent(); EXPECT_TRUE(p.empty()); } { test_abs_path path("/a/b/../c"); auto p = path.parent(); EXPECT_EQ(p.str(), "/a"); } { test_abs_path path("/a/b/c/d"); path.shrink(2); EXPECT_EQ(path, test_abs_path("/a/b")); } { test_abs_path path("/a/b/c/d"); EXPECT_EQ(path.back(), "d"); EXPECT_EQ(path.front(), "a"); } { test_abs_path from("/a/b/c/d"); test_abs_path to("/a/b/x/y"); auto rel = from.path_to(to); EXPECT_EQ(rel, test_rel_path("../../x/y")); rel += ".."; rel.collapse_path(); EXPECT_EQ(rel, test_rel_path("../../x")); test_abs_path path("/a/b/c/d"); path += rel; EXPECT_EQ(path, test_abs_path("/a/b/c/d/../../x")); } { test_abs_path from("/a/b"); test_abs_path to("/a/b/x/y"); auto rel = from.path_to(to); EXPECT_EQ(rel, test_rel_path("x/y")); } { test_abs_path from("/c/d"); test_abs_path to("/a/b/x/y"); auto rel = from.path_to(to); EXPECT_EQ(rel, test_rel_path("../../a/b/x/y")); } { test_abs_path p("/c/d/m/a/../s/d/a"); tl::string s = p.str(); EXPECT_EQ(s, "/c/d/m/s/d/a"); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path p("/../s/d/a"); EXPECT_TRUE(p.empty()); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path p("/s/../../d/a"); EXPECT_TRUE(p.empty()); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path p("/s/d/../../../a"); EXPECT_TRUE(p.empty()); } { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); test_abs_path p("\\\\../a"); EXPECT_TRUE(p.empty()); } { test_abs_path p("/c/d/m"); tl::string s = p.str(); EXPECT_EQ(s, "/c/d/m"); } { test_abs_path p("/foo/..bar"); tl::string s = p.str(); EXPECT_EQ(s, "/foo/..bar"); } { test_abs_path p("/foo/..."); tl::string s = p.str(); EXPECT_EQ(s, "/foo/..."); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "/a" }, test_abs_path("/b")); EXPECT_EQ(test_abs_path("/a"), path); EXPECT_NE(test_abs_path("/b"), path); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "a/b" }, test_abs_path("/x")); EXPECT_EQ(test_abs_path("/x/a/b"), path); } { EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path path = test_abs_path::from_string(tl::string_view{ ".." }, test_abs_path("/")); EXPECT_TRUE(path.empty()); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "../.." }, test_abs_path("/a/b/d")); EXPECT_TRUE(path.is_valid()); EXPECT_EQ(path, test_abs_path("/a")); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" }, test_abs_path("")); EXPECT_TRUE(path.is_valid()); EXPECT_EQ(path, test_abs_path("/bla")); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path("")); EXPECT_TRUE(!path.is_valid()); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path()); EXPECT_TRUE(!path.is_valid()); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }); EXPECT_TRUE(!path.is_valid()); } { test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" }); EXPECT_TRUE(path.is_valid()); EXPECT_EQ(path, test_abs_path("/bla")); } { test_abs_path p1 = test_abs_path("/a/bc/d"); test_abs_path p2 = test_abs_path("/a/bd"); EXPECT_LT(p1, p2); EXPECT_GE(p1, p1); EXPECT_GE(p2, p1); } } // non_member_tests ----------------------------------------------------------------// UTEST(non_member_tests, non_member_tests) { // test non-member functions, particularly operator overloads test_abs_path e, e2; tl::string es, es2; char acs[] = "a"; tl::string as(acs); test_rel_path a(as); char acs2[] = "a"; tl::string as2(acs2); test_rel_path a2(as2); char bcs[] = "b"; tl::string bs(bcs); test_rel_path b(bs); // swap a.swap(b); EXPECT_EQ(a.str(), "b"); EXPECT_EQ(b.str(), "a"); std::swap(a, b); EXPECT_EQ(a.str(), "a"); EXPECT_EQ(b.str(), "b"); // probe operator / PATH_TEST_EQ(test_abs_path("/") + ".", "/."); { EXPECTED_ASSERT_GUARD("Failed to parse abs path"); PATH_TEST_EQ(test_abs_path("/") + "..", "/.."); } { PATH_TEST_EQ(test_abs_path("/a") + "b", "/a/b"); { EXPECTED_ASSERT_GUARD("Invalid path"); PATH_TEST_EQ(test_abs_path("/") + "..", ""); } PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("bar"), "/foo/bar"); // path arg PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar"); // const char* arg PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("woo/bar").back(), "/foo/bar"); // const std::string & arg PATH_TEST_EQ(test_abs_path("/foo") + "..", "/"); PATH_TEST_EQ(test_abs_path("/f") + ".." + "b", "/b"); PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "..", "/foo"); PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "..", "/"); PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "blah", "/foo/blah"); PATH_TEST_EQ(test_abs_path("/f") + "b" + "..", "/f"); PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + "..", "/foo"); PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + ".." + "bletch", "/foo/bletch"); PATH_TEST_EQ(test_abs_path("/foo") + ".", "/foo"); PATH_TEST_EQ(test_abs_path("/foo") + "." + "bar", "/foo/bar"); PATH_TEST_EQ(test_abs_path("/foo") + "." + ".", "/foo"); PATH_TEST_EQ(test_abs_path("/foo") + "." + "..", "/"); { test_abs_path path(tl::string("/.")); EXPECTED_ASSERT_GUARD("Invalid path"); path += "./.."; EXPECT_TRUE(path.empty()); } { test_abs_path path(tl::string("/.")); EXPECTED_ASSERT_GUARD("Invalid path"); path += "../."; EXPECT_TRUE(path.empty()); } } // make sure basic_path overloads don't conflict with std::string overloads //TEST_CHECK(!(as < as)); //TEST_CHECK(!(as < acs)); //TEST_CHECK(!(acs < as)); // character set reality check before lexicographical tests EXPECT_LT(std::string("a.b"), std::string("a/b")); // verify compare is actually lexicographical // EXPECT_LT(path("a/b") < path("a.b")); EXPECT_EQ(test_abs_path("/a/b"), test_abs_path("/a///b")); EXPECT_EQ(test_abs_path("\\\\/a/b"), test_abs_path("\\\\a///b")); // operator == and != are implemented separately, so test separately test_abs_path p1("/fe/fi/fo/fum"); test_abs_path p2(p1); test_abs_path p3("/fe/fi/fo/fumm"); EXPECT_NE(p1.str(), p3.str()); // check each overload EXPECT_NE(p1, p3); EXPECT_NE(p1.str(), p3.str()); EXPECT_NE(p1.str(), p3.str().c_str()); p3 = p2; EXPECT_EQ(p1.str(), p3.str()); // check each overload EXPECT_EQ(p1, p3); EXPECT_EQ(p1.str(), p3.str()); EXPECT_EQ(p1.str(), p3.str().c_str()); } UTEST(is_prefix_tests, is_prefix_tests) { test_abs_path p1{ "\\\\windows" }; test_abs_path p2{ "\\\\windows\\system" }; test_abs_path p3{ "\\\\windows\\system32" }; test_abs_path p4{ "\\\\windows\\system32\\" }; test_abs_path w1{ "/windows" }; test_abs_path w2{ "/windows/" }; test_abs_path w3{ "/windows/system" }; test_abs_path w4{ "/windows/system32" }; test_abs_path w5{ "/windows/system32/" }; EXPECT_TRUE(p1.is_prefix_of(p2)); EXPECT_TRUE(!p2.is_prefix_of(p3)); EXPECT_TRUE(p3.is_prefix_of(p4)); EXPECT_TRUE(!p4.is_prefix_of(p1)); EXPECT_TRUE(w1.is_prefix_of(w2)); EXPECT_TRUE(w2.is_prefix_of(w3)); EXPECT_TRUE(w2.is_prefix_of(w4)); EXPECT_TRUE(!w3.is_prefix_of(w4)); EXPECT_TRUE(w4.is_prefix_of(w5)); } // composition_tests ----------------------------------------------------------------// // construction_tests ---------------------------------------------------------------// UTEST(construction_tests, construction_tests) { PATH_TEST_EQ("", ""); PATH_TEST_EQ("/", "/"); PATH_TEST_EQ("\\\\", "\\\\"); PATH_TEST_EQ("/foo", "/foo"); PATH_TEST_EQ("/foo/", "/foo/"); PATH_TEST_EQ("\\\\f/", "\\\\f/"); PATH_TEST_EQ("/foo/..", "/foo/.."); PATH_TEST_EQ("/foo/../", "/foo/../"); PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../.."); PATH_TEST_EQ("/foo/bar/../../", "/foo/bar/../../"); PATH_TEST_EQ("/f", "/f"); PATH_TEST_EQ("/foo/bar/", "/foo/bar/"); PATH_TEST_EQ("//foo//bar//", "//foo//bar//"); PATH_TEST_EQ("///foo///bar///", "///foo///bar///"); PATH_TEST_EQ("\\\\/foo\\/bar\\/", "\\\\/foo\\/bar\\/"); PATH_TEST_EQ("\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//"); PATH_TEST_EQ("\\\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//"); PATH_TEST_EQ("/foo/..", "/foo/.."); PATH_TEST_EQ("/foo/..bar", "/foo/..bar"); PATH_TEST_EQ("/f/../f", "/f/../f"); PATH_TEST_EQ("/f/..", "/f/.."); PATH_TEST_EQ("/foo/../bar", "/foo/../bar"); PATH_TEST_EQ("/foo/bar/..", "/foo/bar/.."); PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../.."); PATH_TEST_EQ("/foo/bar/../blah", "/foo/bar/../blah"); PATH_TEST_EQ("/f/../b", "/f/../b"); PATH_TEST_EQ("/f/b/..", "/f/b/.."); PATH_TEST_EQ("/f/b/../a", "/f/b/../a"); PATH_TEST_EQ("/foo/bar/blah/../..", "/foo/bar/blah/../.."); PATH_TEST_EQ("/foo/bar/blah/../../bletch", "/foo/bar/blah/../../bletch"); PATH_TEST_EQ("/...", "/..."); PATH_TEST_EQ("/....", "/...."); PATH_TEST_EQ("/foo/...", "/foo/..."); PATH_TEST_EQ("/abc.", "/abc."); PATH_TEST_EQ("/abc..", "/abc.."); PATH_TEST_EQ("/foo/abc.", "/foo/abc."); PATH_TEST_EQ("/foo/abc..", "/foo/abc.."); PATH_TEST_EQ("/.abc", "/.abc"); PATH_TEST_EQ("/a.c", "/a.c"); PATH_TEST_EQ("/..abc", "/..abc"); PATH_TEST_EQ("/a..c", "/a..c"); PATH_TEST_EQ("/foo/.abc", "/foo/.abc"); PATH_TEST_EQ("/foo/a.c", "/foo/a.c"); PATH_TEST_EQ("/foo/..abc", "/foo/..abc"); PATH_TEST_EQ("/foo/a..c", "/foo/a..c"); } // append_tests --------------------------------------------------------------------// static void append_test_aux(const test_abs_path& p, const tl::string& s, const tl::string& expect, int* utest_result) { PATH_TEST_EQ((p + s.c_str()).str(), expect); PATH_TEST_EQ((p + s).str(), expect); // path x(p); // x.append(s.begin(), s.end()); // PATH_TEST_EQ(x.str(), expect); } UTEST(append_tests, append_tests) { // There are many control paths to be exercised, since empty paths and arguments, // paths with trailing separators, arguments with leading separators, with or without // other characters being present, are all separate cases that need to be tested. // Furthermore, some of the code to be tested is specific to argument categories, // so that results in further permutations to be tested. //// code to generate test cases //// //// expected results must be checked by hand //// "foo\bar" expected result must be edited by hand and moved for Windows/POSIX //// //const char* x[] = { "", "/", "foo", "foo/" }; //const char* y[] = { "", "/", "bar", "/bar" }; //for (int i = 0; i < sizeof(x)/sizeof(char*); ++i) // for (int j = 0; j < sizeof(y)/sizeof(char*); ++j) // { // std::cout << "\n PATH_TEST_EQ(path(\"" << x[i] << "\") + \"" << y[j] << "\", \"" // << path(x[i]) + y[j] << "\");\n"; // std::cout << " append_test_aux(\"" << x[i] << "\", \"" << y[j] << "\", \"" // << path(x[i]) + y[j] << "\");\n"; // } PATH_TEST_EQ(test_abs_path("") + "", ""); // append_test_aux(test_abs_path(""), "", ""); test_abs_path abs = test_abs_path("") + "/"; test_abs_path abs1 = test_abs_path(abs); test_abs_path abs2 = test_abs_path("/") + "/"; PATH_TEST_EQ(test_abs_path("") + "/", "/"); append_test_aux(test_abs_path(""), "/", "/", utest_result); PATH_TEST_EQ(test_abs_path("") + "/bar", "/bar"); append_test_aux(test_abs_path(""), "/bar", "/bar", utest_result); PATH_TEST_EQ(test_abs_path("/") + "", "/"); append_test_aux(test_abs_path("/"), "", "/", utest_result); PATH_TEST_EQ(test_abs_path("/") + "/", "//"); append_test_aux(test_abs_path("/"), "/", "//", utest_result); PATH_TEST_EQ(test_abs_path("/") + "bar", "/bar"); append_test_aux(test_abs_path("/"), "bar", "/bar", utest_result); PATH_TEST_EQ(test_abs_path("/") + "/bar", "//bar"); append_test_aux(test_abs_path("/"), "/bar", "//bar", utest_result); PATH_TEST_EQ(test_abs_path("/foo") + "", "/foo"); append_test_aux(test_abs_path("/foo"), "", "/foo", utest_result); PATH_TEST_EQ(test_abs_path("/foo") + "/", "/foo/"); append_test_aux(test_abs_path("/foo"), "/", "/foo/", utest_result); PATH_TEST_EQ(test_abs_path("/foo") + "/bar", "/foo/bar"); append_test_aux(test_abs_path("/foo"), "/bar", "/foo/bar", utest_result); PATH_TEST_EQ(test_abs_path("/foo/") + "", "/foo/"); append_test_aux(test_abs_path("/foo/"), "", "/foo/", utest_result); PATH_TEST_EQ(test_abs_path("/foo/") + "/", "/foo//"); append_test_aux(test_abs_path("/foo/"), "/", "/foo//", utest_result); PATH_TEST_EQ(test_abs_path("/foo/") + "bar", "/foo/bar"); append_test_aux(test_abs_path("/foo/"), "bar", "/foo/bar", utest_result); PATH_TEST_EQ(test_abs_path("/foo/") + "/bar", "/foo//bar"); append_test_aux(test_abs_path("/foo/"), "/bar", "/foo//bar", utest_result); { PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar"); append_test_aux(test_abs_path("/foo"), "bar", "/foo/bar", utest_result); } // ticket #6819 union { char a[1]; char b[3]; } u; u.b[0] = '/'; u.b[1] = 'a'; u.b[2] = '\0'; test_abs_path p6819; p6819 += (const char*)u.a; EXPECT_EQ(p6819, test_abs_path("/a")); } // self_assign_and_append_tests ------------------------------------------------------// UTEST(self_assign_and_append_tests, self_assign_and_append_tests) { test_abs_path p; p = "/snafubar"; PATH_TEST_EQ(p = p, "/snafubar"); p = "/snafubar"; p = p.str().c_str(); PATH_TEST_EQ(p, "/snafubar"); // p = "snafubar"; // p.assign(p.str().c_str(), path::codecvt()); // PATH_TEST_EQ(p, "snafubar"); p = "/snafu/bar"; PATH_TEST_EQ(p = p.str().c_str() + 6, "/bar"); // p = "snafubar"; // PATH_TEST_EQ(p.assign(p.c_str() + 5, p.c_str() + 7), "ba"); p = "/snafubar"; p += p.str().c_str(); PATH_TEST_EQ(p, "/snafubar/snafubar"); // p = "snafubar"; // p.append(p.c_str()); // PATH_TEST_EQ(p, "snafubar/snafubar"); // p = "snafubar"; // PATH_TEST_EQ(p.append(p.c_str() + 5, p.c_str() + 7), "snafubar" BOOST_DIR_SEP "ba"); } UTEST(PathView, PathView) { { test_abs_path path; test_abs_path_view pathView = path; EXPECT_TRUE(pathView.empty()); EXPECT_FALSE(pathView.is_valid()); EXPECT_EQ(pathView.size(), 0); EXPECT_EQ(pathView.hash(), path.hash()); } { test_abs_path path("/caca/maca"); test_abs_path_view pathView = path; EXPECT_FALSE(pathView.empty()); EXPECT_TRUE(pathView.is_valid()); EXPECT_EQ(pathView.size(), path.size()); EXPECT_EQ(pathView.hash(), path.hash()); } { test_abs_path path("/caca/maca"); test_abs_path_view pathView = path; pathView.pop_back(); EXPECT_FALSE(pathView.empty()); EXPECT_TRUE(pathView.is_valid()); EXPECT_EQ(pathView.size(), path.size() - 1); EXPECT_EQ(pathView.str(), "/caca"); EXPECT_EQ(pathView.hash(), test_abs_path("/caca").hash()); EXPECT_EQ(pathView.hash(), test_abs_path(pathView).hash()); } { test_abs_path path("/a"); test_abs_path_view pathView = path; EXPECT_TRUE(!pathView.empty()); EXPECT_EQ(pathView.size(), 1); EXPECT_TRUE(pathView.is()); EXPECT_EQ(pathView[0], "a"); test_abs_path path2("/a"); test_abs_path_view pathView2 = path2; test_abs_path path3("/"); test_abs_path_view pathView3 = path3; EXPECT_EQ(pathView, pathView2); EXPECT_NE(pathView, pathView3); test_abs_path path4("\\\\"); test_abs_path_view pathView4(path4); EXPECT_NE(pathView3, pathView4); } { test_abs_path path("\\\\a"); test_abs_path_view pathView(path); EXPECT_TRUE(!pathView.empty()); EXPECT_EQ(pathView.size(), 1); EXPECT_TRUE(pathView.is()); EXPECT_EQ(pathView[0], "a"); } { test_abs_path path("/a/b"); test_abs_path_view pathView(path); EXPECT_TRUE(!pathView.empty()); EXPECT_EQ(pathView.size(), 2); EXPECT_EQ(pathView[0], "a"); EXPECT_EQ(pathView[1], "b"); } //xxx { test_abs_path path(tl::string("/")); path += "a/b"; path += "c"; path += ".."; EXPECT_TRUE(!path.empty()); EXPECT_EQ(path.size(), 2); EXPECT_EQ(path[0], "a"); EXPECT_EQ(path[1], "b"); path += "../.."; EXPECT_EQ(path.size(), 0); EXPECT_TRUE(path.empty()); EXPECT_TRUE(path.is()); } //xxx { test_abs_path path(tl::string("\\\\")); path += "a/b"; EXPECTED_ASSERT_GUARD("Invalid path"); path += "../../.."; EXPECT_TRUE(path.empty()); } //xxx { test_abs_path path(tl::string("\\\\")); EXPECTED_ASSERT_GUARD("Invalid path"); path.push_back(".."); EXPECT_TRUE(path.empty()); } //xxx { test_abs_path path(tl::string("/")); EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path newPath = path + "../.."; EXPECT_TRUE(newPath.empty()); } { EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path path(tl::string("/")); test_abs_path_view pathView(path); auto pathParentView = pathView.parent(); EXPECT_TRUE(pathParentView.empty()); } { test_abs_path path(tl::string("/a/b/c/d")); test_abs_path_view pathView(path); test_abs_path_view newPathView = pathView.parent(2); EXPECT_EQ(newPathView.str(), "/a/b"); } { EXPECTED_ASSERT_GUARD("Invalid path"); test_abs_path path(tl::string("/a")); test_abs_path_view pathView(path); test_abs_path_view newPathView = pathView.parent(2); EXPECT_TRUE(newPathView.empty()); } //{ // test_abs_path path("\\\\a/b/c/d"); // auto p = path.subpath(0, 0); // EXPECT_EQ(p, test_rel_path("a/b/c/d")); //} //{ // test_abs_path path("/a/b/c/d"); // auto p = path.subpath(1, 0); // EXPECT_EQ(p, test_rel_path("b/c/d")); //} //{ // test_abs_path path("\\\\a/b/c/d"); // auto p = path.subpath(0, -1); // EXPECT_EQ(p, test_rel_path("a/b/c")); //} //{ // test_abs_path path("/a/b/c/d"); // auto p = path.subpath(0, 2); // EXPECT_EQ(p, test_rel_path("a/b")); //} { test_abs_path path("\\\\a/b/c"); auto p = path.parent(); EXPECT_EQ(p, test_abs_path("\\\\a/b")); } { test_abs_path path("/a"); auto p = path.parent(); EXPECT_EQ(p, test_abs_path("/")); EXPECT_NE(p, test_abs_path("\\\\")); } { test_abs_path path("/a/b/../c"); auto p = path.parent(); EXPECT_EQ(p, test_abs_path("/a")); } }