diff options
Diffstat (limited to 'llvm/unittests/CAS/ProgramTest.cpp')
-rw-r--r-- | llvm/unittests/CAS/ProgramTest.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/llvm/unittests/CAS/ProgramTest.cpp b/llvm/unittests/CAS/ProgramTest.cpp new file mode 100644 index 0000000..95cc359 --- /dev/null +++ b/llvm/unittests/CAS/ProgramTest.cpp @@ -0,0 +1,151 @@ +//===- MappedFileRegionBumpPtrTest.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Program.h" +#include "llvm/CAS/MappedFileRegionBumpPtr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/ThreadPool.h" +#include "gtest/gtest.h" +#if defined(__APPLE__) +#include <crt_externs.h> +#elif !defined(_MSC_VER) +// Forward declare environ in case it's not provided by stdlib.h. +extern char **environ; +#endif + +using namespace llvm; +using namespace llvm::cas; + +extern const char *TestMainArgv0; +static char ProgramID = 0; + +class CASProgramTest : public testing::Test { + std::vector<StringRef> EnvTable; + std::vector<std::string> EnvStorage; + +protected: + void SetUp() override { + auto EnvP = [] { +#if defined(_WIN32) + _wgetenv(L"TMP"); // Populate _wenviron, initially is null + return _wenviron; +#elif defined(__APPLE__) + return *_NSGetEnviron(); +#else + return environ; +#endif + }(); + ASSERT_TRUE(EnvP); + + auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef { +#if defined(_WIN32) + // On Windows convert UTF16 encoded variable to UTF8 + auto Len = wcslen(Var); + ArrayRef<char> Ref{reinterpret_cast<char const *>(Var), + Len * sizeof(*Var)}; + EnvStorage.emplace_back(); + auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back()); + EXPECT_TRUE(convStatus); + return EnvStorage.back(); +#else + (void)this; + return StringRef(Var); +#endif + }; + + while (*EnvP != nullptr) { + auto S = prepareEnvVar(*EnvP); + if (!StringRef(S).starts_with("GTEST_")) + EnvTable.emplace_back(S); + ++EnvP; + } + } + + void TearDown() override { + EnvTable.clear(); + EnvStorage.clear(); + } + + void addEnvVar(StringRef Var) { EnvTable.emplace_back(Var); } + + ArrayRef<StringRef> getEnviron() const { return EnvTable; } +}; + +#if LLVM_ENABLE_ONDISK_CAS + +TEST_F(CASProgramTest, MappedFileRegionBumpPtrTest) { + auto TestAllocator = [](StringRef Path) { + auto NewFileConstructor = [&](MappedFileRegionBumpPtr &Alloc) -> Error { + Alloc.initializeBumpPtr(0); + return Error::success(); + }; + + auto Alloc = MappedFileRegionBumpPtr::create( + Path, /*Capacity=*/10 * 1024 * 1024, + /*BumpPtrOffset=*/0, NewFileConstructor); + if (!Alloc) + ASSERT_TRUE(false); + + std::vector<unsigned *> AllocatedPtr; + AllocatedPtr.resize(100); + DefaultThreadPool Threads; + for (unsigned I = 0; I < 100; ++I) { + Threads.async( + [&](unsigned Idx) { + // Allocate a buffer that is larger than needed so allocator hits + // additional pages for test coverage. + unsigned *P = (unsigned *)Alloc->allocate(100); + *P = Idx; + AllocatedPtr[Idx] = P; + }, + I); + } + + Threads.wait(); + for (unsigned I = 0; I < 100; ++I) + EXPECT_EQ(*AllocatedPtr[I], I); + }; + + if (const char *File = getenv("LLVM_CAS_TEST_MAPPED_FILE_REGION")) { + TestAllocator(File); + exit(0); + } + + SmallString<128> FilePath; + sys::fs::createUniqueDirectory("MappedFileRegionBumpPtr", FilePath); + sys::path::append(FilePath, "allocation-file"); + + std::string Executable = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramID); + StringRef Argv[] = { + Executable, "--gtest_filter=CASProgramTest.MappedFileRegionBumpPtrTest"}; + + // Add LLVM_PROGRAM_TEST_LOCKED_FILE to the environment of the child. + std::string EnvVar = "LLVM_CAS_TEST_MAPPED_FILE_REGION="; + EnvVar += FilePath.str(); + addEnvVar(EnvVar); + + std::string Error; + bool ExecutionFailed; + sys::ProcessInfo PI = sys::ExecuteNoWait(Executable, Argv, getEnviron(), {}, + 0, &Error, &ExecutionFailed); + TestAllocator(FilePath); + + ASSERT_FALSE(ExecutionFailed) << Error; + ASSERT_TRUE(Error.empty()); + ASSERT_NE(PI.Pid, sys::ProcessInfo::InvalidPid) << "Invalid process id"; + llvm::sys::Wait(PI, /*SecondsToWait=*/5, &Error); + ASSERT_TRUE(Error.empty()); + + // Clean up after both processes finish testing. + sys::fs::remove(FilePath); + sys::fs::remove_directories(sys::path::parent_path(FilePath)); +} + +#endif // LLVM_ENABLE_ONDISK_CAS |