
…Stream. CachedFileStream has previously performed the commit step in its destructor, but this means its only recourse for error handling is report_fatal_error. Modify this to add an explicit commit() method, and call this in the appropriate places with appropriate error handling for the location. Currently the destructor of CacheStream gives an assert failure in Debug builds if commit() was not called. This will help track down any remaining uses of the API that assume the old destructior behaviour. In Release builds we fall back to the previous behaviour and call report_fatal_error if the commit fails. This is version 2 of this PR, superseding reverted PR https://github.com/llvm/llvm-project/pull/115331 . I have incorporated a change to the testcase to make it more reliable on Windows, as well as two follow-up changes (df79000896
andb0baa1d8bd
) that were also reverted when 115331 was reverted. --------- Co-authored-by: Augie Fackler <augie@google.com> Co-authored-by: Vitaly Buka <vitalybuka@google.com>
158 lines
5.0 KiB
C++
158 lines
5.0 KiB
C++
//===- Caching.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/Caching.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#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 { \
|
|
}
|
|
|
|
char data[] = "some data";
|
|
|
|
TEST(Caching, Normal) {
|
|
SmallString<256> CacheDir;
|
|
sys::fs::createUniquePath("llvm_test_cache-%%%%%%", CacheDir, true);
|
|
|
|
sys::fs::remove_directories(CacheDir.str());
|
|
|
|
std::unique_ptr<MemoryBuffer> CachedBuffer;
|
|
auto AddBuffer = [&CachedBuffer](unsigned Task, const Twine &ModuleName,
|
|
std::unique_ptr<MemoryBuffer> M) {
|
|
CachedBuffer = std::move(M);
|
|
};
|
|
auto CacheOrErr =
|
|
localCache("LLVMTestCache", "LLVMTest", CacheDir, AddBuffer);
|
|
ASSERT_TRUE(bool(CacheOrErr));
|
|
|
|
FileCache &Cache = *CacheOrErr;
|
|
|
|
{
|
|
auto AddStreamOrErr = Cache(1, "foo", "");
|
|
ASSERT_TRUE(bool(AddStreamOrErr));
|
|
|
|
AddStreamFn &AddStream = *AddStreamOrErr;
|
|
ASSERT_TRUE(AddStream);
|
|
|
|
auto FileOrErr = AddStream(1, "");
|
|
ASSERT_TRUE(bool(FileOrErr));
|
|
|
|
CachedFileStream *CFS = FileOrErr->get();
|
|
(*CFS->OS).write(data, sizeof(data));
|
|
ASSERT_THAT_ERROR(CFS->commit(), Succeeded());
|
|
}
|
|
|
|
{
|
|
auto AddStreamOrErr = Cache(1, "foo", "");
|
|
ASSERT_TRUE(bool(AddStreamOrErr));
|
|
|
|
AddStreamFn &AddStream = *AddStreamOrErr;
|
|
ASSERT_FALSE(AddStream);
|
|
|
|
ASSERT_TRUE(CachedBuffer->getBufferSize() == sizeof(data));
|
|
StringRef readData = CachedBuffer->getBuffer();
|
|
ASSERT_TRUE(memcmp(data, readData.data(), sizeof(data)) == 0);
|
|
}
|
|
|
|
ASSERT_NO_ERROR(sys::fs::remove_directories(CacheDir.str()));
|
|
}
|
|
|
|
TEST(Caching, WriteAfterCommit) {
|
|
SmallString<256> CacheDir;
|
|
sys::fs::createUniquePath("llvm_test_cache-%%%%%%", CacheDir, true);
|
|
|
|
sys::fs::remove_directories(CacheDir.str());
|
|
|
|
std::unique_ptr<MemoryBuffer> CachedBuffer;
|
|
auto AddBuffer = [&CachedBuffer](unsigned Task, const Twine &ModuleName,
|
|
std::unique_ptr<MemoryBuffer> M) {
|
|
CachedBuffer = std::move(M);
|
|
};
|
|
auto CacheOrErr =
|
|
localCache("LLVMTestCache", "LLVMTest", CacheDir, AddBuffer);
|
|
ASSERT_TRUE(bool(CacheOrErr));
|
|
|
|
FileCache &Cache = *CacheOrErr;
|
|
|
|
auto AddStreamOrErr = Cache(1, "foo", "");
|
|
ASSERT_TRUE(bool(AddStreamOrErr));
|
|
|
|
AddStreamFn &AddStream = *AddStreamOrErr;
|
|
ASSERT_TRUE(AddStream);
|
|
|
|
auto FileOrErr = AddStream(1, "");
|
|
ASSERT_TRUE(bool(FileOrErr));
|
|
|
|
CachedFileStream *CFS = FileOrErr->get();
|
|
(*CFS->OS).write(data, sizeof(data));
|
|
ASSERT_THAT_ERROR(CFS->commit(), Succeeded());
|
|
|
|
EXPECT_DEATH(
|
|
{ (*CFS->OS).write(data, sizeof(data)); }, "")
|
|
<< "Write after commit did not cause abort";
|
|
|
|
ASSERT_NO_ERROR(sys::fs::remove_directories(CacheDir.str()));
|
|
}
|
|
|
|
TEST(Caching, NoCommit) {
|
|
SmallString<256> CacheDir;
|
|
sys::fs::createUniquePath("llvm_test_cache-%%%%%%", CacheDir, true);
|
|
|
|
sys::fs::remove_directories(CacheDir.str());
|
|
|
|
std::unique_ptr<MemoryBuffer> CachedBuffer;
|
|
auto AddBuffer = [&CachedBuffer](unsigned Task, const Twine &ModuleName,
|
|
std::unique_ptr<MemoryBuffer> M) {
|
|
CachedBuffer = std::move(M);
|
|
};
|
|
auto CacheOrErr =
|
|
localCache("LLVMTestCache", "LLVMTest", CacheDir, AddBuffer);
|
|
ASSERT_TRUE(bool(CacheOrErr));
|
|
|
|
FileCache &Cache = *CacheOrErr;
|
|
|
|
auto AddStreamOrErr = Cache(1, "foo", "");
|
|
ASSERT_TRUE(bool(AddStreamOrErr));
|
|
|
|
AddStreamFn &AddStream = *AddStreamOrErr;
|
|
ASSERT_TRUE(AddStream);
|
|
|
|
auto FileOrErr = AddStream(1, "");
|
|
ASSERT_TRUE(bool(FileOrErr));
|
|
|
|
CachedFileStream *CFS = FileOrErr->get();
|
|
(*CFS->OS).write(data, sizeof(data));
|
|
ASSERT_THAT_ERROR(CFS->commit(), Succeeded());
|
|
|
|
EXPECT_DEATH(
|
|
{
|
|
auto FileOrErr = AddStream(1, "");
|
|
ASSERT_TRUE(bool(FileOrErr));
|
|
|
|
CachedFileStream *CFS = FileOrErr->get();
|
|
(*CFS->OS).write(data, sizeof(data));
|
|
},
|
|
"")
|
|
<< "destruction without commit did not cause error";
|
|
|
|
ASSERT_NO_ERROR(sys::fs::remove_directories(CacheDir.str()));
|
|
}
|