162 lines · cpp
1//===- llvm/unittest/Support/FileOutputBuffer.cpp - unit tests ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/FileOutputBuffer.h"10#include "llvm/Support/Errc.h"11#include "llvm/Support/ErrorHandling.h"12#include "llvm/Support/FileSystem.h"13#include "llvm/Support/MemoryBuffer.h"14#include "llvm/Support/Path.h"15#include "llvm/Support/raw_ostream.h"16#include "gtest/gtest.h"17 18using namespace llvm;19using namespace llvm::sys;20 21#define ASSERT_NO_ERROR(x) \22 if (std::error_code ASSERT_NO_ERROR_ec = x) { \23 SmallString<128> MessageStorage; \24 raw_svector_ostream Message(MessageStorage); \25 Message << #x ": did not return errc::success.\n" \26 << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \27 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \28 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \29 } else { \30 }31 32namespace {33TEST(FileOutputBuffer, Test) {34 // Create unique temporary directory for these tests35 SmallString<128> TestDirectory;36 {37 ASSERT_NO_ERROR(38 fs::createUniqueDirectory("FileOutputBuffer-test", TestDirectory));39 }40 41 // TEST 1: Verify commit case.42 SmallString<128> File1(TestDirectory);43 File1.append("/file1");44 {45 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =46 FileOutputBuffer::create(File1, 8192);47 ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));48 std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;49 // Start buffer with special header.50 memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);51 // Write to end of buffer to verify it is writable.52 memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);53 // Commit buffer.54 ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));55 }56 57 // Verify file is correct size.58 uint64_t File1Size;59 ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size));60 ASSERT_EQ(File1Size, 8192ULL);61 ASSERT_NO_ERROR(fs::remove(File1.str()));62 63 // TEST 2: Verify abort case.64 SmallString<128> File2(TestDirectory);65 File2.append("/file2");66 {67 Expected<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr =68 FileOutputBuffer::create(File2, 8192);69 ASSERT_NO_ERROR(errorToErrorCode(Buffer2OrErr.takeError()));70 std::unique_ptr<FileOutputBuffer> &Buffer2 = *Buffer2OrErr;71 // Fill buffer with special header.72 memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);73 // Do *not* commit buffer.74 }75 // Verify file does not exist (because buffer not committed).76 ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist),77 errc::no_such_file_or_directory);78 ASSERT_NO_ERROR(fs::remove(File2.str()));79 80 // TEST 3: Verify sizing down case.81 SmallString<128> File3(TestDirectory);82 File3.append("/file3");83 {84 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =85 FileOutputBuffer::create(File3, 8192000);86 ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));87 std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;88 // Start buffer with special header.89 memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);90 // Write to end of buffer to verify it is writable.91 memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);92 ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));93 }94 95 // Verify file is correct size.96 uint64_t File3Size;97 ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size));98 ASSERT_EQ(File3Size, 8192000ULL);99 ASSERT_NO_ERROR(fs::remove(File3.str()));100 101 // TEST 4: Verify file can be made executable.102 SmallString<128> File4(TestDirectory);103 File4.append("/file4");104 {105 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =106 FileOutputBuffer::create(File4, 8192, FileOutputBuffer::F_executable);107 ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));108 std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;109 // Start buffer with special header.110 memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);111 // Commit buffer.112 ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));113 }114 // Verify file exists and is executable.115 fs::file_status Status;116 ASSERT_NO_ERROR(fs::status(Twine(File4), Status));117 bool IsExecutable = (Status.permissions() & fs::owner_exe);118 EXPECT_TRUE(IsExecutable);119 ASSERT_NO_ERROR(fs::remove(File4.str()));120 121 // TEST 5: In-memory buffer works as expected.122 SmallString<128> File5(TestDirectory);123 File5.append("/file5");124 {125 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =126 FileOutputBuffer::create(File5, 8000, FileOutputBuffer::F_mmap);127 ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));128 std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;129 // Start buffer with special header.130 memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);131 ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));132 // Write to end of buffer to verify it is writable.133 memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);134 // Commit buffer.135 ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));136 }137 138 // Verify file is correct size.139 uint64_t File5Size;140 ASSERT_NO_ERROR(fs::file_size(Twine(File5), File5Size));141 ASSERT_EQ(File5Size, 8000ULL);142 ASSERT_NO_ERROR(fs::remove(File5.str()));143 144 // TEST 6: Create an empty file.145 SmallString<128> File6(TestDirectory);146 File6.append("/file6");147 {148 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =149 FileOutputBuffer::create(File6, 0);150 ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));151 ASSERT_NO_ERROR(errorToErrorCode((*BufferOrErr)->commit()));152 }153 uint64_t File6Size;154 ASSERT_NO_ERROR(fs::file_size(Twine(File6), File6Size));155 ASSERT_EQ(File6Size, 0ULL);156 ASSERT_NO_ERROR(fs::remove(File6.str()));157 158 // Clean up.159 ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));160}161} // anonymous namespace162