X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=unittests%2FSupport%2FPath.cpp;h=c4067b9137ee86f2e279129f8de510d915e3caab;hp=878c22796a5b709536e2633a759295ad7c68bae1;hb=0a3eef53d7eb99bb902c40549d4170a5048c16c0;hpb=5a88dda4be791426ab4d20a6a6c9c65d66614a27 diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 878c22796a5..c4067b9137e 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -7,9 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/PathV2.h" +#include "llvm/Support/Path.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" @@ -140,6 +141,88 @@ TEST(Support, Path) { } } +TEST(Support, RelativePathIterator) { + SmallString<64> Path(StringRef("c/d/e/foo.txt")); + 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; + 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")); + typedef SmallVector PathComponents; + PathComponents ExpectedPathComponents; + PathComponents ActualPathComponents; + + StringRef(Path).split(ExpectedPathComponents, "\\"); + + // The root path (which comes after the drive name) will also be a component + // when iterating. + ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\"); + + 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 HomeDir; + EXPECT_TRUE(path::home_directory(HomeDir)); + EXPECT_FALSE(HomeDir.empty()); +#ifdef LLVM_ON_UNIX + } +#endif +} + class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must @@ -147,29 +230,73 @@ protected: SmallString<128> TestDirectory; virtual void SetUp() { - int fd; ASSERT_NO_ERROR( - fs::unique_file("file-system-test-%%-%%-%%-%%/test-directory.anchor", fd, - TestDirectory)); + fs::createUniqueDirectory("file-system-test", TestDirectory)); // We don't care about this specific file. - ::close(fd); - TestDirectory = path::parent_path(TestDirectory); errs() << "Test Directory: " << TestDirectory << '\n'; errs().flush(); } virtual void TearDown() { - uint32_t removed; - ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), removed)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } }; +TEST_F(FileSystemTest, Unique) { + // Create a temp file. + int FileDescriptor; + SmallString<64> TempPath; + ASSERT_NO_ERROR( + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + + // The same file should return an identical unique id. + fs::UniqueID F1, F2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F1)); + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F2)); + ASSERT_EQ(F1, F2); + + // Different files should return different unique ids. + int FileDescriptor2; + SmallString<64> TempPath2; + ASSERT_NO_ERROR( + fs::createTemporaryFile("prefix", "temp", FileDescriptor2, TempPath2)); + + fs::UniqueID D; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D)); + ASSERT_NE(D, F1); + ::close(FileDescriptor2); + + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + + // Two paths representing the same file on disk should still provide the + // same unique id. We can test this by making a hard link. + ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); + fs::UniqueID D2; + ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2)); + ASSERT_EQ(D2, F1); + + ::close(FileDescriptor); + + SmallString<128> Dir1; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("dir1", Dir1)); + ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F1)); + ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F2)); + ASSERT_EQ(F1, F2); + + SmallString<128> Dir2; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("dir2", Dir2)); + ASSERT_NO_ERROR(fs::getUniqueID(Dir2.c_str(), F2)); + ASSERT_NE(F1, F2); +} + TEST_F(FileSystemTest, TempFiles) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( - fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath)); + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Make sure it exists. bool TempFileExists; @@ -179,7 +306,8 @@ TEST_F(FileSystemTest, TempFiles) { // Create another temp tile. int FD2; SmallString<64> TempPath2; - ASSERT_NO_ERROR(fs::unique_file("%%-%%-%%-%%.temp", FD2, TempPath2)); + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD2, TempPath2)); + ASSERT_TRUE(TempPath2.endswith(".temp")); ASSERT_NE(TempPath.str(), TempPath2.str()); fs::file_status A, B; @@ -187,22 +315,26 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B)); EXPECT_FALSE(fs::equivalent(A, B)); - // Try to copy the first to the second. - EXPECT_EQ( - fs::copy_file(Twine(TempPath), Twine(TempPath2)), errc::file_exists); - ::close(FD2); - // Try again with the proper options. - ASSERT_NO_ERROR(fs::copy_file(Twine(TempPath), Twine(TempPath2), - fs::copy_option::overwrite_if_exists)); + // Remove Temp2. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_EQ(fs::remove(Twine(TempPath2), false), + errc::no_such_file_or_directory); + + error_code EC = fs::status(TempPath2.c_str(), B); + EXPECT_EQ(EC, errc::no_such_file_or_directory); + EXPECT_EQ(B.type(), fs::file_type::file_not_found); // Make sure Temp2 doesn't exist. ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists)); EXPECT_FALSE(TempFileExists); + SmallString<64> TempPath3; + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); + ASSERT_FALSE(TempPath3.endswith(".")); + // Create a hard link to Temp1. ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); bool equal; @@ -214,16 +346,34 @@ TEST_F(FileSystemTest, TempFiles) { // Remove Temp1. ::close(FileDescriptor); - ASSERT_NO_ERROR(fs::remove(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); // Remove the hard link. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); EXPECT_FALSE(TempFileExists); + +#ifdef LLVM_ON_WIN32 + // Path name > 260 chars should get an error. + const char *Path270 = + "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8" + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), + windows_error::path_not_found); +#endif +} + +TEST_F(FileSystemTest, CreateDir) { + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), + errc::file_exists); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); } TEST_F(FileSystemTest, DirectoryIteration) { @@ -232,17 +382,16 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_NO_ERROR(ec); // Create a known hierarchy to recurse over. - bool existed; - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/aa1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/ab1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/dontlookhere/da1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/z0/za1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/pop/p1", existed)); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/pop/p1")); typedef std::vector v_t; v_t visited; for (fs::recursive_directory_iterator i(Twine(TestDirectory) @@ -284,14 +433,67 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_LT(a0, aa1); ASSERT_LT(a0, ab1); ASSERT_LT(z0, za1); + + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0")); + ASSERT_NO_ERROR( + fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop/p1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive")); } +const char archive[] = "!\x0A"; +const char bitcode[] = "\xde\xc0\x17\x0b"; +const char coff_object[] = "\x00\x00......"; +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 }; +const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\0x00"; +const char macho_object[] = "\xfe\xed\xfa\xce..........\x00\x01"; +const char macho_executable[] = "\xfe\xed\xfa\xce..........\x00\x02"; +const char macho_fixed_virtual_memory_shared_lib[] = + "\xfe\xed\xfa\xce..........\x00\x03"; +const char macho_core[] = "\xfe\xed\xfa\xce..........\x00\x04"; +const char macho_preload_executable[] = "\xfe\xed\xfa\xce..........\x00\x05"; +const char macho_dynamically_linked_shared_lib[] = + "\xfe\xed\xfa\xce..........\x00\x06"; +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 windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; + TEST_F(FileSystemTest, Magic) { struct type { const char *filename; const char *magic_str; - size_t magic_str_len; - } types [] = {{"magic.archive", "!\x0A", 8}}; + size_t magic_str_len; + fs::file_magic magic; + } types[] = { +#define DEFINE(magic) \ + { #magic, magic, sizeof(magic), fs::file_magic::magic } + DEFINE(archive), + DEFINE(bitcode), + DEFINE(coff_object), + DEFINE(coff_import_library), + DEFINE(elf_relocatable), + DEFINE(macho_universal_binary), + DEFINE(macho_object), + DEFINE(macho_executable), + DEFINE(macho_fixed_virtual_memory_shared_lib), + DEFINE(macho_core), + DEFINE(macho_preload_executable), + DEFINE(macho_dynamically_linked_shared_lib), + DEFINE(macho_dynamic_linker), + DEFINE(macho_bundle), + DEFINE(macho_dsym_companion), + DEFINE(windows_resource) +#undef DEFINE + }; // Create some files filled with magic. for (type *i = types, *e = types + (sizeof(types) / sizeof(type)); i != e; @@ -299,8 +501,7 @@ TEST_F(FileSystemTest, Magic) { SmallString<128> file_pathname(TestDirectory); path::append(file_pathname, i->filename); std::string ErrMsg; - raw_fd_ostream file(file_pathname.c_str(), ErrMsg, - raw_fd_ostream::F_Binary); + raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; @@ -308,34 +509,39 @@ TEST_F(FileSystemTest, Magic) { bool res = false; ASSERT_NO_ERROR(fs::has_magic(file_pathname.c_str(), magic, res)); EXPECT_TRUE(res); + EXPECT_EQ(i->magic, fs::identify_magic(magic)); + ASSERT_NO_ERROR(fs::remove(Twine(file_pathname))); } } -#if !defined(_WIN32) // FIXME: Win32 has different permission schema. -TEST_F(FileSystemTest, Permissions) { - // Create a temp file. - int FileDescriptor; - SmallString<64> TempPath; - ASSERT_NO_ERROR( - fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath)); - - // Mark file as read-only - const fs::perms AllWrite = fs::owner_write|fs::group_write|fs::others_write; - ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::remove_perms|AllWrite)); - - // Verify file is read-only - fs::file_status Status; - ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status)); - bool AnyWriteBits = (Status.permissions() & AllWrite); - EXPECT_FALSE(AnyWriteBits); - - // Mark file as read-write - ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::add_perms|AllWrite)); - - // Verify file is read-write - ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status)); - AnyWriteBits = (Status.permissions() & AllWrite); - EXPECT_TRUE(AnyWriteBits); +#ifdef LLVM_ON_WIN32 +TEST_F(FileSystemTest, CarriageReturn) { + SmallString<128> FilePathname(TestDirectory); + std::string ErrMsg; + path::append(FilePathname, "test"); + + { + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); + EXPECT_EQ(ErrMsg, ""); + File << '\n'; + } + { + OwningPtr Buf; + MemoryBuffer::getFile(FilePathname.c_str(), Buf); + EXPECT_EQ(Buf->getBuffer(), "\r\n"); + } + + { + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); + EXPECT_EQ(ErrMsg, ""); + File << '\n'; + } + { + OwningPtr Buf; + MemoryBuffer::getFile(FilePathname.c_str(), Buf); + EXPECT_EQ(Buf->getBuffer(), "\n"); + } + ASSERT_NO_ERROR(fs::remove(Twine(FilePathname))); } #endif @@ -344,12 +550,13 @@ TEST_F(FileSystemTest, FileMapping) { int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( - fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath)); + fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Map in temp file and add some content error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, + true, fs::mapped_file_region::readwrite, 4096, 0, @@ -360,7 +567,7 @@ TEST_F(FileSystemTest, FileMapping) { mfr.data()[Val.size()] = 0; // Unmap temp file } - + // Map it back in read-only fs::mapped_file_region mfr(Twine(TempPath), fs::mapped_file_region::readonly, @@ -368,13 +575,12 @@ TEST_F(FileSystemTest, FileMapping) { 0, EC); ASSERT_NO_ERROR(EC); - + // Verify content EXPECT_EQ(StringRef(mfr.const_data()), Val); - + // Unmap temp file -#if LLVM_HAS_RVALUE_REFERENCES fs::mapped_file_region m(Twine(TempPath), fs::mapped_file_region::readonly, 0, @@ -382,8 +588,7 @@ TEST_F(FileSystemTest, FileMapping) { EC); ASSERT_NO_ERROR(EC); const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(llvm_move(m)); + fs::mapped_file_region mfrrv(std::move(m)); EXPECT_EQ(mfrrv.const_data(), Data); -#endif } } // anonymous namespace