1*9880d681SAndroid Build Coastguard Worker //===- llvm/unittest/Support/ReplaceFileTest.cpp - unit tests -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errc.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Process.h"
16*9880d681SAndroid Build Coastguard Worker #include "gtest/gtest.h"
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Worker using namespace llvm;
19*9880d681SAndroid Build Coastguard Worker using namespace llvm::sys;
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker #define ASSERT_NO_ERROR(x) \
22*9880d681SAndroid Build Coastguard Worker do { \
23*9880d681SAndroid Build Coastguard Worker if (std::error_code ASSERT_NO_ERROR_ec = x) { \
24*9880d681SAndroid Build Coastguard Worker errs() << #x ": did not return errc::success.\n" \
25*9880d681SAndroid Build Coastguard Worker << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
26*9880d681SAndroid Build Coastguard Worker << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
27*9880d681SAndroid Build Coastguard Worker } \
28*9880d681SAndroid Build Coastguard Worker } while (false)
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker namespace {
CreateFileWithContent(const SmallString<128> & FilePath,const StringRef & content)31*9880d681SAndroid Build Coastguard Worker std::error_code CreateFileWithContent(const SmallString<128> &FilePath,
32*9880d681SAndroid Build Coastguard Worker const StringRef &content) {
33*9880d681SAndroid Build Coastguard Worker int FD = 0;
34*9880d681SAndroid Build Coastguard Worker if (std::error_code ec = fs::openFileForWrite(FilePath, FD, fs::F_None))
35*9880d681SAndroid Build Coastguard Worker return ec;
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker const bool ShouldClose = true;
38*9880d681SAndroid Build Coastguard Worker raw_fd_ostream OS(FD, ShouldClose);
39*9880d681SAndroid Build Coastguard Worker OS << content;
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker return std::error_code();
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker class ScopedFD {
45*9880d681SAndroid Build Coastguard Worker int FD;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker ScopedFD(const ScopedFD &) = delete;
48*9880d681SAndroid Build Coastguard Worker ScopedFD &operator=(const ScopedFD &) = delete;
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker public:
ScopedFD(int Descriptor)51*9880d681SAndroid Build Coastguard Worker explicit ScopedFD(int Descriptor) : FD(Descriptor) {}
~ScopedFD()52*9880d681SAndroid Build Coastguard Worker ~ScopedFD() { Process::SafelyCloseFileDescriptor(FD); }
53*9880d681SAndroid Build Coastguard Worker };
54*9880d681SAndroid Build Coastguard Worker
TEST(rename,FileOpenedForReadingCanBeReplaced)55*9880d681SAndroid Build Coastguard Worker TEST(rename, FileOpenedForReadingCanBeReplaced) {
56*9880d681SAndroid Build Coastguard Worker // Create unique temporary directory for this test.
57*9880d681SAndroid Build Coastguard Worker SmallString<128> TestDirectory;
58*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(fs::createUniqueDirectory(
59*9880d681SAndroid Build Coastguard Worker "FileOpenedForReadingCanBeReplaced-test", TestDirectory));
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Add a couple of files to the test directory.
62*9880d681SAndroid Build Coastguard Worker SmallString<128> SourceFileName(TestDirectory);
63*9880d681SAndroid Build Coastguard Worker path::append(SourceFileName, "source");
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker SmallString<128> TargetFileName(TestDirectory);
66*9880d681SAndroid Build Coastguard Worker path::append(TargetFileName, "target");
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(CreateFileWithContent(SourceFileName, "!!source!!"));
69*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(CreateFileWithContent(TargetFileName, "!!target!!"));
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker {
72*9880d681SAndroid Build Coastguard Worker // Open the target file for reading.
73*9880d681SAndroid Build Coastguard Worker int ReadFD = 0;
74*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, ReadFD));
75*9880d681SAndroid Build Coastguard Worker ScopedFD EventuallyCloseIt(ReadFD);
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker // Confirm we can replace the file while it is open.
78*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(!fs::rename(SourceFileName, TargetFileName));
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker // We should still be able to read the old data through the existing
81*9880d681SAndroid Build Coastguard Worker // descriptor.
82*9880d681SAndroid Build Coastguard Worker auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1);
83*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(static_cast<bool>(Buffer));
84*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(Buffer.get()->getBuffer(), "!!target!!");
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker // The source file should no longer exist
87*9880d681SAndroid Build Coastguard Worker EXPECT_FALSE(fs::exists(SourceFileName));
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker {
91*9880d681SAndroid Build Coastguard Worker // If we obtain a new descriptor for the target file, we should find that it
92*9880d681SAndroid Build Coastguard Worker // contains the content that was in the source file.
93*9880d681SAndroid Build Coastguard Worker int ReadFD = 0;
94*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, ReadFD));
95*9880d681SAndroid Build Coastguard Worker ScopedFD EventuallyCloseIt(ReadFD);
96*9880d681SAndroid Build Coastguard Worker auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1);
97*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(static_cast<bool>(Buffer));
98*9880d681SAndroid Build Coastguard Worker
99*9880d681SAndroid Build Coastguard Worker EXPECT_EQ(Buffer.get()->getBuffer(), "!!source!!");
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker // Rename the target file back to the source file name to confirm that rename
103*9880d681SAndroid Build Coastguard Worker // still works if the destination does not already exist.
104*9880d681SAndroid Build Coastguard Worker EXPECT_TRUE(!fs::rename(TargetFileName, SourceFileName));
105*9880d681SAndroid Build Coastguard Worker EXPECT_FALSE(fs::exists(TargetFileName));
106*9880d681SAndroid Build Coastguard Worker ASSERT_TRUE(fs::exists(SourceFileName));
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Worker // Clean up.
109*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(fs::remove(SourceFileName));
110*9880d681SAndroid Build Coastguard Worker ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker } // anonymous namespace
114