diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /unittests/Support/ReplaceFileTest.cpp | |
parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) |
Notes
Diffstat (limited to 'unittests/Support/ReplaceFileTest.cpp')
-rw-r--r-- | unittests/Support/ReplaceFileTest.cpp | 88 |
1 files changed, 74 insertions, 14 deletions
diff --git a/unittests/Support/ReplaceFileTest.cpp b/unittests/Support/ReplaceFileTest.cpp index 8b16daf3233c..794f36b1f654 100644 --- a/unittests/Support/ReplaceFileTest.cpp +++ b/unittests/Support/ReplaceFileTest.cpp @@ -52,6 +52,21 @@ class ScopedFD { ~ScopedFD() { Process::SafelyCloseFileDescriptor(FD); } }; +bool FDHasContent(int FD, StringRef Content) { + auto Buffer = MemoryBuffer::getOpenFile(FD, "", -1); + assert(Buffer); + return Buffer.get()->getBuffer() == Content; +} + +bool FileHasContent(StringRef File, StringRef Content) { + int FD = 0; + auto EC = fs::openFileForRead(File, FD); + (void)EC; + assert(!EC); + ScopedFD EventuallyCloseIt(FD); + return FDHasContent(FD, Content); +} + TEST(rename, FileOpenedForReadingCanBeReplaced) { // Create unique temporary directory for this test. SmallString<128> TestDirectory; @@ -79,25 +94,15 @@ TEST(rename, FileOpenedForReadingCanBeReplaced) { // We should still be able to read the old data through the existing // descriptor. - auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1); - ASSERT_TRUE(static_cast<bool>(Buffer)); - EXPECT_EQ(Buffer.get()->getBuffer(), "!!target!!"); + EXPECT_TRUE(FDHasContent(ReadFD, "!!target!!")); // The source file should no longer exist EXPECT_FALSE(fs::exists(SourceFileName)); } - { - // If we obtain a new descriptor for the target file, we should find that it - // contains the content that was in the source file. - int ReadFD = 0; - ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, ReadFD)); - ScopedFD EventuallyCloseIt(ReadFD); - auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1); - ASSERT_TRUE(static_cast<bool>(Buffer)); - - EXPECT_EQ(Buffer.get()->getBuffer(), "!!source!!"); - } + // If we obtain a new descriptor for the target file, we should find that it + // contains the content that was in the source file. + EXPECT_TRUE(FileHasContent(TargetFileName, "!!source!!")); // Rename the target file back to the source file name to confirm that rename // still works if the destination does not already exist. @@ -110,4 +115,59 @@ TEST(rename, FileOpenedForReadingCanBeReplaced) { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } +TEST(rename, ExistingTemp) { + // Test that existing .tmpN files don't get deleted by the Windows + // sys::fs::rename implementation. + SmallString<128> TestDirectory; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("ExistingTemp-test", TestDirectory)); + + SmallString<128> SourceFileName(TestDirectory); + path::append(SourceFileName, "source"); + + SmallString<128> TargetFileName(TestDirectory); + path::append(TargetFileName, "target"); + + SmallString<128> TargetTmp0FileName(TestDirectory); + path::append(TargetTmp0FileName, "target.tmp0"); + + SmallString<128> TargetTmp1FileName(TestDirectory); + path::append(TargetTmp1FileName, "target.tmp1"); + + ASSERT_NO_ERROR(CreateFileWithContent(SourceFileName, "!!source!!")); + ASSERT_NO_ERROR(CreateFileWithContent(TargetFileName, "!!target!!")); + ASSERT_NO_ERROR(CreateFileWithContent(TargetTmp0FileName, "!!target.tmp0!!")); + + { + // Use mapped_file_region to make sure that the destination file is mmap'ed. + // This will cause SetInformationByHandle to fail when renaming to the + // destination, and we will follow the code path that tries to give target + // a temporary name. + int TargetFD; + std::error_code EC; + ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, TargetFD)); + ScopedFD X(TargetFD); + sys::fs::mapped_file_region MFR( + TargetFD, sys::fs::mapped_file_region::readonly, 10, 0, EC); + ASSERT_FALSE(EC); + + ASSERT_NO_ERROR(fs::rename(SourceFileName, TargetFileName)); + +#ifdef _WIN32 + // Make sure that target was temporarily renamed to target.tmp1 on Windows. + // This is signified by a permission denied error as opposed to no such file + // or directory when trying to open it. + int Tmp1FD; + EXPECT_EQ(errc::permission_denied, + fs::openFileForRead(TargetTmp1FileName, Tmp1FD)); +#endif + } + + EXPECT_TRUE(FileHasContent(TargetTmp0FileName, "!!target.tmp0!!")); + + ASSERT_NO_ERROR(fs::remove(TargetFileName)); + ASSERT_NO_ERROR(fs::remove(TargetTmp0FileName)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} + } // anonymous namespace |