1 //===- llvm/unittest/Support/Path.cpp - Path tests ------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Support/Path.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/ScopeExit.h" 12 #include "llvm/ADT/SmallVector.h" 13 #include "llvm/ADT/Triple.h" 14 #include "llvm/BinaryFormat/Magic.h" 15 #include "llvm/Config/llvm-config.h" 16 #include "llvm/Support/Compiler.h" 17 #include "llvm/Support/ConvertUTF.h" 18 #include "llvm/Support/Errc.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/FileUtilities.h" 22 #include "llvm/Support/Host.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include "llvm/Testing/Support/Error.h" 26 #include "gmock/gmock.h" 27 #include "gtest/gtest.h" 28 29 #ifdef _WIN32 30 #include "llvm/ADT/ArrayRef.h" 31 #include "llvm/Support/Chrono.h" 32 #include "llvm/Support/Windows/WindowsSupport.h" 33 #include <windows.h> 34 #include <winerror.h> 35 #endif 36 37 #ifdef LLVM_ON_UNIX 38 #include <pwd.h> 39 #include <sys/stat.h> 40 #endif 41 42 using namespace llvm; 43 using namespace llvm::sys; 44 45 #define ASSERT_NO_ERROR(x) \ 46 if (std::error_code ASSERT_NO_ERROR_ec = x) { \ 47 SmallString<128> MessageStorage; \ 48 raw_svector_ostream Message(MessageStorage); \ 49 Message << #x ": did not return errc::success.\n" \ 50 << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ 51 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ 52 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ 53 } else { \ 54 } 55 56 #define ASSERT_ERROR(x) \ 57 if (!x) { \ 58 SmallString<128> MessageStorage; \ 59 raw_svector_ostream Message(MessageStorage); \ 60 Message << #x ": did not return a failure error code.\n"; \ 61 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ 62 } 63 64 namespace { 65 66 struct FileDescriptorCloser { 67 explicit FileDescriptorCloser(int FD) : FD(FD) {} 68 ~FileDescriptorCloser() { ::close(FD); } 69 int FD; 70 }; 71 72 TEST(is_separator, Works) { 73 EXPECT_TRUE(path::is_separator('/')); 74 EXPECT_FALSE(path::is_separator('\0')); 75 EXPECT_FALSE(path::is_separator('-')); 76 EXPECT_FALSE(path::is_separator(' ')); 77 78 EXPECT_TRUE(path::is_separator('\\', path::Style::windows)); 79 EXPECT_FALSE(path::is_separator('\\', path::Style::posix)); 80 81 #ifdef _WIN32 82 EXPECT_TRUE(path::is_separator('\\')); 83 #else 84 EXPECT_FALSE(path::is_separator('\\')); 85 #endif 86 } 87 88 TEST(Support, Path) { 89 SmallVector<StringRef, 40> paths; 90 paths.push_back(""); 91 paths.push_back("."); 92 paths.push_back(".."); 93 paths.push_back("foo"); 94 paths.push_back("/"); 95 paths.push_back("/foo"); 96 paths.push_back("foo/"); 97 paths.push_back("/foo/"); 98 paths.push_back("foo/bar"); 99 paths.push_back("/foo/bar"); 100 paths.push_back("//net"); 101 paths.push_back("//net/"); 102 paths.push_back("//net/foo"); 103 paths.push_back("///foo///"); 104 paths.push_back("///foo///bar"); 105 paths.push_back("/."); 106 paths.push_back("./"); 107 paths.push_back("/.."); 108 paths.push_back("../"); 109 paths.push_back("foo/."); 110 paths.push_back("foo/.."); 111 paths.push_back("foo/./"); 112 paths.push_back("foo/./bar"); 113 paths.push_back("foo/.."); 114 paths.push_back("foo/../"); 115 paths.push_back("foo/../bar"); 116 paths.push_back("c:"); 117 paths.push_back("c:/"); 118 paths.push_back("c:foo"); 119 paths.push_back("c:/foo"); 120 paths.push_back("c:foo/"); 121 paths.push_back("c:/foo/"); 122 paths.push_back("c:/foo/bar"); 123 paths.push_back("prn:"); 124 paths.push_back("c:\\"); 125 paths.push_back("c:foo"); 126 paths.push_back("c:\\foo"); 127 paths.push_back("c:foo\\"); 128 paths.push_back("c:\\foo\\"); 129 paths.push_back("c:\\foo/"); 130 paths.push_back("c:/foo\\bar"); 131 132 for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(), 133 e = paths.end(); 134 i != e; 135 ++i) { 136 SCOPED_TRACE(*i); 137 SmallVector<StringRef, 5> ComponentStack; 138 for (sys::path::const_iterator ci = sys::path::begin(*i), 139 ce = sys::path::end(*i); 140 ci != ce; 141 ++ci) { 142 EXPECT_FALSE(ci->empty()); 143 ComponentStack.push_back(*ci); 144 } 145 146 SmallVector<StringRef, 5> ReverseComponentStack; 147 for (sys::path::reverse_iterator ci = sys::path::rbegin(*i), 148 ce = sys::path::rend(*i); 149 ci != ce; 150 ++ci) { 151 EXPECT_FALSE(ci->empty()); 152 ReverseComponentStack.push_back(*ci); 153 } 154 std::reverse(ReverseComponentStack.begin(), ReverseComponentStack.end()); 155 EXPECT_THAT(ComponentStack, testing::ContainerEq(ReverseComponentStack)); 156 157 // Crash test most of the API - since we're iterating over all of our paths 158 // here there isn't really anything reasonable to assert on in the results. 159 (void)path::has_root_path(*i); 160 (void)path::root_path(*i); 161 (void)path::has_root_name(*i); 162 (void)path::root_name(*i); 163 (void)path::has_root_directory(*i); 164 (void)path::root_directory(*i); 165 (void)path::has_parent_path(*i); 166 (void)path::parent_path(*i); 167 (void)path::has_filename(*i); 168 (void)path::filename(*i); 169 (void)path::has_stem(*i); 170 (void)path::stem(*i); 171 (void)path::has_extension(*i); 172 (void)path::extension(*i); 173 (void)path::is_absolute(*i); 174 (void)path::is_relative(*i); 175 176 SmallString<128> temp_store; 177 temp_store = *i; 178 ASSERT_NO_ERROR(fs::make_absolute(temp_store)); 179 temp_store = *i; 180 path::remove_filename(temp_store); 181 182 temp_store = *i; 183 path::replace_extension(temp_store, "ext"); 184 StringRef filename(temp_store.begin(), temp_store.size()), stem, ext; 185 stem = path::stem(filename); 186 ext = path::extension(filename); 187 EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str()); 188 189 path::native(*i, temp_store); 190 } 191 192 { 193 SmallString<32> Relative("foo.cpp"); 194 sys::fs::make_absolute("/root", Relative); 195 Relative[5] = '/'; // Fix up windows paths. 196 ASSERT_EQ("/root/foo.cpp", Relative); 197 } 198 199 { 200 SmallString<32> Relative("foo.cpp"); 201 sys::fs::make_absolute("//root", Relative); 202 Relative[6] = '/'; // Fix up windows paths. 203 ASSERT_EQ("//root/foo.cpp", Relative); 204 } 205 } 206 207 TEST(Support, FilenameParent) { 208 EXPECT_EQ("/", path::filename("/")); 209 EXPECT_EQ("", path::parent_path("/")); 210 211 EXPECT_EQ("\\", path::filename("c:\\", path::Style::windows)); 212 EXPECT_EQ("c:", path::parent_path("c:\\", path::Style::windows)); 213 214 EXPECT_EQ("/", path::filename("///")); 215 EXPECT_EQ("", path::parent_path("///")); 216 217 EXPECT_EQ("\\", path::filename("c:\\\\", path::Style::windows)); 218 EXPECT_EQ("c:", path::parent_path("c:\\\\", path::Style::windows)); 219 220 EXPECT_EQ("bar", path::filename("/foo/bar")); 221 EXPECT_EQ("/foo", path::parent_path("/foo/bar")); 222 223 EXPECT_EQ("foo", path::filename("/foo")); 224 EXPECT_EQ("/", path::parent_path("/foo")); 225 226 EXPECT_EQ("foo", path::filename("foo")); 227 EXPECT_EQ("", path::parent_path("foo")); 228 229 EXPECT_EQ(".", path::filename("foo/")); 230 EXPECT_EQ("foo", path::parent_path("foo/")); 231 232 EXPECT_EQ("//net", path::filename("//net")); 233 EXPECT_EQ("", path::parent_path("//net")); 234 235 EXPECT_EQ("/", path::filename("//net/")); 236 EXPECT_EQ("//net", path::parent_path("//net/")); 237 238 EXPECT_EQ("foo", path::filename("//net/foo")); 239 EXPECT_EQ("//net/", path::parent_path("//net/foo")); 240 241 // These checks are just to make sure we do something reasonable with the 242 // paths below. They are not meant to prescribe the one true interpretation of 243 // these paths. Other decompositions (e.g. "//" -> "" + "//") are also 244 // possible. 245 EXPECT_EQ("/", path::filename("//")); 246 EXPECT_EQ("", path::parent_path("//")); 247 248 EXPECT_EQ("\\", path::filename("\\\\", path::Style::windows)); 249 EXPECT_EQ("", path::parent_path("\\\\", path::Style::windows)); 250 251 EXPECT_EQ("\\", path::filename("\\\\\\", path::Style::windows)); 252 EXPECT_EQ("", path::parent_path("\\\\\\", path::Style::windows)); 253 } 254 255 static std::vector<StringRef> 256 GetComponents(StringRef Path, path::Style S = path::Style::native) { 257 return {path::begin(Path, S), path::end(Path)}; 258 } 259 260 TEST(Support, PathIterator) { 261 EXPECT_THAT(GetComponents("/foo"), testing::ElementsAre("/", "foo")); 262 EXPECT_THAT(GetComponents("/"), testing::ElementsAre("/")); 263 EXPECT_THAT(GetComponents("//"), testing::ElementsAre("/")); 264 EXPECT_THAT(GetComponents("///"), testing::ElementsAre("/")); 265 EXPECT_THAT(GetComponents("c/d/e/foo.txt"), 266 testing::ElementsAre("c", "d", "e", "foo.txt")); 267 EXPECT_THAT(GetComponents(".c/.d/../."), 268 testing::ElementsAre(".c", ".d", "..", ".")); 269 EXPECT_THAT(GetComponents("/c/d/e/foo.txt"), 270 testing::ElementsAre("/", "c", "d", "e", "foo.txt")); 271 EXPECT_THAT(GetComponents("/.c/.d/../."), 272 testing::ElementsAre("/", ".c", ".d", "..", ".")); 273 EXPECT_THAT(GetComponents("c:\\c\\e\\foo.txt", path::Style::windows), 274 testing::ElementsAre("c:", "\\", "c", "e", "foo.txt")); 275 EXPECT_THAT(GetComponents("//net/"), testing::ElementsAre("//net", "/")); 276 EXPECT_THAT(GetComponents("//net/c/foo.txt"), 277 testing::ElementsAre("//net", "/", "c", "foo.txt")); 278 } 279 280 TEST(Support, AbsolutePathIteratorEnd) { 281 // Trailing slashes are converted to '.' unless they are part of the root path. 282 SmallVector<std::pair<StringRef, path::Style>, 4> Paths; 283 Paths.emplace_back("/foo/", path::Style::native); 284 Paths.emplace_back("/foo//", path::Style::native); 285 Paths.emplace_back("//net/foo/", path::Style::native); 286 Paths.emplace_back("c:\\foo\\", path::Style::windows); 287 288 for (auto &Path : Paths) { 289 SCOPED_TRACE(Path.first); 290 StringRef LastComponent = *path::rbegin(Path.first, Path.second); 291 EXPECT_EQ(".", LastComponent); 292 } 293 294 SmallVector<std::pair<StringRef, path::Style>, 3> RootPaths; 295 RootPaths.emplace_back("/", path::Style::native); 296 RootPaths.emplace_back("//net/", path::Style::native); 297 RootPaths.emplace_back("c:\\", path::Style::windows); 298 RootPaths.emplace_back("//net//", path::Style::native); 299 RootPaths.emplace_back("c:\\\\", path::Style::windows); 300 301 for (auto &Path : RootPaths) { 302 SCOPED_TRACE(Path.first); 303 StringRef LastComponent = *path::rbegin(Path.first, Path.second); 304 EXPECT_EQ(1u, LastComponent.size()); 305 EXPECT_TRUE(path::is_separator(LastComponent[0], Path.second)); 306 } 307 } 308 309 #ifdef _WIN32 310 std::string getEnvWin(const wchar_t *Var) { 311 std::string expected; 312 if (wchar_t const *path = ::_wgetenv(Var)) { 313 auto pathLen = ::wcslen(path); 314 ArrayRef<char> ref{reinterpret_cast<char const *>(path), 315 pathLen * sizeof(wchar_t)}; 316 convertUTF16ToUTF8String(ref, expected); 317 } 318 return expected; 319 } 320 #else 321 // RAII helper to set and restore an environment variable. 322 class WithEnv { 323 const char *Var; 324 llvm::Optional<std::string> OriginalValue; 325 326 public: 327 WithEnv(const char *Var, const char *Value) : Var(Var) { 328 if (const char *V = ::getenv(Var)) 329 OriginalValue.emplace(V); 330 if (Value) 331 ::setenv(Var, Value, 1); 332 else 333 ::unsetenv(Var); 334 } 335 ~WithEnv() { 336 if (OriginalValue) 337 ::setenv(Var, OriginalValue->c_str(), 1); 338 else 339 ::unsetenv(Var); 340 } 341 }; 342 #endif 343 344 TEST(Support, HomeDirectory) { 345 std::string expected; 346 #ifdef _WIN32 347 expected = getEnvWin(L"USERPROFILE"); 348 #else 349 if (char const *path = ::getenv("HOME")) 350 expected = path; 351 #endif 352 // Do not try to test it if we don't know what to expect. 353 // On Windows we use something better than env vars. 354 if (!expected.empty()) { 355 SmallString<128> HomeDir; 356 auto status = path::home_directory(HomeDir); 357 EXPECT_TRUE(status); 358 EXPECT_EQ(expected, HomeDir); 359 } 360 } 361 362 #ifdef LLVM_ON_UNIX 363 TEST(Support, HomeDirectoryWithNoEnv) { 364 WithEnv Env("HOME", nullptr); 365 366 // Don't run the test if we have nothing to compare against. 367 struct passwd *pw = getpwuid(getuid()); 368 if (!pw || !pw->pw_dir) return; 369 std::string PwDir = pw->pw_dir; 370 371 SmallString<128> HomeDir; 372 EXPECT_TRUE(path::home_directory(HomeDir)); 373 EXPECT_EQ(PwDir, HomeDir); 374 } 375 376 TEST(Support, CacheDirectoryWithEnv) { 377 WithEnv Env("XDG_CACHE_HOME", "/xdg/cache"); 378 379 SmallString<128> CacheDir; 380 EXPECT_TRUE(path::cache_directory(CacheDir)); 381 EXPECT_EQ("/xdg/cache", CacheDir); 382 } 383 384 TEST(Support, CacheDirectoryNoEnv) { 385 WithEnv Env("XDG_CACHE_HOME", nullptr); 386 387 SmallString<128> Fallback; 388 ASSERT_TRUE(path::home_directory(Fallback)); 389 path::append(Fallback, ".cache"); 390 391 SmallString<128> CacheDir; 392 EXPECT_TRUE(path::cache_directory(CacheDir)); 393 EXPECT_EQ(Fallback, CacheDir); 394 } 395 #endif 396 397 #ifdef _WIN32 398 TEST(Support, CacheDirectory) { 399 std::string Expected = getEnvWin(L"LOCALAPPDATA"); 400 // Do not try to test it if we don't know what to expect. 401 if (!Expected.empty()) { 402 SmallString<128> CacheDir; 403 EXPECT_TRUE(path::cache_directory(CacheDir)); 404 EXPECT_EQ(Expected, CacheDir); 405 } 406 } 407 #endif 408 409 TEST(Support, TempDirectory) { 410 SmallString<32> TempDir; 411 path::system_temp_directory(false, TempDir); 412 EXPECT_TRUE(!TempDir.empty()); 413 TempDir.clear(); 414 path::system_temp_directory(true, TempDir); 415 EXPECT_TRUE(!TempDir.empty()); 416 } 417 418 #ifdef _WIN32 419 static std::string path2regex(std::string Path) { 420 size_t Pos = 0; 421 while ((Pos = Path.find('\\', Pos)) != std::string::npos) { 422 Path.replace(Pos, 1, "\\\\"); 423 Pos += 2; 424 } 425 return Path; 426 } 427 428 /// Helper for running temp dir test in separated process. See below. 429 #define EXPECT_TEMP_DIR(prepare, expected) \ 430 EXPECT_EXIT( \ 431 { \ 432 prepare; \ 433 SmallString<300> TempDir; \ 434 path::system_temp_directory(true, TempDir); \ 435 raw_os_ostream(std::cerr) << TempDir; \ 436 std::exit(0); \ 437 }, \ 438 ::testing::ExitedWithCode(0), path2regex(expected)) 439 440 TEST(SupportDeathTest, TempDirectoryOnWindows) { 441 // In this test we want to check how system_temp_directory responds to 442 // different values of specific env vars. To prevent corrupting env vars of 443 // the current process all checks are done in separated processes. 444 EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"C:\\OtherFolder"), "C:\\OtherFolder"); 445 EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"C:/Unix/Path/Seperators"), 446 "C:\\Unix\\Path\\Seperators"); 447 EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"Local Path"), ".+\\Local Path$"); 448 EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"F:\\TrailingSep\\"), "F:\\TrailingSep"); 449 EXPECT_TEMP_DIR( 450 _wputenv_s(L"TMP", L"C:\\2\x03C0r-\x00B5\x00B3\\\x2135\x2080"), 451 "C:\\2\xCF\x80r-\xC2\xB5\xC2\xB3\\\xE2\x84\xB5\xE2\x82\x80"); 452 453 // Test $TMP empty, $TEMP set. 454 EXPECT_TEMP_DIR( 455 { 456 _wputenv_s(L"TMP", L""); 457 _wputenv_s(L"TEMP", L"C:\\Valid\\Path"); 458 }, 459 "C:\\Valid\\Path"); 460 461 // All related env vars empty 462 EXPECT_TEMP_DIR( 463 { 464 _wputenv_s(L"TMP", L""); 465 _wputenv_s(L"TEMP", L""); 466 _wputenv_s(L"USERPROFILE", L""); 467 }, 468 "C:\\Temp"); 469 470 // Test evn var / path with 260 chars. 471 SmallString<270> Expected{"C:\\Temp\\AB\\123456789"}; 472 while (Expected.size() < 260) 473 Expected.append("\\DirNameWith19Charss"); 474 ASSERT_EQ(260U, Expected.size()); 475 EXPECT_TEMP_DIR(_putenv_s("TMP", Expected.c_str()), Expected.c_str()); 476 } 477 #endif 478 479 class FileSystemTest : public testing::Test { 480 protected: 481 /// Unique temporary directory in which all created filesystem entities must 482 /// be placed. It is removed at the end of each test (must be empty). 483 SmallString<128> TestDirectory; 484 SmallString<128> NonExistantFile; 485 486 void SetUp() override { 487 ASSERT_NO_ERROR( 488 fs::createUniqueDirectory("file-system-test", TestDirectory)); 489 // We don't care about this specific file. 490 errs() << "Test Directory: " << TestDirectory << '\n'; 491 errs().flush(); 492 NonExistantFile = TestDirectory; 493 494 // Even though this value is hardcoded, is a 128-bit GUID, so we should be 495 // guaranteed that this file will never exist. 496 sys::path::append(NonExistantFile, "1B28B495C16344CB9822E588CD4C3EF0"); 497 } 498 499 void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } 500 }; 501 502 TEST_F(FileSystemTest, Unique) { 503 // Create a temp file. 504 int FileDescriptor; 505 SmallString<64> TempPath; 506 ASSERT_NO_ERROR( 507 fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); 508 509 // The same file should return an identical unique id. 510 fs::UniqueID F1, F2; 511 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F1)); 512 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F2)); 513 ASSERT_EQ(F1, F2); 514 515 // Different files should return different unique ids. 516 int FileDescriptor2; 517 SmallString<64> TempPath2; 518 ASSERT_NO_ERROR( 519 fs::createTemporaryFile("prefix", "temp", FileDescriptor2, TempPath2)); 520 521 fs::UniqueID D; 522 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D)); 523 ASSERT_NE(D, F1); 524 ::close(FileDescriptor2); 525 526 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); 527 528 // Two paths representing the same file on disk should still provide the 529 // same unique id. We can test this by making a hard link. 530 ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); 531 fs::UniqueID D2; 532 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2)); 533 ASSERT_EQ(D2, F1); 534 535 ::close(FileDescriptor); 536 537 SmallString<128> Dir1; 538 ASSERT_NO_ERROR( 539 fs::createUniqueDirectory("dir1", Dir1)); 540 ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F1)); 541 ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F2)); 542 ASSERT_EQ(F1, F2); 543 544 SmallString<128> Dir2; 545 ASSERT_NO_ERROR( 546 fs::createUniqueDirectory("dir2", Dir2)); 547 ASSERT_NO_ERROR(fs::getUniqueID(Dir2.c_str(), F2)); 548 ASSERT_NE(F1, F2); 549 ASSERT_NO_ERROR(fs::remove(Dir1)); 550 ASSERT_NO_ERROR(fs::remove(Dir2)); 551 ASSERT_NO_ERROR(fs::remove(TempPath2)); 552 ASSERT_NO_ERROR(fs::remove(TempPath)); 553 } 554 555 TEST_F(FileSystemTest, RealPath) { 556 ASSERT_NO_ERROR( 557 fs::create_directories(Twine(TestDirectory) + "/test1/test2/test3")); 558 ASSERT_TRUE(fs::exists(Twine(TestDirectory) + "/test1/test2/test3")); 559 560 SmallString<64> RealBase; 561 SmallString<64> Expected; 562 SmallString<64> Actual; 563 564 // TestDirectory itself might be under a symlink or have been specified with 565 // a different case than the existing temp directory. In such cases real_path 566 // on the concatenated path will differ in the TestDirectory portion from 567 // how we specified it. Make sure to compare against the real_path of the 568 // TestDirectory, and not just the value of TestDirectory. 569 ASSERT_NO_ERROR(fs::real_path(TestDirectory, RealBase)); 570 path::native(Twine(RealBase) + "/test1/test2", Expected); 571 572 ASSERT_NO_ERROR(fs::real_path( 573 Twine(TestDirectory) + "/././test1/../test1/test2/./test3/..", Actual)); 574 575 EXPECT_EQ(Expected, Actual); 576 577 SmallString<64> HomeDir; 578 579 // This can fail if $HOME is not set and getpwuid fails. 580 bool Result = llvm::sys::path::home_directory(HomeDir); 581 if (Result) { 582 ASSERT_NO_ERROR(fs::real_path(HomeDir, Expected)); 583 ASSERT_NO_ERROR(fs::real_path("~", Actual, true)); 584 EXPECT_EQ(Expected, Actual); 585 ASSERT_NO_ERROR(fs::real_path("~/", Actual, true)); 586 EXPECT_EQ(Expected, Actual); 587 } 588 589 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1")); 590 } 591 592 TEST_F(FileSystemTest, ExpandTilde) { 593 SmallString<64> Expected; 594 SmallString<64> Actual; 595 SmallString<64> HomeDir; 596 597 // This can fail if $HOME is not set and getpwuid fails. 598 bool Result = llvm::sys::path::home_directory(HomeDir); 599 if (Result) { 600 fs::expand_tilde(HomeDir, Expected); 601 602 fs::expand_tilde("~", Actual); 603 EXPECT_EQ(Expected, Actual); 604 605 #ifdef _WIN32 606 Expected += "\\foo"; 607 fs::expand_tilde("~\\foo", Actual); 608 #else 609 Expected += "/foo"; 610 fs::expand_tilde("~/foo", Actual); 611 #endif 612 613 EXPECT_EQ(Expected, Actual); 614 } 615 } 616 617 #ifdef LLVM_ON_UNIX 618 TEST_F(FileSystemTest, RealPathNoReadPerm) { 619 SmallString<64> Expanded; 620 621 ASSERT_NO_ERROR( 622 fs::create_directories(Twine(TestDirectory) + "/noreadperm")); 623 ASSERT_TRUE(fs::exists(Twine(TestDirectory) + "/noreadperm")); 624 625 fs::setPermissions(Twine(TestDirectory) + "/noreadperm", fs::no_perms); 626 fs::setPermissions(Twine(TestDirectory) + "/noreadperm", fs::all_exe); 627 628 ASSERT_NO_ERROR(fs::real_path(Twine(TestDirectory) + "/noreadperm", Expanded, 629 false)); 630 631 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/noreadperm")); 632 } 633 #endif 634 635 636 TEST_F(FileSystemTest, TempFileKeepDiscard) { 637 // We can keep then discard. 638 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); 639 ASSERT_TRUE((bool)TempFileOrError); 640 fs::TempFile File = std::move(*TempFileOrError); 641 ASSERT_EQ(-1, TempFileOrError->FD); 642 ASSERT_FALSE((bool)File.keep(TestDirectory + "/keep")); 643 ASSERT_FALSE((bool)File.discard()); 644 ASSERT_TRUE(fs::exists(TestDirectory + "/keep")); 645 ASSERT_NO_ERROR(fs::remove(TestDirectory + "/keep")); 646 } 647 648 TEST_F(FileSystemTest, TempFileDiscardDiscard) { 649 // We can discard twice. 650 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); 651 ASSERT_TRUE((bool)TempFileOrError); 652 fs::TempFile File = std::move(*TempFileOrError); 653 ASSERT_EQ(-1, TempFileOrError->FD); 654 ASSERT_FALSE((bool)File.discard()); 655 ASSERT_FALSE((bool)File.discard()); 656 ASSERT_FALSE(fs::exists(TestDirectory + "/keep")); 657 } 658 659 TEST_F(FileSystemTest, TempFiles) { 660 // Create a temp file. 661 int FileDescriptor; 662 SmallString<64> TempPath; 663 ASSERT_NO_ERROR( 664 fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); 665 666 // Make sure it exists. 667 ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); 668 669 // Create another temp tile. 670 int FD2; 671 SmallString<64> TempPath2; 672 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD2, TempPath2)); 673 ASSERT_TRUE(TempPath2.endswith(".temp")); 674 ASSERT_NE(TempPath.str(), TempPath2.str()); 675 676 fs::file_status A, B; 677 ASSERT_NO_ERROR(fs::status(Twine(TempPath), A)); 678 ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B)); 679 EXPECT_FALSE(fs::equivalent(A, B)); 680 681 ::close(FD2); 682 683 // Remove Temp2. 684 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); 685 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); 686 ASSERT_EQ(fs::remove(Twine(TempPath2), false), 687 errc::no_such_file_or_directory); 688 689 std::error_code EC = fs::status(TempPath2.c_str(), B); 690 EXPECT_EQ(EC, errc::no_such_file_or_directory); 691 EXPECT_EQ(B.type(), fs::file_type::file_not_found); 692 693 // Make sure Temp2 doesn't exist. 694 ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist), 695 errc::no_such_file_or_directory); 696 697 SmallString<64> TempPath3; 698 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); 699 ASSERT_FALSE(TempPath3.endswith(".")); 700 FileRemover Cleanup3(TempPath3); 701 702 // Create a hard link to Temp1. 703 ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); 704 bool equal; 705 ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal)); 706 EXPECT_TRUE(equal); 707 ASSERT_NO_ERROR(fs::status(Twine(TempPath), A)); 708 ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B)); 709 EXPECT_TRUE(fs::equivalent(A, B)); 710 711 // Remove Temp1. 712 ::close(FileDescriptor); 713 ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); 714 715 // Remove the hard link. 716 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); 717 718 // Make sure Temp1 doesn't exist. 719 ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), 720 errc::no_such_file_or_directory); 721 722 #ifdef _WIN32 723 // Path name > 260 chars should get an error. 724 const char *Path270 = 725 "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8" 726 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" 727 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" 728 "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" 729 "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; 730 EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), 731 errc::invalid_argument); 732 // Relative path < 247 chars, no problem. 733 const char *Path216 = 734 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" 735 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" 736 "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" 737 "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; 738 ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); 739 ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); 740 #endif 741 } 742 743 TEST_F(FileSystemTest, TempFileCollisions) { 744 SmallString<128> TestDirectory; 745 ASSERT_NO_ERROR( 746 fs::createUniqueDirectory("CreateUniqueFileTest", TestDirectory)); 747 FileRemover Cleanup(TestDirectory); 748 SmallString<128> Model = TestDirectory; 749 path::append(Model, "%.tmp"); 750 SmallString<128> Path; 751 std::vector<fs::TempFile> TempFiles; 752 753 auto TryCreateTempFile = [&]() { 754 Expected<fs::TempFile> T = fs::TempFile::create(Model); 755 if (T) { 756 TempFiles.push_back(std::move(*T)); 757 return true; 758 } else { 759 logAllUnhandledErrors(T.takeError(), errs(), 760 "Failed to create temporary file: "); 761 return false; 762 } 763 }; 764 765 // Our single-character template allows for 16 unique names. Check that 766 // calling TryCreateTempFile repeatedly results in 16 successes. 767 // Because the test depends on random numbers, it could theoretically fail. 768 // However, the probability of this happening is tiny: with 32 calls, each 769 // of which will retry up to 128 times, to not get a given digit we would 770 // have to fail at least 15 + 17 * 128 = 2191 attempts. The probability of 771 // 2191 attempts not producing a given hexadecimal digit is 772 // (1 - 1/16) ** 2191 or 3.88e-62. 773 int Successes = 0; 774 for (int i = 0; i < 32; ++i) 775 if (TryCreateTempFile()) ++Successes; 776 EXPECT_EQ(Successes, 16); 777 778 for (fs::TempFile &T : TempFiles) 779 cantFail(T.discard()); 780 } 781 782 TEST_F(FileSystemTest, CreateDir) { 783 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); 784 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); 785 ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), 786 errc::file_exists); 787 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); 788 789 #ifdef LLVM_ON_UNIX 790 // Set a 0000 umask so that we can test our directory permissions. 791 mode_t OldUmask = ::umask(0000); 792 793 fs::file_status Status; 794 ASSERT_NO_ERROR( 795 fs::create_directory(Twine(TestDirectory) + "baz500", false, 796 fs::perms::owner_read | fs::perms::owner_exe)); 797 ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status)); 798 ASSERT_EQ(Status.permissions() & fs::perms::all_all, 799 fs::perms::owner_read | fs::perms::owner_exe); 800 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false, 801 fs::perms::all_all)); 802 ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status)); 803 ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all); 804 805 // Restore umask to be safe. 806 ::umask(OldUmask); 807 #endif 808 809 #ifdef _WIN32 810 // Prove that create_directories() can handle a pathname > 248 characters, 811 // which is the documented limit for CreateDirectory(). 812 // (248 is MAX_PATH subtracting room for an 8.3 filename.) 813 // Generate a directory path guaranteed to fall into that range. 814 size_t TmpLen = TestDirectory.size(); 815 const char *OneDir = "\\123456789"; 816 size_t OneDirLen = strlen(OneDir); 817 ASSERT_LT(OneDirLen, 12U); 818 size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; 819 SmallString<260> LongDir(TestDirectory); 820 for (size_t I = 0; I < NLevels; ++I) 821 LongDir.append(OneDir); 822 ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); 823 ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); 824 ASSERT_EQ(fs::create_directories(Twine(LongDir), false), 825 errc::file_exists); 826 // Tidy up, "recursively" removing the directories. 827 StringRef ThisDir(LongDir); 828 for (size_t J = 0; J < NLevels; ++J) { 829 ASSERT_NO_ERROR(fs::remove(ThisDir)); 830 ThisDir = path::parent_path(ThisDir); 831 } 832 833 // Also verify that paths with Unix separators are handled correctly. 834 std::string LongPathWithUnixSeparators(TestDirectory.str()); 835 // Add at least one subdirectory to TestDirectory, and replace slashes with 836 // backslashes 837 do { 838 LongPathWithUnixSeparators.append("/DirNameWith19Charss"); 839 } while (LongPathWithUnixSeparators.size() < 260); 840 std::replace(LongPathWithUnixSeparators.begin(), 841 LongPathWithUnixSeparators.end(), 842 '\\', '/'); 843 ASSERT_NO_ERROR(fs::create_directories(Twine(LongPathWithUnixSeparators))); 844 // cleanup 845 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + 846 "/DirNameWith19Charss")); 847 848 // Similarly for a relative pathname. Need to set the current directory to 849 // TestDirectory so that the one we create ends up in the right place. 850 char PreviousDir[260]; 851 size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); 852 ASSERT_GT(PreviousDirLen, 0U); 853 ASSERT_LT(PreviousDirLen, 260U); 854 ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); 855 LongDir.clear(); 856 // Generate a relative directory name with absolute length > 248. 857 size_t LongDirLen = 249 - TestDirectory.size(); 858 LongDir.assign(LongDirLen, 'a'); 859 ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); 860 // While we're here, prove that .. and . handling works in these long paths. 861 const char *DotDotDirs = "\\..\\.\\b"; 862 LongDir.append(DotDotDirs); 863 ASSERT_NO_ERROR(fs::create_directory("b")); 864 ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); 865 // And clean up. 866 ASSERT_NO_ERROR(fs::remove("b")); 867 ASSERT_NO_ERROR(fs::remove( 868 Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); 869 ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); 870 #endif 871 } 872 873 TEST_F(FileSystemTest, DirectoryIteration) { 874 std::error_code ec; 875 for (fs::directory_iterator i(".", ec), e; i != e; i.increment(ec)) 876 ASSERT_NO_ERROR(ec); 877 878 // Create a known hierarchy to recurse over. 879 ASSERT_NO_ERROR( 880 fs::create_directories(Twine(TestDirectory) + "/recursive/a0/aa1")); 881 ASSERT_NO_ERROR( 882 fs::create_directories(Twine(TestDirectory) + "/recursive/a0/ab1")); 883 ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + 884 "/recursive/dontlookhere/da1")); 885 ASSERT_NO_ERROR( 886 fs::create_directories(Twine(TestDirectory) + "/recursive/z0/za1")); 887 ASSERT_NO_ERROR( 888 fs::create_directories(Twine(TestDirectory) + "/recursive/pop/p1")); 889 typedef std::vector<std::string> v_t; 890 v_t visited; 891 for (fs::recursive_directory_iterator i(Twine(TestDirectory) 892 + "/recursive", ec), e; i != e; i.increment(ec)){ 893 ASSERT_NO_ERROR(ec); 894 if (path::filename(i->path()) == "p1") { 895 i.pop(); 896 // FIXME: recursive_directory_iterator should be more robust. 897 if (i == e) break; 898 } 899 if (path::filename(i->path()) == "dontlookhere") 900 i.no_push(); 901 visited.push_back(std::string(path::filename(i->path()))); 902 } 903 v_t::const_iterator a0 = find(visited, "a0"); 904 v_t::const_iterator aa1 = find(visited, "aa1"); 905 v_t::const_iterator ab1 = find(visited, "ab1"); 906 v_t::const_iterator dontlookhere = find(visited, "dontlookhere"); 907 v_t::const_iterator da1 = find(visited, "da1"); 908 v_t::const_iterator z0 = find(visited, "z0"); 909 v_t::const_iterator za1 = find(visited, "za1"); 910 v_t::const_iterator pop = find(visited, "pop"); 911 v_t::const_iterator p1 = find(visited, "p1"); 912 913 // Make sure that each path was visited correctly. 914 ASSERT_NE(a0, visited.end()); 915 ASSERT_NE(aa1, visited.end()); 916 ASSERT_NE(ab1, visited.end()); 917 ASSERT_NE(dontlookhere, visited.end()); 918 ASSERT_EQ(da1, visited.end()); // Not visited. 919 ASSERT_NE(z0, visited.end()); 920 ASSERT_NE(za1, visited.end()); 921 ASSERT_NE(pop, visited.end()); 922 ASSERT_EQ(p1, visited.end()); // Not visited. 923 924 // Make sure that parents were visited before children. No other ordering 925 // guarantees can be made across siblings. 926 ASSERT_LT(a0, aa1); 927 ASSERT_LT(a0, ab1); 928 ASSERT_LT(z0, za1); 929 930 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/aa1")); 931 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/ab1")); 932 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0")); 933 ASSERT_NO_ERROR( 934 fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere/da1")); 935 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere")); 936 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop/p1")); 937 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop")); 938 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1")); 939 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0")); 940 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive")); 941 942 // Test recursive_directory_iterator level() 943 ASSERT_NO_ERROR( 944 fs::create_directories(Twine(TestDirectory) + "/reclevel/a/b/c")); 945 fs::recursive_directory_iterator I(Twine(TestDirectory) + "/reclevel", ec), E; 946 for (int l = 0; I != E; I.increment(ec), ++l) { 947 ASSERT_NO_ERROR(ec); 948 EXPECT_EQ(I.level(), l); 949 } 950 EXPECT_EQ(I, E); 951 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b/c")); 952 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b")); 953 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a")); 954 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel")); 955 } 956 957 #ifdef LLVM_ON_UNIX 958 TEST_F(FileSystemTest, BrokenSymlinkDirectoryIteration) { 959 // Create a known hierarchy to recurse over. 960 ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + "/symlink")); 961 ASSERT_NO_ERROR( 962 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/a")); 963 ASSERT_NO_ERROR( 964 fs::create_directories(Twine(TestDirectory) + "/symlink/b/bb")); 965 ASSERT_NO_ERROR( 966 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/b/ba")); 967 ASSERT_NO_ERROR( 968 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/b/bc")); 969 ASSERT_NO_ERROR( 970 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/c")); 971 ASSERT_NO_ERROR( 972 fs::create_directories(Twine(TestDirectory) + "/symlink/d/dd/ddd")); 973 ASSERT_NO_ERROR(fs::create_link(Twine(TestDirectory) + "/symlink/d/dd", 974 Twine(TestDirectory) + "/symlink/d/da")); 975 ASSERT_NO_ERROR( 976 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/e")); 977 978 typedef std::vector<std::string> v_t; 979 v_t VisitedNonBrokenSymlinks; 980 v_t VisitedBrokenSymlinks; 981 std::error_code ec; 982 using testing::UnorderedElementsAre; 983 using testing::UnorderedElementsAreArray; 984 985 // Broken symbol links are expected to throw an error. 986 for (fs::directory_iterator i(Twine(TestDirectory) + "/symlink", ec), e; 987 i != e; i.increment(ec)) { 988 ASSERT_NO_ERROR(ec); 989 if (i->status().getError() == 990 std::make_error_code(std::errc::no_such_file_or_directory)) { 991 VisitedBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 992 continue; 993 } 994 VisitedNonBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 995 } 996 EXPECT_THAT(VisitedNonBrokenSymlinks, UnorderedElementsAre("b", "d")); 997 VisitedNonBrokenSymlinks.clear(); 998 999 EXPECT_THAT(VisitedBrokenSymlinks, UnorderedElementsAre("a", "c", "e")); 1000 VisitedBrokenSymlinks.clear(); 1001 1002 // Broken symbol links are expected to throw an error. 1003 for (fs::recursive_directory_iterator i( 1004 Twine(TestDirectory) + "/symlink", ec), e; i != e; i.increment(ec)) { 1005 ASSERT_NO_ERROR(ec); 1006 if (i->status().getError() == 1007 std::make_error_code(std::errc::no_such_file_or_directory)) { 1008 VisitedBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 1009 continue; 1010 } 1011 VisitedNonBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 1012 } 1013 EXPECT_THAT(VisitedNonBrokenSymlinks, 1014 UnorderedElementsAre("b", "bb", "d", "da", "dd", "ddd", "ddd")); 1015 VisitedNonBrokenSymlinks.clear(); 1016 1017 EXPECT_THAT(VisitedBrokenSymlinks, 1018 UnorderedElementsAre("a", "ba", "bc", "c", "e")); 1019 VisitedBrokenSymlinks.clear(); 1020 1021 for (fs::recursive_directory_iterator i( 1022 Twine(TestDirectory) + "/symlink", ec, /*follow_symlinks=*/false), e; 1023 i != e; i.increment(ec)) { 1024 ASSERT_NO_ERROR(ec); 1025 if (i->status().getError() == 1026 std::make_error_code(std::errc::no_such_file_or_directory)) { 1027 VisitedBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 1028 continue; 1029 } 1030 VisitedNonBrokenSymlinks.push_back(std::string(path::filename(i->path()))); 1031 } 1032 EXPECT_THAT(VisitedNonBrokenSymlinks, 1033 UnorderedElementsAreArray({"a", "b", "ba", "bb", "bc", "c", "d", 1034 "da", "dd", "ddd", "e"})); 1035 VisitedNonBrokenSymlinks.clear(); 1036 1037 EXPECT_THAT(VisitedBrokenSymlinks, UnorderedElementsAre()); 1038 VisitedBrokenSymlinks.clear(); 1039 1040 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/symlink")); 1041 } 1042 #endif 1043 1044 TEST_F(FileSystemTest, Remove) { 1045 SmallString<64> BaseDir; 1046 SmallString<64> Paths[4]; 1047 int fds[4]; 1048 ASSERT_NO_ERROR(fs::createUniqueDirectory("fs_remove", BaseDir)); 1049 1050 ASSERT_NO_ERROR(fs::create_directories(Twine(BaseDir) + "/foo/bar/baz")); 1051 ASSERT_NO_ERROR(fs::create_directories(Twine(BaseDir) + "/foo/bar/buzz")); 1052 ASSERT_NO_ERROR(fs::createUniqueFile( 1053 Twine(BaseDir) + "/foo/bar/baz/%%%%%%.tmp", fds[0], Paths[0])); 1054 ASSERT_NO_ERROR(fs::createUniqueFile( 1055 Twine(BaseDir) + "/foo/bar/baz/%%%%%%.tmp", fds[1], Paths[1])); 1056 ASSERT_NO_ERROR(fs::createUniqueFile( 1057 Twine(BaseDir) + "/foo/bar/buzz/%%%%%%.tmp", fds[2], Paths[2])); 1058 ASSERT_NO_ERROR(fs::createUniqueFile( 1059 Twine(BaseDir) + "/foo/bar/buzz/%%%%%%.tmp", fds[3], Paths[3])); 1060 1061 for (int fd : fds) 1062 ::close(fd); 1063 1064 EXPECT_TRUE(fs::exists(Twine(BaseDir) + "/foo/bar/baz")); 1065 EXPECT_TRUE(fs::exists(Twine(BaseDir) + "/foo/bar/buzz")); 1066 EXPECT_TRUE(fs::exists(Paths[0])); 1067 EXPECT_TRUE(fs::exists(Paths[1])); 1068 EXPECT_TRUE(fs::exists(Paths[2])); 1069 EXPECT_TRUE(fs::exists(Paths[3])); 1070 1071 ASSERT_NO_ERROR(fs::remove_directories("D:/footest")); 1072 1073 ASSERT_NO_ERROR(fs::remove_directories(BaseDir)); 1074 ASSERT_FALSE(fs::exists(BaseDir)); 1075 } 1076 1077 #ifdef _WIN32 1078 TEST_F(FileSystemTest, CarriageReturn) { 1079 SmallString<128> FilePathname(TestDirectory); 1080 std::error_code EC; 1081 path::append(FilePathname, "test"); 1082 1083 { 1084 raw_fd_ostream File(FilePathname, EC, sys::fs::OF_Text); 1085 ASSERT_NO_ERROR(EC); 1086 File << '\n'; 1087 } 1088 { 1089 auto Buf = MemoryBuffer::getFile(FilePathname.str()); 1090 EXPECT_TRUE((bool)Buf); 1091 EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); 1092 } 1093 1094 { 1095 raw_fd_ostream File(FilePathname, EC, sys::fs::OF_None); 1096 ASSERT_NO_ERROR(EC); 1097 File << '\n'; 1098 } 1099 { 1100 auto Buf = MemoryBuffer::getFile(FilePathname.str()); 1101 EXPECT_TRUE((bool)Buf); 1102 EXPECT_EQ(Buf.get()->getBuffer(), "\n"); 1103 } 1104 ASSERT_NO_ERROR(fs::remove(Twine(FilePathname))); 1105 } 1106 #endif 1107 1108 TEST_F(FileSystemTest, Resize) { 1109 int FD; 1110 SmallString<64> TempPath; 1111 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); 1112 ASSERT_NO_ERROR(fs::resize_file(FD, 123)); 1113 fs::file_status Status; 1114 ASSERT_NO_ERROR(fs::status(FD, Status)); 1115 ASSERT_EQ(Status.getSize(), 123U); 1116 ::close(FD); 1117 ASSERT_NO_ERROR(fs::remove(TempPath)); 1118 } 1119 1120 TEST_F(FileSystemTest, MD5) { 1121 int FD; 1122 SmallString<64> TempPath; 1123 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); 1124 StringRef Data("abcdefghijklmnopqrstuvwxyz"); 1125 ASSERT_EQ(write(FD, Data.data(), Data.size()), static_cast<ssize_t>(Data.size())); 1126 lseek(FD, 0, SEEK_SET); 1127 auto Hash = fs::md5_contents(FD); 1128 ::close(FD); 1129 ASSERT_NO_ERROR(Hash.getError()); 1130 1131 EXPECT_STREQ("c3fcd3d76192e4007dfb496cca67e13b", Hash->digest().c_str()); 1132 } 1133 1134 TEST_F(FileSystemTest, FileMapping) { 1135 // Create a temp file. 1136 int FileDescriptor; 1137 SmallString<64> TempPath; 1138 ASSERT_NO_ERROR( 1139 fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); 1140 unsigned Size = 4096; 1141 ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size)); 1142 1143 // Map in temp file and add some content 1144 std::error_code EC; 1145 StringRef Val("hello there"); 1146 { 1147 fs::mapped_file_region mfr(fs::convertFDToNativeFile(FileDescriptor), 1148 fs::mapped_file_region::readwrite, Size, 0, EC); 1149 ASSERT_NO_ERROR(EC); 1150 std::copy(Val.begin(), Val.end(), mfr.data()); 1151 // Explicitly add a 0. 1152 mfr.data()[Val.size()] = 0; 1153 // Unmap temp file 1154 } 1155 ASSERT_EQ(close(FileDescriptor), 0); 1156 1157 // Map it back in read-only 1158 { 1159 int FD; 1160 EC = fs::openFileForRead(Twine(TempPath), FD); 1161 ASSERT_NO_ERROR(EC); 1162 fs::mapped_file_region mfr(fs::convertFDToNativeFile(FD), 1163 fs::mapped_file_region::readonly, Size, 0, EC); 1164 ASSERT_NO_ERROR(EC); 1165 1166 // Verify content 1167 EXPECT_EQ(StringRef(mfr.const_data()), Val); 1168 1169 // Unmap temp file 1170 fs::mapped_file_region m(fs::convertFDToNativeFile(FD), 1171 fs::mapped_file_region::readonly, Size, 0, EC); 1172 ASSERT_NO_ERROR(EC); 1173 ASSERT_EQ(close(FD), 0); 1174 } 1175 ASSERT_NO_ERROR(fs::remove(TempPath)); 1176 } 1177 1178 TEST(Support, NormalizePath) { 1179 // Input, Expected Win, Expected Posix 1180 using TestTuple = std::tuple<const char *, const char *, const char *>; 1181 std::vector<TestTuple> Tests; 1182 Tests.emplace_back("a", "a", "a"); 1183 Tests.emplace_back("a/b", "a\\b", "a/b"); 1184 Tests.emplace_back("a\\b", "a\\b", "a/b"); 1185 Tests.emplace_back("a\\\\b", "a\\\\b", "a//b"); 1186 Tests.emplace_back("\\a", "\\a", "/a"); 1187 Tests.emplace_back("a\\", "a\\", "a/"); 1188 Tests.emplace_back("a\\t", "a\\t", "a/t"); 1189 1190 for (auto &T : Tests) { 1191 SmallString<64> Win(std::get<0>(T)); 1192 SmallString<64> Posix(Win); 1193 path::native(Win, path::Style::windows); 1194 path::native(Posix, path::Style::posix); 1195 EXPECT_EQ(std::get<1>(T), Win); 1196 EXPECT_EQ(std::get<2>(T), Posix); 1197 } 1198 1199 #if defined(_WIN32) 1200 SmallString<64> PathHome; 1201 path::home_directory(PathHome); 1202 1203 const char *Path7a = "~/aaa"; 1204 SmallString<64> Path7(Path7a); 1205 path::native(Path7); 1206 EXPECT_TRUE(Path7.endswith("\\aaa")); 1207 EXPECT_TRUE(Path7.startswith(PathHome)); 1208 EXPECT_EQ(Path7.size(), PathHome.size() + strlen(Path7a + 1)); 1209 1210 const char *Path8a = "~"; 1211 SmallString<64> Path8(Path8a); 1212 path::native(Path8); 1213 EXPECT_EQ(Path8, PathHome); 1214 1215 const char *Path9a = "~aaa"; 1216 SmallString<64> Path9(Path9a); 1217 path::native(Path9); 1218 EXPECT_EQ(Path9, "~aaa"); 1219 1220 const char *Path10a = "aaa/~/b"; 1221 SmallString<64> Path10(Path10a); 1222 path::native(Path10); 1223 EXPECT_EQ(Path10, "aaa\\~\\b"); 1224 #endif 1225 } 1226 1227 TEST(Support, RemoveLeadingDotSlash) { 1228 StringRef Path1("././/foolz/wat"); 1229 StringRef Path2("./////"); 1230 1231 Path1 = path::remove_leading_dotslash(Path1); 1232 EXPECT_EQ(Path1, "foolz/wat"); 1233 Path2 = path::remove_leading_dotslash(Path2); 1234 EXPECT_EQ(Path2, ""); 1235 } 1236 1237 static std::string remove_dots(StringRef path, bool remove_dot_dot, 1238 path::Style style) { 1239 SmallString<256> buffer(path); 1240 path::remove_dots(buffer, remove_dot_dot, style); 1241 return std::string(buffer.str()); 1242 } 1243 1244 TEST(Support, RemoveDots) { 1245 EXPECT_EQ("foolz\\wat", 1246 remove_dots(".\\.\\\\foolz\\wat", false, path::Style::windows)); 1247 EXPECT_EQ("", remove_dots(".\\\\\\\\\\", false, path::Style::windows)); 1248 1249 EXPECT_EQ("a\\..\\b\\c", 1250 remove_dots(".\\a\\..\\b\\c", false, path::Style::windows)); 1251 EXPECT_EQ("b\\c", remove_dots(".\\a\\..\\b\\c", true, path::Style::windows)); 1252 EXPECT_EQ("c", remove_dots(".\\.\\c", true, path::Style::windows)); 1253 EXPECT_EQ("..\\a\\c", 1254 remove_dots("..\\a\\b\\..\\c", true, path::Style::windows)); 1255 EXPECT_EQ("..\\..\\a\\c", 1256 remove_dots("..\\..\\a\\b\\..\\c", true, path::Style::windows)); 1257 EXPECT_EQ("C:\\a\\c", remove_dots("C:\\foo\\bar//..\\..\\a\\c", true, 1258 path::Style::windows)); 1259 1260 // FIXME: These leading forward slashes are emergent behavior. VFS depends on 1261 // this behavior now. 1262 EXPECT_EQ("C:/bar", 1263 remove_dots("C:/foo/../bar", true, path::Style::windows)); 1264 EXPECT_EQ("C:/foo\\bar", 1265 remove_dots("C:/foo/bar", true, path::Style::windows)); 1266 EXPECT_EQ("C:/foo\\bar", 1267 remove_dots("C:/foo\\bar", true, path::Style::windows)); 1268 EXPECT_EQ("/", remove_dots("/", true, path::Style::windows)); 1269 EXPECT_EQ("C:/", remove_dots("C:/", true, path::Style::windows)); 1270 1271 // Some clients of remove_dots expect it to remove trailing slashes. Again, 1272 // this is emergent behavior that VFS relies on, and not inherently part of 1273 // the specification. 1274 EXPECT_EQ("C:\\foo\\bar", 1275 remove_dots("C:\\foo\\bar\\", true, path::Style::windows)); 1276 EXPECT_EQ("/foo/bar", 1277 remove_dots("/foo/bar/", true, path::Style::posix)); 1278 1279 // A double separator is rewritten. 1280 EXPECT_EQ("C:/foo\\bar", remove_dots("C:/foo//bar", true, path::Style::windows)); 1281 1282 SmallString<64> Path1(".\\.\\c"); 1283 EXPECT_TRUE(path::remove_dots(Path1, true, path::Style::windows)); 1284 EXPECT_EQ("c", Path1); 1285 1286 EXPECT_EQ("foolz/wat", 1287 remove_dots("././/foolz/wat", false, path::Style::posix)); 1288 EXPECT_EQ("", remove_dots("./////", false, path::Style::posix)); 1289 1290 EXPECT_EQ("a/../b/c", remove_dots("./a/../b/c", false, path::Style::posix)); 1291 EXPECT_EQ("b/c", remove_dots("./a/../b/c", true, path::Style::posix)); 1292 EXPECT_EQ("c", remove_dots("././c", true, path::Style::posix)); 1293 EXPECT_EQ("../a/c", remove_dots("../a/b/../c", true, path::Style::posix)); 1294 EXPECT_EQ("../../a/c", 1295 remove_dots("../../a/b/../c", true, path::Style::posix)); 1296 EXPECT_EQ("/a/c", remove_dots("/../../a/c", true, path::Style::posix)); 1297 EXPECT_EQ("/a/c", 1298 remove_dots("/../a/b//../././/c", true, path::Style::posix)); 1299 EXPECT_EQ("/", remove_dots("/", true, path::Style::posix)); 1300 1301 // FIXME: Leaving behind this double leading slash seems like a bug. 1302 EXPECT_EQ("//foo/bar", 1303 remove_dots("//foo/bar/", true, path::Style::posix)); 1304 1305 SmallString<64> Path2("././c"); 1306 EXPECT_TRUE(path::remove_dots(Path2, true, path::Style::posix)); 1307 EXPECT_EQ("c", Path2); 1308 } 1309 1310 TEST(Support, ReplacePathPrefix) { 1311 SmallString<64> Path1("/foo"); 1312 SmallString<64> Path2("/old/foo"); 1313 SmallString<64> Path3("/oldnew/foo"); 1314 SmallString<64> Path4("C:\\old/foo\\bar"); 1315 SmallString<64> OldPrefix("/old"); 1316 SmallString<64> OldPrefixSep("/old/"); 1317 SmallString<64> OldPrefixWin("c:/oLD/F"); 1318 SmallString<64> NewPrefix("/new"); 1319 SmallString<64> NewPrefix2("/longernew"); 1320 SmallString<64> EmptyPrefix(""); 1321 bool Found; 1322 1323 SmallString<64> Path = Path1; 1324 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix); 1325 EXPECT_FALSE(Found); 1326 EXPECT_EQ(Path, "/foo"); 1327 Path = Path2; 1328 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix); 1329 EXPECT_TRUE(Found); 1330 EXPECT_EQ(Path, "/new/foo"); 1331 Path = Path2; 1332 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2); 1333 EXPECT_TRUE(Found); 1334 EXPECT_EQ(Path, "/longernew/foo"); 1335 Path = Path1; 1336 Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix); 1337 EXPECT_TRUE(Found); 1338 EXPECT_EQ(Path, "/new/foo"); 1339 Path = Path2; 1340 Found = path::replace_path_prefix(Path, OldPrefix, EmptyPrefix); 1341 EXPECT_TRUE(Found); 1342 EXPECT_EQ(Path, "/foo"); 1343 Path = Path2; 1344 Found = path::replace_path_prefix(Path, OldPrefixSep, EmptyPrefix); 1345 EXPECT_TRUE(Found); 1346 EXPECT_EQ(Path, "foo"); 1347 Path = Path3; 1348 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix); 1349 EXPECT_TRUE(Found); 1350 EXPECT_EQ(Path, "/newnew/foo"); 1351 Path = Path3; 1352 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix2); 1353 EXPECT_TRUE(Found); 1354 EXPECT_EQ(Path, "/longernewnew/foo"); 1355 Path = Path1; 1356 Found = path::replace_path_prefix(Path, EmptyPrefix, NewPrefix); 1357 EXPECT_TRUE(Found); 1358 EXPECT_EQ(Path, "/new/foo"); 1359 Path = OldPrefix; 1360 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix); 1361 EXPECT_TRUE(Found); 1362 EXPECT_EQ(Path, "/new"); 1363 Path = OldPrefixSep; 1364 Found = path::replace_path_prefix(Path, OldPrefix, NewPrefix); 1365 EXPECT_TRUE(Found); 1366 EXPECT_EQ(Path, "/new/"); 1367 Path = OldPrefix; 1368 Found = path::replace_path_prefix(Path, OldPrefixSep, NewPrefix); 1369 EXPECT_FALSE(Found); 1370 EXPECT_EQ(Path, "/old"); 1371 Path = Path4; 1372 Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix, 1373 path::Style::windows); 1374 EXPECT_TRUE(Found); 1375 EXPECT_EQ(Path, "/newoo\\bar"); 1376 Path = Path4; 1377 Found = path::replace_path_prefix(Path, OldPrefixWin, NewPrefix, 1378 path::Style::posix); 1379 EXPECT_FALSE(Found); 1380 EXPECT_EQ(Path, "C:\\old/foo\\bar"); 1381 } 1382 1383 TEST_F(FileSystemTest, OpenFileForRead) { 1384 // Create a temp file. 1385 int FileDescriptor; 1386 SmallString<64> TempPath; 1387 ASSERT_NO_ERROR( 1388 fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); 1389 FileRemover Cleanup(TempPath); 1390 1391 // Make sure it exists. 1392 ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); 1393 1394 // Open the file for read 1395 int FileDescriptor2; 1396 SmallString<64> ResultPath; 1397 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor2, 1398 fs::OF_None, &ResultPath)) 1399 1400 // If we succeeded, check that the paths are the same (modulo case): 1401 if (!ResultPath.empty()) { 1402 // The paths returned by createTemporaryFile and getPathFromOpenFD 1403 // should reference the same file on disk. 1404 fs::UniqueID D1, D2; 1405 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); 1406 ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); 1407 ASSERT_EQ(D1, D2); 1408 } 1409 ::close(FileDescriptor); 1410 ::close(FileDescriptor2); 1411 1412 #ifdef _WIN32 1413 // Since Windows Vista, file access time is not updated by default. 1414 // This is instead updated manually by openFileForRead. 1415 // https://blogs.technet.microsoft.com/filecab/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance/ 1416 // This part of the unit test is Windows specific as the updating of 1417 // access times can be disabled on Linux using /etc/fstab. 1418 1419 // Set access time to UNIX epoch. 1420 ASSERT_NO_ERROR(sys::fs::openFileForWrite(Twine(TempPath), FileDescriptor, 1421 fs::CD_OpenExisting)); 1422 TimePoint<> Epoch(std::chrono::milliseconds(0)); 1423 ASSERT_NO_ERROR(fs::setLastAccessAndModificationTime(FileDescriptor, Epoch)); 1424 ::close(FileDescriptor); 1425 1426 // Open the file and ensure access time is updated, when forced. 1427 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor, 1428 fs::OF_UpdateAtime, &ResultPath)); 1429 1430 sys::fs::file_status Status; 1431 ASSERT_NO_ERROR(sys::fs::status(FileDescriptor, Status)); 1432 auto FileAccessTime = Status.getLastAccessedTime(); 1433 1434 ASSERT_NE(Epoch, FileAccessTime); 1435 ::close(FileDescriptor); 1436 1437 // Ideally this test would include a case when ATime is not forced to update, 1438 // however the expected behaviour will differ depending on the configuration 1439 // of the Windows file system. 1440 #endif 1441 } 1442 1443 static void createFileWithData(const Twine &Path, bool ShouldExistBefore, 1444 fs::CreationDisposition Disp, StringRef Data) { 1445 int FD; 1446 ASSERT_EQ(ShouldExistBefore, fs::exists(Path)); 1447 ASSERT_NO_ERROR(fs::openFileForWrite(Path, FD, Disp)); 1448 FileDescriptorCloser Closer(FD); 1449 ASSERT_TRUE(fs::exists(Path)); 1450 1451 ASSERT_EQ(Data.size(), (size_t)write(FD, Data.data(), Data.size())); 1452 } 1453 1454 static void verifyFileContents(const Twine &Path, StringRef Contents) { 1455 auto Buffer = MemoryBuffer::getFile(Path); 1456 ASSERT_TRUE((bool)Buffer); 1457 StringRef Data = Buffer.get()->getBuffer(); 1458 ASSERT_EQ(Data, Contents); 1459 } 1460 1461 TEST_F(FileSystemTest, CreateNew) { 1462 int FD; 1463 Optional<FileDescriptorCloser> Closer; 1464 1465 // Succeeds if the file does not exist. 1466 ASSERT_FALSE(fs::exists(NonExistantFile)); 1467 ASSERT_NO_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew)); 1468 ASSERT_TRUE(fs::exists(NonExistantFile)); 1469 1470 FileRemover Cleanup(NonExistantFile); 1471 Closer.emplace(FD); 1472 1473 // And creates a file of size 0. 1474 sys::fs::file_status Status; 1475 ASSERT_NO_ERROR(sys::fs::status(FD, Status)); 1476 EXPECT_EQ(0ULL, Status.getSize()); 1477 1478 // Close this first, before trying to re-open the file. 1479 Closer.reset(); 1480 1481 // But fails if the file does exist. 1482 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew)); 1483 } 1484 1485 TEST_F(FileSystemTest, CreateAlways) { 1486 int FD; 1487 Optional<FileDescriptorCloser> Closer; 1488 1489 // Succeeds if the file does not exist. 1490 ASSERT_FALSE(fs::exists(NonExistantFile)); 1491 ASSERT_NO_ERROR( 1492 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways)); 1493 1494 Closer.emplace(FD); 1495 1496 ASSERT_TRUE(fs::exists(NonExistantFile)); 1497 1498 FileRemover Cleanup(NonExistantFile); 1499 1500 // And creates a file of size 0. 1501 uint64_t FileSize; 1502 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1503 ASSERT_EQ(0ULL, FileSize); 1504 1505 // If we write some data to it re-create it with CreateAlways, it succeeds and 1506 // truncates to 0 bytes. 1507 ASSERT_EQ(4, write(FD, "Test", 4)); 1508 1509 Closer.reset(); 1510 1511 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1512 ASSERT_EQ(4ULL, FileSize); 1513 1514 ASSERT_NO_ERROR( 1515 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways)); 1516 Closer.emplace(FD); 1517 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1518 ASSERT_EQ(0ULL, FileSize); 1519 } 1520 1521 TEST_F(FileSystemTest, OpenExisting) { 1522 int FD; 1523 1524 // Fails if the file does not exist. 1525 ASSERT_FALSE(fs::exists(NonExistantFile)); 1526 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting)); 1527 ASSERT_FALSE(fs::exists(NonExistantFile)); 1528 1529 // Make a dummy file now so that we can try again when the file does exist. 1530 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz"); 1531 FileRemover Cleanup(NonExistantFile); 1532 uint64_t FileSize; 1533 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1534 ASSERT_EQ(4ULL, FileSize); 1535 1536 // If we re-create it with different data, it overwrites rather than 1537 // appending. 1538 createFileWithData(NonExistantFile, true, fs::CD_OpenExisting, "Buzz"); 1539 verifyFileContents(NonExistantFile, "Buzz"); 1540 } 1541 1542 TEST_F(FileSystemTest, OpenAlways) { 1543 // Succeeds if the file does not exist. 1544 createFileWithData(NonExistantFile, false, fs::CD_OpenAlways, "Fizz"); 1545 FileRemover Cleanup(NonExistantFile); 1546 uint64_t FileSize; 1547 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1548 ASSERT_EQ(4ULL, FileSize); 1549 1550 // Now re-open it and write again, verifying the contents get over-written. 1551 createFileWithData(NonExistantFile, true, fs::CD_OpenAlways, "Bu"); 1552 verifyFileContents(NonExistantFile, "Buzz"); 1553 } 1554 1555 TEST_F(FileSystemTest, AppendSetsCorrectFileOffset) { 1556 fs::CreationDisposition Disps[] = {fs::CD_CreateAlways, fs::CD_OpenAlways, 1557 fs::CD_OpenExisting}; 1558 1559 // Write some data and re-open it with every possible disposition (this is a 1560 // hack that shouldn't work, but is left for compatibility. OF_Append 1561 // overrides 1562 // the specified disposition. 1563 for (fs::CreationDisposition Disp : Disps) { 1564 int FD; 1565 Optional<FileDescriptorCloser> Closer; 1566 1567 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz"); 1568 1569 FileRemover Cleanup(NonExistantFile); 1570 1571 uint64_t FileSize; 1572 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1573 ASSERT_EQ(4ULL, FileSize); 1574 ASSERT_NO_ERROR( 1575 fs::openFileForWrite(NonExistantFile, FD, Disp, fs::OF_Append)); 1576 Closer.emplace(FD); 1577 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize)); 1578 ASSERT_EQ(4ULL, FileSize); 1579 1580 ASSERT_EQ(4, write(FD, "Buzz", 4)); 1581 Closer.reset(); 1582 1583 verifyFileContents(NonExistantFile, "FizzBuzz"); 1584 } 1585 } 1586 1587 static void verifyRead(int FD, StringRef Data, bool ShouldSucceed) { 1588 std::vector<char> Buffer; 1589 Buffer.resize(Data.size()); 1590 int Result = ::read(FD, Buffer.data(), Buffer.size()); 1591 if (ShouldSucceed) { 1592 ASSERT_EQ((size_t)Result, Data.size()); 1593 ASSERT_EQ(Data, StringRef(Buffer.data(), Buffer.size())); 1594 } else { 1595 ASSERT_EQ(-1, Result); 1596 ASSERT_EQ(EBADF, errno); 1597 } 1598 } 1599 1600 static void verifyWrite(int FD, StringRef Data, bool ShouldSucceed) { 1601 int Result = ::write(FD, Data.data(), Data.size()); 1602 if (ShouldSucceed) 1603 ASSERT_EQ((size_t)Result, Data.size()); 1604 else { 1605 ASSERT_EQ(-1, Result); 1606 ASSERT_EQ(EBADF, errno); 1607 } 1608 } 1609 1610 TEST_F(FileSystemTest, ReadOnlyFileCantWrite) { 1611 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz"); 1612 FileRemover Cleanup(NonExistantFile); 1613 1614 int FD; 1615 ASSERT_NO_ERROR(fs::openFileForRead(NonExistantFile, FD)); 1616 FileDescriptorCloser Closer(FD); 1617 1618 verifyWrite(FD, "Buzz", false); 1619 verifyRead(FD, "Fizz", true); 1620 } 1621 1622 TEST_F(FileSystemTest, WriteOnlyFileCantRead) { 1623 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz"); 1624 FileRemover Cleanup(NonExistantFile); 1625 1626 int FD; 1627 ASSERT_NO_ERROR( 1628 fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting)); 1629 FileDescriptorCloser Closer(FD); 1630 verifyRead(FD, "Fizz", false); 1631 verifyWrite(FD, "Buzz", true); 1632 } 1633 1634 TEST_F(FileSystemTest, ReadWriteFileCanReadOrWrite) { 1635 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz"); 1636 FileRemover Cleanup(NonExistantFile); 1637 1638 int FD; 1639 ASSERT_NO_ERROR(fs::openFileForReadWrite(NonExistantFile, FD, 1640 fs::CD_OpenExisting, fs::OF_None)); 1641 FileDescriptorCloser Closer(FD); 1642 verifyRead(FD, "Fizz", true); 1643 verifyWrite(FD, "Buzz", true); 1644 } 1645 1646 TEST_F(FileSystemTest, readNativeFile) { 1647 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "01234"); 1648 FileRemover Cleanup(NonExistantFile); 1649 const auto &Read = [&](size_t ToRead) -> Expected<std::string> { 1650 std::string Buf(ToRead, '?'); 1651 Expected<fs::file_t> FD = fs::openNativeFileForRead(NonExistantFile); 1652 if (!FD) 1653 return FD.takeError(); 1654 auto Close = make_scope_exit([&] { fs::closeFile(*FD); }); 1655 if (Expected<size_t> BytesRead = fs::readNativeFile( 1656 *FD, makeMutableArrayRef(&*Buf.begin(), Buf.size()))) 1657 return Buf.substr(0, *BytesRead); 1658 else 1659 return BytesRead.takeError(); 1660 }; 1661 EXPECT_THAT_EXPECTED(Read(5), HasValue("01234")); 1662 EXPECT_THAT_EXPECTED(Read(3), HasValue("012")); 1663 EXPECT_THAT_EXPECTED(Read(6), HasValue("01234")); 1664 } 1665 1666 TEST_F(FileSystemTest, readNativeFileSlice) { 1667 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "01234"); 1668 FileRemover Cleanup(NonExistantFile); 1669 Expected<fs::file_t> FD = fs::openNativeFileForRead(NonExistantFile); 1670 ASSERT_THAT_EXPECTED(FD, Succeeded()); 1671 auto Close = make_scope_exit([&] { fs::closeFile(*FD); }); 1672 const auto &Read = [&](size_t Offset, 1673 size_t ToRead) -> Expected<std::string> { 1674 std::string Buf(ToRead, '?'); 1675 if (Expected<size_t> BytesRead = fs::readNativeFileSlice( 1676 *FD, makeMutableArrayRef(&*Buf.begin(), Buf.size()), Offset)) 1677 return Buf.substr(0, *BytesRead); 1678 else 1679 return BytesRead.takeError(); 1680 }; 1681 EXPECT_THAT_EXPECTED(Read(0, 5), HasValue("01234")); 1682 EXPECT_THAT_EXPECTED(Read(0, 3), HasValue("012")); 1683 EXPECT_THAT_EXPECTED(Read(2, 3), HasValue("234")); 1684 EXPECT_THAT_EXPECTED(Read(0, 6), HasValue("01234")); 1685 EXPECT_THAT_EXPECTED(Read(2, 6), HasValue("234")); 1686 EXPECT_THAT_EXPECTED(Read(5, 5), HasValue("")); 1687 } 1688 1689 TEST_F(FileSystemTest, is_local) { 1690 bool TestDirectoryIsLocal; 1691 ASSERT_NO_ERROR(fs::is_local(TestDirectory, TestDirectoryIsLocal)); 1692 EXPECT_EQ(TestDirectoryIsLocal, fs::is_local(TestDirectory)); 1693 1694 int FD; 1695 SmallString<128> TempPath; 1696 ASSERT_NO_ERROR( 1697 fs::createUniqueFile(Twine(TestDirectory) + "/temp", FD, TempPath)); 1698 FileRemover Cleanup(TempPath); 1699 1700 // Make sure it exists. 1701 ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); 1702 1703 bool TempFileIsLocal; 1704 ASSERT_NO_ERROR(fs::is_local(FD, TempFileIsLocal)); 1705 EXPECT_EQ(TempFileIsLocal, fs::is_local(FD)); 1706 ::close(FD); 1707 1708 // Expect that the file and its parent directory are equally local or equally 1709 // remote. 1710 EXPECT_EQ(TestDirectoryIsLocal, TempFileIsLocal); 1711 } 1712 1713 TEST_F(FileSystemTest, getUmask) { 1714 #ifdef _WIN32 1715 EXPECT_EQ(fs::getUmask(), 0U) << "Should always be 0 on Windows."; 1716 #else 1717 unsigned OldMask = ::umask(0022); 1718 unsigned CurrentMask = fs::getUmask(); 1719 EXPECT_EQ(CurrentMask, 0022U) 1720 << "getUmask() didn't return previously set umask()"; 1721 EXPECT_EQ(::umask(OldMask), 0022U) << "getUmask() may have changed umask()"; 1722 #endif 1723 } 1724 1725 TEST_F(FileSystemTest, RespectUmask) { 1726 #ifndef _WIN32 1727 unsigned OldMask = ::umask(0022); 1728 1729 int FD; 1730 SmallString<128> TempPath; 1731 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); 1732 1733 fs::perms AllRWE = static_cast<fs::perms>(0777); 1734 1735 ASSERT_NO_ERROR(fs::setPermissions(TempPath, AllRWE)); 1736 1737 ErrorOr<fs::perms> Perms = fs::getPermissions(TempPath); 1738 ASSERT_TRUE(!!Perms); 1739 EXPECT_EQ(Perms.get(), AllRWE) << "Should have ignored umask by default"; 1740 1741 ASSERT_NO_ERROR(fs::setPermissions(TempPath, AllRWE)); 1742 1743 Perms = fs::getPermissions(TempPath); 1744 ASSERT_TRUE(!!Perms); 1745 EXPECT_EQ(Perms.get(), AllRWE) << "Should have ignored umask"; 1746 1747 ASSERT_NO_ERROR( 1748 fs::setPermissions(FD, static_cast<fs::perms>(AllRWE & ~fs::getUmask()))); 1749 Perms = fs::getPermissions(TempPath); 1750 ASSERT_TRUE(!!Perms); 1751 EXPECT_EQ(Perms.get(), static_cast<fs::perms>(0755)) 1752 << "Did not respect umask"; 1753 1754 (void)::umask(0057); 1755 1756 ASSERT_NO_ERROR( 1757 fs::setPermissions(FD, static_cast<fs::perms>(AllRWE & ~fs::getUmask()))); 1758 Perms = fs::getPermissions(TempPath); 1759 ASSERT_TRUE(!!Perms); 1760 EXPECT_EQ(Perms.get(), static_cast<fs::perms>(0720)) 1761 << "Did not respect umask"; 1762 1763 (void)::umask(OldMask); 1764 (void)::close(FD); 1765 #endif 1766 } 1767 1768 TEST_F(FileSystemTest, set_current_path) { 1769 SmallString<128> path; 1770 1771 ASSERT_NO_ERROR(fs::current_path(path)); 1772 ASSERT_NE(TestDirectory, path); 1773 1774 struct RestorePath { 1775 SmallString<128> path; 1776 RestorePath(const SmallString<128> &path) : path(path) {} 1777 ~RestorePath() { fs::set_current_path(path); } 1778 } restore_path(path); 1779 1780 ASSERT_NO_ERROR(fs::set_current_path(TestDirectory)); 1781 1782 ASSERT_NO_ERROR(fs::current_path(path)); 1783 1784 fs::UniqueID D1, D2; 1785 ASSERT_NO_ERROR(fs::getUniqueID(TestDirectory, D1)); 1786 ASSERT_NO_ERROR(fs::getUniqueID(path, D2)); 1787 ASSERT_EQ(D1, D2) << "D1: " << TestDirectory << "\nD2: " << path; 1788 } 1789 1790 TEST_F(FileSystemTest, permissions) { 1791 int FD; 1792 SmallString<64> TempPath; 1793 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); 1794 FileRemover Cleanup(TempPath); 1795 1796 // Make sure it exists. 1797 ASSERT_TRUE(fs::exists(Twine(TempPath))); 1798 1799 auto CheckPermissions = [&](fs::perms Expected) { 1800 ErrorOr<fs::perms> Actual = fs::getPermissions(TempPath); 1801 return Actual && *Actual == Expected; 1802 }; 1803 1804 std::error_code NoError; 1805 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_all), NoError); 1806 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1807 1808 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::all_exe), NoError); 1809 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::all_exe)); 1810 1811 #if defined(_WIN32) 1812 fs::perms ReadOnly = fs::all_read | fs::all_exe; 1813 EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError); 1814 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1815 1816 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError); 1817 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1818 1819 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError); 1820 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1821 1822 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError); 1823 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1824 1825 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError); 1826 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1827 1828 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError); 1829 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1830 1831 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError); 1832 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1833 1834 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError); 1835 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1836 1837 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError); 1838 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1839 1840 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError); 1841 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1842 1843 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError); 1844 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1845 1846 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError); 1847 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1848 1849 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError); 1850 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1851 1852 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError); 1853 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1854 1855 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError); 1856 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1857 1858 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError); 1859 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1860 1861 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError); 1862 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1863 1864 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError); 1865 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1866 1867 EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError); 1868 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1869 1870 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe | 1871 fs::set_gid_on_exe | 1872 fs::sticky_bit), 1873 NoError); 1874 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1875 1876 EXPECT_EQ(fs::setPermissions(TempPath, ReadOnly | fs::set_uid_on_exe | 1877 fs::set_gid_on_exe | 1878 fs::sticky_bit), 1879 NoError); 1880 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1881 1882 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError); 1883 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1884 #else 1885 EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError); 1886 EXPECT_TRUE(CheckPermissions(fs::no_perms)); 1887 1888 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError); 1889 EXPECT_TRUE(CheckPermissions(fs::owner_read)); 1890 1891 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError); 1892 EXPECT_TRUE(CheckPermissions(fs::owner_write)); 1893 1894 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError); 1895 EXPECT_TRUE(CheckPermissions(fs::owner_exe)); 1896 1897 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError); 1898 EXPECT_TRUE(CheckPermissions(fs::owner_all)); 1899 1900 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError); 1901 EXPECT_TRUE(CheckPermissions(fs::group_read)); 1902 1903 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError); 1904 EXPECT_TRUE(CheckPermissions(fs::group_write)); 1905 1906 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError); 1907 EXPECT_TRUE(CheckPermissions(fs::group_exe)); 1908 1909 EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError); 1910 EXPECT_TRUE(CheckPermissions(fs::group_all)); 1911 1912 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError); 1913 EXPECT_TRUE(CheckPermissions(fs::others_read)); 1914 1915 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError); 1916 EXPECT_TRUE(CheckPermissions(fs::others_write)); 1917 1918 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError); 1919 EXPECT_TRUE(CheckPermissions(fs::others_exe)); 1920 1921 EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError); 1922 EXPECT_TRUE(CheckPermissions(fs::others_all)); 1923 1924 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError); 1925 EXPECT_TRUE(CheckPermissions(fs::all_read)); 1926 1927 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError); 1928 EXPECT_TRUE(CheckPermissions(fs::all_write)); 1929 1930 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError); 1931 EXPECT_TRUE(CheckPermissions(fs::all_exe)); 1932 1933 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError); 1934 EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe)); 1935 1936 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError); 1937 EXPECT_TRUE(CheckPermissions(fs::set_gid_on_exe)); 1938 1939 // Modern BSDs require root to set the sticky bit on files. 1940 // AIX and Solaris without root will mask off (i.e., lose) the sticky bit 1941 // on files. 1942 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \ 1943 !defined(_AIX) && !(defined(__sun__) && defined(__svr4__)) 1944 EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError); 1945 EXPECT_TRUE(CheckPermissions(fs::sticky_bit)); 1946 1947 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe | 1948 fs::set_gid_on_exe | 1949 fs::sticky_bit), 1950 NoError); 1951 EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe | fs::set_gid_on_exe | 1952 fs::sticky_bit)); 1953 1954 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::set_uid_on_exe | 1955 fs::set_gid_on_exe | 1956 fs::sticky_bit), 1957 NoError); 1958 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::set_uid_on_exe | 1959 fs::set_gid_on_exe | fs::sticky_bit)); 1960 1961 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError); 1962 EXPECT_TRUE(CheckPermissions(fs::all_perms)); 1963 #endif // !FreeBSD && !NetBSD && !OpenBSD && !AIX 1964 1965 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms & ~fs::sticky_bit), 1966 NoError); 1967 EXPECT_TRUE(CheckPermissions(fs::all_perms & ~fs::sticky_bit)); 1968 #endif 1969 } 1970 1971 #ifdef _WIN32 1972 TEST_F(FileSystemTest, widenPath) { 1973 const std::wstring LongPathPrefix(L"\\\\?\\"); 1974 1975 // Test that the length limit is checked against the UTF-16 length and not the 1976 // UTF-8 length. 1977 std::string Input("C:\\foldername\\"); 1978 const std::string Pi("\xcf\x80"); // UTF-8 lower case pi. 1979 // Add Pi up to the MAX_PATH limit. 1980 const size_t NumChars = MAX_PATH - Input.size() - 1; 1981 for (size_t i = 0; i < NumChars; ++i) 1982 Input += Pi; 1983 // Check that UTF-8 length already exceeds MAX_PATH. 1984 EXPECT_TRUE(Input.size() > MAX_PATH); 1985 SmallVector<wchar_t, MAX_PATH + 16> Result; 1986 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 1987 // Result should not start with the long path prefix. 1988 EXPECT_TRUE(std::wmemcmp(Result.data(), LongPathPrefix.c_str(), 1989 LongPathPrefix.size()) != 0); 1990 EXPECT_EQ(Result.size(), (size_t)MAX_PATH - 1); 1991 1992 // Add another Pi to exceed the MAX_PATH limit. 1993 Input += Pi; 1994 // Construct the expected result. 1995 SmallVector<wchar_t, MAX_PATH + 16> Expected; 1996 ASSERT_NO_ERROR(windows::UTF8ToUTF16(Input, Expected)); 1997 Expected.insert(Expected.begin(), LongPathPrefix.begin(), 1998 LongPathPrefix.end()); 1999 2000 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 2001 EXPECT_EQ(Result, Expected); 2002 2003 // Test that UNC paths are handled correctly. 2004 const std::string ShareName("\\\\sharename\\"); 2005 const std::string FileName("\\filename"); 2006 // Initialize directory name so that the input is within the MAX_PATH limit. 2007 const char DirChar = 'x'; 2008 std::string DirName(MAX_PATH - ShareName.size() - FileName.size() - 1, 2009 DirChar); 2010 2011 Input = ShareName + DirName + FileName; 2012 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 2013 // Result should not start with the long path prefix. 2014 EXPECT_TRUE(std::wmemcmp(Result.data(), LongPathPrefix.c_str(), 2015 LongPathPrefix.size()) != 0); 2016 EXPECT_EQ(Result.size(), (size_t)MAX_PATH - 1); 2017 2018 // Extend the directory name so the input exceeds the MAX_PATH limit. 2019 DirName += DirChar; 2020 Input = ShareName + DirName + FileName; 2021 // Construct the expected result. 2022 ASSERT_NO_ERROR(windows::UTF8ToUTF16(StringRef(Input).substr(2), Expected)); 2023 const std::wstring UNCPrefix(LongPathPrefix + L"UNC\\"); 2024 Expected.insert(Expected.begin(), UNCPrefix.begin(), UNCPrefix.end()); 2025 2026 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 2027 EXPECT_EQ(Result, Expected); 2028 2029 // Check that Unix separators are handled correctly. 2030 std::replace(Input.begin(), Input.end(), '\\', '/'); 2031 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 2032 EXPECT_EQ(Result, Expected); 2033 2034 // Check the removal of "dots". 2035 Input = ShareName + DirName + "\\.\\foo\\.\\.." + FileName; 2036 ASSERT_NO_ERROR(windows::widenPath(Input, Result)); 2037 EXPECT_EQ(Result, Expected); 2038 } 2039 #endif 2040 2041 } // anonymous namespace 2042