//===- llvm/unittest/Support/FileOutputBuffer.cpp - unit tests ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace llvm::sys;

#define ASSERT_NO_ERROR(x)                                                     \
  if (std::error_code ASSERT_NO_ERROR_ec = x) {                                \
    SmallString<128> MessageStorage;                                           \
    raw_svector_ostream Message(MessageStorage);                               \
    Message << #x ": did not return errc::success.\n"                          \
            << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"          \
            << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";      \
    GTEST_FATAL_FAILURE_(MessageStorage.c_str());                              \
  } else {                                                                     \
  }

namespace {
TEST(FileOutputBuffer, Test) {
  // Create unique temporary directory for these tests
  SmallString<128> TestDirectory;
  {
    ASSERT_NO_ERROR(
        fs::createUniqueDirectory("FileOutputBuffer-test", TestDirectory));
  }

  // TEST 1: Verify commit case.
  SmallString<128> File1(TestDirectory);
  File1.append("/file1");
  {
    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
        FileOutputBuffer::create(File1, 8192);
    ASSERT_NO_ERROR(BufferOrErr.getError());
    std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
    // Start buffer with special header.
    memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
    // Write to end of buffer to verify it is writable.
    memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
    // Commit buffer.
    ASSERT_NO_ERROR(Buffer->commit());
  }

  // Verify file is correct size.
  uint64_t File1Size;
  ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size));
  ASSERT_EQ(File1Size, 8192ULL);
  ASSERT_NO_ERROR(fs::remove(File1.str()));

  // TEST 2: Verify abort case.
  SmallString<128> File2(TestDirectory);
  File2.append("/file2");
  {
    ErrorOr<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr =
        FileOutputBuffer::create(File2, 8192);
    ASSERT_NO_ERROR(Buffer2OrErr.getError());
    std::unique_ptr<FileOutputBuffer> &Buffer2 = *Buffer2OrErr;
    // Fill buffer with special header.
    memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
    // Do *not* commit buffer.
  }
  // Verify file does not exist (because buffer not committed).
  ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist),
            errc::no_such_file_or_directory);
  ASSERT_NO_ERROR(fs::remove(File2.str()));

  // TEST 3: Verify sizing down case.
  SmallString<128> File3(TestDirectory);
  File3.append("/file3");
  {
    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
        FileOutputBuffer::create(File3, 8192000);
    ASSERT_NO_ERROR(BufferOrErr.getError());
    std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
    // Start buffer with special header.
    memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
    // Write to end of buffer to verify it is writable.
    memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
    ASSERT_NO_ERROR(Buffer->commit());
  }

  // Verify file is correct size.
  uint64_t File3Size;
  ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size));
  ASSERT_EQ(File3Size, 8192000ULL);
  ASSERT_NO_ERROR(fs::remove(File3.str()));

  // TEST 4: Verify file can be made executable.
  SmallString<128> File4(TestDirectory);
  File4.append("/file4");
  {
    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
        FileOutputBuffer::create(File4, 8192, FileOutputBuffer::F_executable);
    ASSERT_NO_ERROR(BufferOrErr.getError());
    std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
    // Start buffer with special header.
    memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
    // Commit buffer.
    ASSERT_NO_ERROR(Buffer->commit());
  }
  // Verify file exists and is executable.
  fs::file_status Status;
  ASSERT_NO_ERROR(fs::status(Twine(File4), Status));
  bool IsExecutable = (Status.permissions() & fs::owner_exe);
  EXPECT_TRUE(IsExecutable);
  ASSERT_NO_ERROR(fs::remove(File4.str()));

  // Clean up.
  ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
}
} // anonymous namespace
