15fce8c4fSNick Kledzik //===- llvm/unittest/Support/FileOutputBuffer.cpp - unit tests ------------===//
25fce8c4fSNick Kledzik //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65fce8c4fSNick Kledzik //
75fce8c4fSNick Kledzik //===----------------------------------------------------------------------===//
85fce8c4fSNick Kledzik
99a67b073SChandler Carruth #include "llvm/Support/FileOutputBuffer.h"
10281f23adSRafael Espindola #include "llvm/Support/Errc.h"
115fce8c4fSNick Kledzik #include "llvm/Support/ErrorHandling.h"
125fce8c4fSNick Kledzik #include "llvm/Support/FileSystem.h"
131adca7c4SZachary Turner #include "llvm/Support/MemoryBuffer.h"
143bc8e719SRafael Espindola #include "llvm/Support/Path.h"
155fce8c4fSNick Kledzik #include "llvm/Support/raw_ostream.h"
165fce8c4fSNick Kledzik #include "gtest/gtest.h"
175fce8c4fSNick Kledzik
185fce8c4fSNick Kledzik using namespace llvm;
195fce8c4fSNick Kledzik using namespace llvm::sys;
205fce8c4fSNick Kledzik
210d802a49SPavel Labath #define ASSERT_NO_ERROR(x) \
220d802a49SPavel Labath if (std::error_code ASSERT_NO_ERROR_ec = x) { \
230d802a49SPavel Labath SmallString<128> MessageStorage; \
240d802a49SPavel Labath raw_svector_ostream Message(MessageStorage); \
250d802a49SPavel Labath Message << #x ": did not return errc::success.\n" \
260d802a49SPavel Labath << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
270d802a49SPavel Labath << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
280d802a49SPavel Labath GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
290d802a49SPavel Labath } else { \
300d802a49SPavel Labath }
315fce8c4fSNick Kledzik
325fce8c4fSNick Kledzik namespace {
TEST(FileOutputBuffer,Test)335fce8c4fSNick Kledzik TEST(FileOutputBuffer, Test) {
345fce8c4fSNick Kledzik // Create unique temporary directory for these tests
355fce8c4fSNick Kledzik SmallString<128> TestDirectory;
365fce8c4fSNick Kledzik {
375fce8c4fSNick Kledzik ASSERT_NO_ERROR(
387ffacc49SRafael Espindola fs::createUniqueDirectory("FileOutputBuffer-test", TestDirectory));
395fce8c4fSNick Kledzik }
405fce8c4fSNick Kledzik
415fce8c4fSNick Kledzik // TEST 1: Verify commit case.
425fce8c4fSNick Kledzik SmallString<128> File1(TestDirectory);
435fce8c4fSNick Kledzik File1.append("/file1");
445fce8c4fSNick Kledzik {
4581ca0df8SRafael Espindola Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
46169284a6SRafael Espindola FileOutputBuffer::create(File1, 8192);
4781ca0df8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
48169284a6SRafael Espindola std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
495fce8c4fSNick Kledzik // Start buffer with special header.
505fce8c4fSNick Kledzik memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
515fce8c4fSNick Kledzik // Write to end of buffer to verify it is writable.
525fce8c4fSNick Kledzik memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
535fce8c4fSNick Kledzik // Commit buffer.
540d7a38a8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
555fce8c4fSNick Kledzik }
5670fbe6f8SRafael Espindola
575fce8c4fSNick Kledzik // Verify file is correct size.
585fce8c4fSNick Kledzik uint64_t File1Size;
595fce8c4fSNick Kledzik ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size));
605fce8c4fSNick Kledzik ASSERT_EQ(File1Size, 8192ULL);
6178dcc03cSRafael Espindola ASSERT_NO_ERROR(fs::remove(File1.str()));
625fce8c4fSNick Kledzik
635fce8c4fSNick Kledzik // TEST 2: Verify abort case.
645fce8c4fSNick Kledzik SmallString<128> File2(TestDirectory);
655fce8c4fSNick Kledzik File2.append("/file2");
665fce8c4fSNick Kledzik {
6781ca0df8SRafael Espindola Expected<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr =
68169284a6SRafael Espindola FileOutputBuffer::create(File2, 8192);
6981ca0df8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(Buffer2OrErr.takeError()));
70169284a6SRafael Espindola std::unique_ptr<FileOutputBuffer> &Buffer2 = *Buffer2OrErr;
715fce8c4fSNick Kledzik // Fill buffer with special header.
725fce8c4fSNick Kledzik memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
735fce8c4fSNick Kledzik // Do *not* commit buffer.
745fce8c4fSNick Kledzik }
75cb402911SAlp Toker // Verify file does not exist (because buffer not committed).
76281f23adSRafael Espindola ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist),
77281f23adSRafael Espindola errc::no_such_file_or_directory);
7878dcc03cSRafael Espindola ASSERT_NO_ERROR(fs::remove(File2.str()));
795fce8c4fSNick Kledzik
805fce8c4fSNick Kledzik // TEST 3: Verify sizing down case.
815fce8c4fSNick Kledzik SmallString<128> File3(TestDirectory);
825fce8c4fSNick Kledzik File3.append("/file3");
835fce8c4fSNick Kledzik {
8481ca0df8SRafael Espindola Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
85169284a6SRafael Espindola FileOutputBuffer::create(File3, 8192000);
8681ca0df8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
87169284a6SRafael Espindola std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
885fce8c4fSNick Kledzik // Start buffer with special header.
895fce8c4fSNick Kledzik memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
905fce8c4fSNick Kledzik // Write to end of buffer to verify it is writable.
915fce8c4fSNick Kledzik memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
920d7a38a8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
935fce8c4fSNick Kledzik }
9470fbe6f8SRafael Espindola
955fce8c4fSNick Kledzik // Verify file is correct size.
965fce8c4fSNick Kledzik uint64_t File3Size;
975fce8c4fSNick Kledzik ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size));
985753cf3cSRafael Espindola ASSERT_EQ(File3Size, 8192000ULL);
9978dcc03cSRafael Espindola ASSERT_NO_ERROR(fs::remove(File3.str()));
1005fce8c4fSNick Kledzik
1015fce8c4fSNick Kledzik // TEST 4: Verify file can be made executable.
1025fce8c4fSNick Kledzik SmallString<128> File4(TestDirectory);
1035fce8c4fSNick Kledzik File4.append("/file4");
1045fce8c4fSNick Kledzik {
10581ca0df8SRafael Espindola Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
106169284a6SRafael Espindola FileOutputBuffer::create(File4, 8192, FileOutputBuffer::F_executable);
10781ca0df8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
108169284a6SRafael Espindola std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
1095fce8c4fSNick Kledzik // Start buffer with special header.
1105fce8c4fSNick Kledzik memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
1115fce8c4fSNick Kledzik // Commit buffer.
1120d7a38a8SRafael Espindola ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
1135fce8c4fSNick Kledzik }
1145fce8c4fSNick Kledzik // Verify file exists and is executable.
1155fce8c4fSNick Kledzik fs::file_status Status;
1165fce8c4fSNick Kledzik ASSERT_NO_ERROR(fs::status(Twine(File4), Status));
1175fce8c4fSNick Kledzik bool IsExecutable = (Status.permissions() & fs::owner_exe);
1185fce8c4fSNick Kledzik EXPECT_TRUE(IsExecutable);
11978dcc03cSRafael Espindola ASSERT_NO_ERROR(fs::remove(File4.str()));
1205fce8c4fSNick Kledzik
12168142324SNick Terrell // TEST 5: In-memory buffer works as expected.
12268142324SNick Terrell SmallString<128> File5(TestDirectory);
12368142324SNick Terrell File5.append("/file5");
12468142324SNick Terrell {
12568142324SNick Terrell Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
12668142324SNick Terrell FileOutputBuffer::create(File5, 8000, FileOutputBuffer::F_no_mmap);
12768142324SNick Terrell ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
12868142324SNick Terrell std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
12968142324SNick Terrell // Start buffer with special header.
13068142324SNick Terrell memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
13168142324SNick Terrell ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
13268142324SNick Terrell // Write to end of buffer to verify it is writable.
13368142324SNick Terrell memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
13468142324SNick Terrell // Commit buffer.
13568142324SNick Terrell ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
13668142324SNick Terrell }
13768142324SNick Terrell
13868142324SNick Terrell // Verify file is correct size.
13968142324SNick Terrell uint64_t File5Size;
14068142324SNick Terrell ASSERT_NO_ERROR(fs::file_size(Twine(File5), File5Size));
14168142324SNick Terrell ASSERT_EQ(File5Size, 8000ULL);
14268142324SNick Terrell ASSERT_NO_ERROR(fs::remove(File5.str()));
143*9d53db2aSFangrui Song
144*9d53db2aSFangrui Song // TEST 6: Create an empty file.
145*9d53db2aSFangrui Song SmallString<128> File6(TestDirectory);
146*9d53db2aSFangrui Song File6.append("/file6");
147*9d53db2aSFangrui Song {
148*9d53db2aSFangrui Song Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
149*9d53db2aSFangrui Song FileOutputBuffer::create(File6, 0);
150*9d53db2aSFangrui Song ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
151*9d53db2aSFangrui Song ASSERT_NO_ERROR(errorToErrorCode((*BufferOrErr)->commit()));
152*9d53db2aSFangrui Song }
153*9d53db2aSFangrui Song uint64_t File6Size;
154*9d53db2aSFangrui Song ASSERT_NO_ERROR(fs::file_size(Twine(File6), File6Size));
155*9d53db2aSFangrui Song ASSERT_EQ(File6Size, 0ULL);
156*9d53db2aSFangrui Song ASSERT_NO_ERROR(fs::remove(File6.str()));
157*9d53db2aSFangrui Song
1585fce8c4fSNick Kledzik // Clean up.
15978dcc03cSRafael Espindola ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
1605fce8c4fSNick Kledzik }
1615fce8c4fSNick Kledzik } // anonymous namespace
162