X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=unittests%2FSupport%2FPath.cpp;h=cfba227dbe93fe723d855d95bcb15a418ba916ec;hb=3d7575d7e2e8bdb6603f6754dfa86aacf1a4bbf3;hp=d4de2735d31e7e7b31b6f4b76dd5dd763044f63e;hpb=8d230cd536cfc00cc58e749f6e9cf58dd138b0bb;p=oota-llvm.git diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index d4de2735d31..cfba227dbe9 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -16,9 +16,14 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 +#include #include #endif +#ifdef LLVM_ON_UNIX +#include +#endif + using namespace llvm; using namespace llvm::sys; @@ -167,6 +172,26 @@ TEST(Support, RelativePathIterator) { } } +TEST(Support, RelativePathDotIterator) { + SmallString<64> Path(StringRef(".c/.d/../.")); + typedef SmallVector PathComponents; + PathComponents ExpectedPathComponents; + PathComponents ActualPathComponents; + + StringRef(Path).split(ExpectedPathComponents, "/"); + + for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; + ++I) { + ActualPathComponents.push_back(*I); + } + + ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); + + for (size_t i = 0; i Path(StringRef("/c/d/e/foo.txt")); typedef SmallVector PathComponents; @@ -190,6 +215,29 @@ TEST(Support, AbsolutePathIterator) { } } +TEST(Support, AbsolutePathDotIterator) { + SmallString<64> Path(StringRef("/.c/.d/../.")); + typedef SmallVector PathComponents; + PathComponents ExpectedPathComponents; + PathComponents ActualPathComponents; + + StringRef(Path).split(ExpectedPathComponents, "/"); + + // The root path will also be a component when iterating + ExpectedPathComponents[0] = "/"; + + for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; + ++I) { + ActualPathComponents.push_back(*I); + } + + ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); + + for (size_t i = 0; i Path(StringRef("c:\\c\\e\\foo.txt")); @@ -261,10 +309,10 @@ TEST(Support, HomeDirectory) { class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must - /// be placed. It is recursively removed at the end of each test. + /// be placed. It is removed at the end of each test (must be empty). SmallString<128> TestDirectory; - virtual void SetUp() { + void SetUp() override { ASSERT_NO_ERROR( fs::createUniqueDirectory("file-system-test", TestDirectory)); // We don't care about this specific file. @@ -272,9 +320,7 @@ protected: errs().flush(); } - virtual void TearDown() { - ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); - } + void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } }; TEST_F(FileSystemTest, Unique) { @@ -396,8 +442,16 @@ TEST_F(FileSystemTest, TempFiles) { "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; - EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), - errc::no_such_file_or_directory); + EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), + errc::invalid_argument); + // Relative path < 247 chars, no problem. + const char *Path216 = + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); #endif } @@ -407,6 +461,74 @@ TEST_F(FileSystemTest, CreateDir) { ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), errc::file_exists); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + +#ifdef LLVM_ON_UNIX + // Set a 0000 umask so that we can test our directory permissions. + mode_t OldUmask = ::umask(0000); + + fs::file_status Status; + ASSERT_NO_ERROR( + fs::create_directory(Twine(TestDirectory) + "baz500", false, + fs::perms::owner_read | fs::perms::owner_exe)); + ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status)); + ASSERT_EQ(Status.permissions() & fs::perms::all_all, + fs::perms::owner_read | fs::perms::owner_exe); + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false, + fs::perms::all_all)); + ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status)); + ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all); + + // Restore umask to be safe. + ::umask(OldUmask); +#endif + +#ifdef LLVM_ON_WIN32 + // Prove that create_directories() can handle a pathname > 248 characters, + // which is the documented limit for CreateDirectory(). + // (248 is MAX_PATH subtracting room for an 8.3 filename.) + // Generate a directory path guaranteed to fall into that range. + size_t TmpLen = TestDirectory.size(); + const char *OneDir = "\\123456789"; + size_t OneDirLen = strlen(OneDir); + ASSERT_LT(OneDirLen, 12U); + size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; + SmallString<260> LongDir(TestDirectory); + for (size_t I = 0; I < NLevels; ++I) + LongDir.append(OneDir); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_EQ(fs::create_directories(Twine(LongDir), false), + errc::file_exists); + // Tidy up, "recursively" removing the directories. + StringRef ThisDir(LongDir); + for (size_t J = 0; J < NLevels; ++J) { + ASSERT_NO_ERROR(fs::remove(ThisDir)); + ThisDir = path::parent_path(ThisDir); + } + + // Similarly for a relative pathname. Need to set the current directory to + // TestDirectory so that the one we create ends up in the right place. + char PreviousDir[260]; + size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); + ASSERT_GT(PreviousDirLen, 0U); + ASSERT_LT(PreviousDirLen, 260U); + ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); + LongDir.clear(); + // Generate a relative directory name with absolute length > 248. + size_t LongDirLen = 249 - TestDirectory.size(); + LongDir.assign(LongDirLen, 'a'); + ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); + // While we're here, prove that .. and . handling works in these long paths. + const char *DotDotDirs = "\\..\\.\\b"; + LongDir.append(DotDotDirs); + ASSERT_NO_ERROR(fs::create_directory("b")); + ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); + // And clean up. + ASSERT_NO_ERROR(fs::remove("b")); + ASSERT_NO_ERROR(fs::remove( + Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); + ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); +#endif } TEST_F(FileSystemTest, DirectoryIteration) { @@ -483,6 +605,8 @@ TEST_F(FileSystemTest, DirectoryIteration) { const char archive[] = "!\x0A"; const char bitcode[] = "\xde\xc0\x17\x0b"; const char coff_object[] = "\x00\x00......"; +const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" + "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8"; const char coff_import_library[] = "\x00\x00\xff\xff...."; const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; @@ -498,7 +622,10 @@ const char macho_dynamically_linked_shared_lib[] = const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07"; const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08"; const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a"; +const char macho_kext_bundle[] = "\xfe\xed\xfa\xce..........\x00\x0b"; const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; +const char macho_dynamically_linked_shared_lib_stub[] = + "\xfe\xed\xfa\xce..........\x00\x09"; TEST_F(FileSystemTest, Magic) { struct type { @@ -512,6 +639,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(archive), DEFINE(bitcode), DEFINE(coff_object), + { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object }, DEFINE(coff_import_library), DEFINE(elf_relocatable), DEFINE(macho_universal_binary), @@ -523,7 +651,9 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_dynamically_linked_shared_lib), DEFINE(macho_dynamic_linker), DEFINE(macho_bundle), + DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), + DEFINE(macho_kext_bundle), DEFINE(windows_resource) #undef DEFINE }; @@ -575,22 +705,31 @@ TEST_F(FileSystemTest, CarriageReturn) { } #endif +TEST_F(FileSystemTest, Resize) { + int FD; + SmallString<64> TempPath; + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); + ASSERT_NO_ERROR(fs::resize_file(FD, 123)); + fs::file_status Status; + ASSERT_NO_ERROR(fs::status(FD, Status)); + ASSERT_EQ(Status.getSize(), 123U); +} + TEST_F(FileSystemTest, FileMapping) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + unsigned Size = 4096; + ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size)); + // Map in temp file and add some content std::error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, - true, - fs::mapped_file_region::readwrite, - 4096, - 0, - EC); + fs::mapped_file_region::readwrite, Size, 0, EC); ASSERT_NO_ERROR(EC); std::copy(Val.begin(), Val.end(), mfr.data()); // Explicitly add a 0. @@ -599,27 +738,19 @@ TEST_F(FileSystemTest, FileMapping) { } // Map it back in read-only - fs::mapped_file_region mfr(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + int FD; + EC = fs::openFileForRead(Twine(TempPath), FD); + ASSERT_NO_ERROR(EC); + fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); // Verify content EXPECT_EQ(StringRef(mfr.const_data()), Val); // Unmap temp file - - fs::mapped_file_region m(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); - const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(std::move(m)); - EXPECT_EQ(mfrrv.const_data(), Data); + ASSERT_EQ(close(FD), 0); } TEST(Support, NormalizePath) { @@ -658,4 +789,14 @@ TEST(Support, NormalizePath) { #undef EXPECT_PATH_IS } + +TEST(Support, RemoveLeadingDotSlash) { + StringRef Path1("././/foolz/wat"); + StringRef Path2("./////"); + + Path1 = path::remove_leading_dotslash(Path1); + EXPECT_EQ(Path1, "foolz/wat"); + Path2 = path::remove_leading_dotslash(Path2); + EXPECT_EQ(Path2, ""); +} } // anonymous namespace