diff options
Diffstat (limited to 'llvm/unittests')
-rw-r--r-- | llvm/unittests/ADT/BitTest.cpp | 38 | ||||
-rw-r--r-- | llvm/unittests/ADT/STLForwardCompatTest.cpp | 22 | ||||
-rw-r--r-- | llvm/unittests/ADT/StringSwitchTest.cpp | 8 | ||||
-rw-r--r-- | llvm/unittests/Analysis/ValueTrackingTest.cpp | 10 | ||||
-rw-r--r-- | llvm/unittests/CAS/CASTestConfig.cpp | 14 | ||||
-rw-r--r-- | llvm/unittests/CAS/CASTestConfig.h | 11 | ||||
-rw-r--r-- | llvm/unittests/CAS/CMakeLists.txt | 21 | ||||
-rw-r--r-- | llvm/unittests/CAS/OnDiskCommonUtils.h | 76 | ||||
-rw-r--r-- | llvm/unittests/CAS/OnDiskGraphDBTest.cpp | 310 | ||||
-rw-r--r-- | llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp | 77 | ||||
-rw-r--r-- | llvm/unittests/IR/IRBuilderTest.cpp | 1 |
11 files changed, 580 insertions, 8 deletions
diff --git a/llvm/unittests/ADT/BitTest.cpp b/llvm/unittests/ADT/BitTest.cpp index eaed4e1..e8041bb 100644 --- a/llvm/unittests/ADT/BitTest.cpp +++ b/llvm/unittests/ADT/BitTest.cpp @@ -270,6 +270,44 @@ TEST(BitTest, BitWidthConstexpr) { llvm::bit_width_constexpr(std::numeric_limits<uint64_t>::max()) == 64); } +TEST(BitTest, BitCeilConstexpr) { + static_assert(llvm::bit_ceil_constexpr(0u) == 1); + static_assert(llvm::bit_ceil_constexpr(1u) == 1); + static_assert(llvm::bit_ceil_constexpr(2u) == 2); + static_assert(llvm::bit_ceil_constexpr(3u) == 4); + static_assert(llvm::bit_ceil_constexpr(4u) == 4); + static_assert(llvm::bit_ceil_constexpr(5u) == 8); + static_assert(llvm::bit_ceil_constexpr(6u) == 8); + static_assert(llvm::bit_ceil_constexpr(7u) == 8); + static_assert(llvm::bit_ceil_constexpr(8u) == 8); + + static_assert(llvm::bit_ceil_constexpr(255u) == 256); + static_assert(llvm::bit_ceil_constexpr(256u) == 256); + static_assert(llvm::bit_ceil_constexpr(257u) == 512); +} + +TEST(BitTest, CountrZeroConstexpr) { + static_assert(llvm::countr_zero_constexpr(0u) == 32); + static_assert(llvm::countr_zero_constexpr(1u) == 0); + static_assert(llvm::countr_zero_constexpr(2u) == 1); + static_assert(llvm::countr_zero_constexpr(3u) == 0); + static_assert(llvm::countr_zero_constexpr(4u) == 2); + static_assert(llvm::countr_zero_constexpr(8u) == 3); + static_assert(llvm::countr_zero_constexpr(0x80000000u) == 31); + + static_assert(llvm::countr_zero_constexpr(0ull) == 64); + static_assert(llvm::countr_zero_constexpr(1ull) == 0); + static_assert(llvm::countr_zero_constexpr(0x100000000ull) == 32); + static_assert(llvm::countr_zero_constexpr(0x8000000000000000ull) == 63); + + static_assert( + llvm::countr_zero_constexpr(std::numeric_limits<uint16_t>::max()) == 0); + static_assert( + llvm::countr_zero_constexpr(std::numeric_limits<uint32_t>::max()) == 0); + static_assert( + llvm::countr_zero_constexpr(std::numeric_limits<uint64_t>::max()) == 0); +} + TEST(BitTest, CountlZero) { uint8_t Z8 = 0; uint16_t Z16 = 0; diff --git a/llvm/unittests/ADT/STLForwardCompatTest.cpp b/llvm/unittests/ADT/STLForwardCompatTest.cpp index 4a8f53c..2a97e8d 100644 --- a/llvm/unittests/ADT/STLForwardCompatTest.cpp +++ b/llvm/unittests/ADT/STLForwardCompatTest.cpp @@ -184,4 +184,26 @@ TEST(TransformTest, ToUnderlying) { static_assert(llvm::to_underlying(E3::B3) == 0); } +TEST(STLForwardCompatTest, IdentityCxx20) { + llvm::identity_cxx20 identity; + + // Test with an lvalue. + int X = 42; + int &Y = identity(X); + EXPECT_EQ(&X, &Y); + + // Test with a const lvalue. + const int CX = 10; + const int &CY = identity(CX); + EXPECT_EQ(&CX, &CY); + + // Test with an rvalue. + EXPECT_EQ(identity(123), 123); + + // Test perfect forwarding. + static_assert(std::is_same_v<int &, decltype(identity(X))>); + static_assert(std::is_same_v<const int &, decltype(identity(CX))>); + static_assert(std::is_same_v<int &&, decltype(identity(int(5)))>); +} + } // namespace diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp index 0fbf371..d88a0ff 100644 --- a/llvm/unittests/ADT/StringSwitchTest.cpp +++ b/llvm/unittests/ADT/StringSwitchTest.cpp @@ -159,7 +159,7 @@ TEST(StringSwitchTest, Cases) { return llvm::StringSwitch<OSType>(S) .Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt", OSType::Windows) - .Cases("linux", "unix", "*nix", "posix", OSType::Linux) + .Cases({"linux", "unix", "*nix", "posix"}, OSType::Linux) .Cases({"macos", "osx"}, OSType::MacOS) .Default(OSType::Unknown); }; @@ -191,7 +191,7 @@ TEST(StringSwitchTest, CasesLower) { return llvm::StringSwitch<OSType>(S) .CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt", OSType::Windows) - .CasesLower("linux", "unix", "*nix", "posix", OSType::Linux) + .CasesLower({"linux", "unix", "*nix", "posix"}, OSType::Linux) .CasesLower({"macos", "osx"}, OSType::MacOS) .Default(OSType::Unknown); }; @@ -230,13 +230,13 @@ TEST(StringSwitchTest, CasesCopies) { // Check that evaluating multiple cases does not cause unnecessary copies. unsigned NumCopies = 0; - llvm::StringSwitch<Copyable, void>("baz").Cases("foo", "bar", "baz", "qux", + llvm::StringSwitch<Copyable, void>("baz").Cases({"foo", "bar", "baz", "qux"}, Copyable{NumCopies}); EXPECT_EQ(NumCopies, 1u); NumCopies = 0; llvm::StringSwitch<Copyable, void>("baz").CasesLower( - "Foo", "Bar", "Baz", "Qux", Copyable{NumCopies}); + {"Foo", "Bar", "Baz", "Qux"}, Copyable{NumCopies}); EXPECT_EQ(NumCopies, 1u); } diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 559a0b7..bb0280ee 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -1091,6 +1091,16 @@ TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison) { } } +TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison_splat) { + parseAssembly( + "define <4 x i32> @test(i32 noundef %x) {\n" + " %ins = insertelement <4 x i32> poison, i32 %x, i32 0\n" + " %A = shufflevector <4 x i32> %ins, <4 x i32> poison, <4 x i32> zeroinitializer\n" + " ret <4 x i32> %A\n" + "}"); + EXPECT_TRUE(isGuaranteedNotToBeUndefOrPoison(A)); +} + TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison_assume) { parseAssembly("declare i1 @f_i1()\n" "declare i32 @f_i32()\n" diff --git a/llvm/unittests/CAS/CASTestConfig.cpp b/llvm/unittests/CAS/CASTestConfig.cpp index 29e2db4..91d0970 100644 --- a/llvm/unittests/CAS/CASTestConfig.cpp +++ b/llvm/unittests/CAS/CASTestConfig.cpp @@ -19,3 +19,17 @@ static CASTestingEnv createInMemory(int I) { INSTANTIATE_TEST_SUITE_P(InMemoryCAS, CASTest, ::testing::Values(createInMemory)); + +#if LLVM_ENABLE_ONDISK_CAS +namespace llvm::cas::ondisk { +extern void setMaxMappingSize(uint64_t Size); +} // namespace llvm::cas::ondisk + +void setMaxOnDiskCASMappingSize() { + static std::once_flag Flag; + std::call_once( + Flag, [] { llvm::cas::ondisk::setMaxMappingSize(100 * 1024 * 1024); }); +} +#else +void setMaxOnDiskCASMappingSize() {} +#endif /* LLVM_ENABLE_ONDISK_CAS */ diff --git a/llvm/unittests/CAS/CASTestConfig.h b/llvm/unittests/CAS/CASTestConfig.h index 8093a0b..c08968b 100644 --- a/llvm/unittests/CAS/CASTestConfig.h +++ b/llvm/unittests/CAS/CASTestConfig.h @@ -18,6 +18,17 @@ struct CASTestingEnv { std::unique_ptr<llvm::cas::ActionCache> Cache; }; +void setMaxOnDiskCASMappingSize(); + +// Test fixture for on-disk data base tests. +class OnDiskCASTest : public ::testing::Test { +protected: + void SetUp() override { + // Use a smaller database size for testing to conserve disk space. + setMaxOnDiskCASMappingSize(); + } +}; + class CASTest : public testing::TestWithParam<std::function<CASTestingEnv(int)>> { protected: diff --git a/llvm/unittests/CAS/CMakeLists.txt b/llvm/unittests/CAS/CMakeLists.txt index ee40e6c..da469f7 100644 --- a/llvm/unittests/CAS/CMakeLists.txt +++ b/llvm/unittests/CAS/CMakeLists.txt @@ -1,3 +1,19 @@ +set(ONDISK_CAS_TEST_SOURCES + OnDiskGraphDBTest.cpp + OnDiskDataAllocatorTest.cpp + OnDiskKeyValueDBTest.cpp + OnDiskTrieRawHashMapTest.cpp + ProgramTest.cpp + ) + +set(LLVM_OPTIONAL_SOURCES + ${ONDISK_CAS_TEST_SOURCES} + ) + +if (NOT LLVM_ENABLE_ONDISK_CAS) + unset(ONDISK_CAS_TEST_SOURCES) +endif() + set(LLVM_LINK_COMPONENTS Support CAS @@ -8,9 +24,8 @@ add_llvm_unittest(CASTests ActionCacheTest.cpp CASTestConfig.cpp ObjectStoreTest.cpp - OnDiskDataAllocatorTest.cpp - OnDiskTrieRawHashMapTest.cpp - ProgramTest.cpp + + ${ONDISK_CAS_TEST_SOURCES} ) target_link_libraries(CASTests PRIVATE LLVMTestingSupport) diff --git a/llvm/unittests/CAS/OnDiskCommonUtils.h b/llvm/unittests/CAS/OnDiskCommonUtils.h new file mode 100644 index 0000000..57c8c22 --- /dev/null +++ b/llvm/unittests/CAS/OnDiskCommonUtils.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +/// \file Helper functions to test OnDiskCASDatabases. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CAS/BuiltinObjectHasher.h" +#include "llvm/CAS/OnDiskGraphDB.h" +#include "llvm/Support/BLAKE3.h" +#include "llvm/Testing/Support/Error.h" + +namespace llvm::unittest::cas { + +using namespace llvm::cas; +using namespace llvm::cas::ondisk; + +using HasherT = BLAKE3; +using HashType = decltype(HasherT::hash(std::declval<ArrayRef<uint8_t> &>())); +using ValueType = std::array<char, 20>; + +inline HashType digest(StringRef Data, ArrayRef<ArrayRef<uint8_t>> RefHashes) { + return BuiltinObjectHasher<HasherT>::hashObject( + RefHashes, arrayRefFromStringRef<char>(Data)); +} + +inline ObjectID digest(OnDiskGraphDB &DB, StringRef Data, + ArrayRef<ObjectID> Refs) { + SmallVector<ArrayRef<uint8_t>, 8> RefHashes; + for (ObjectID Ref : Refs) + RefHashes.push_back(DB.getDigest(Ref)); + HashType Digest = digest(Data, RefHashes); + std::optional<ObjectID> ID; + EXPECT_THAT_ERROR(DB.getReference(Digest).moveInto(ID), Succeeded()); + return *ID; +} + +inline HashType digest(StringRef Data) { + return HasherT::hash(arrayRefFromStringRef(Data)); +} + +inline ValueType valueFromString(StringRef S) { + ValueType Val; + llvm::copy(S.substr(0, sizeof(Val)), Val.data()); + return Val; +} + +inline Expected<ObjectID> store(OnDiskGraphDB &DB, StringRef Data, + ArrayRef<ObjectID> Refs) { + ObjectID ID = digest(DB, Data, Refs); + if (Error E = DB.store(ID, Refs, arrayRefFromStringRef<char>(Data))) + return std::move(E); + return ID; +} + +inline Error printTree(OnDiskGraphDB &DB, ObjectID ID, raw_ostream &OS, + unsigned Indent = 0) { + std::optional<ondisk::ObjectHandle> Obj; + if (Error E = DB.load(ID).moveInto(Obj)) + return E; + if (!Obj) + return Error::success(); + OS.indent(Indent) << toStringRef(DB.getObjectData(*Obj)) << '\n'; + for (ObjectID Ref : DB.getObjectRefs(*Obj)) { + if (Error E = printTree(DB, Ref, OS, Indent + 2)) + return E; + } + return Error::success(); +} + +} // namespace llvm::unittest::cas diff --git a/llvm/unittests/CAS/OnDiskGraphDBTest.cpp b/llvm/unittests/CAS/OnDiskGraphDBTest.cpp new file mode 100644 index 0000000..58f5dcc6 --- /dev/null +++ b/llvm/unittests/CAS/OnDiskGraphDBTest.cpp @@ -0,0 +1,310 @@ +//===----------------------------------------------------------------------===// +// +// 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 "CASTestConfig.h" +#include "OnDiskCommonUtils.h" +#include "llvm/Testing/Support/Error.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::cas; +using namespace llvm::cas::ondisk; +using namespace llvm::unittest::cas; + +TEST_F(OnDiskCASTest, OnDiskGraphDBTest) { + unittest::TempDir Temp("ondiskcas", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> DB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType)).moveInto(DB), + Succeeded()); + + auto digest = [&DB](StringRef Data, ArrayRef<ObjectID> Refs) -> ObjectID { + return ::digest(*DB, Data, Refs); + }; + + auto store = [&](StringRef Data, + ArrayRef<ObjectID> Refs) -> Expected<ObjectID> { + return ::store(*DB, Data, Refs); + }; + + std::optional<ObjectID> ID1; + ASSERT_THAT_ERROR(store("hello", {}).moveInto(ID1), Succeeded()); + + std::optional<ondisk::ObjectHandle> Obj1; + ASSERT_THAT_ERROR(DB->load(*ID1).moveInto(Obj1), Succeeded()); + ASSERT_TRUE(Obj1.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj1)), "hello"); + + ArrayRef<uint8_t> Digest1 = DB->getDigest(*ID1); + std::optional<ObjectID> ID2; + ASSERT_THAT_ERROR(DB->getReference(Digest1).moveInto(ID2), Succeeded()); + EXPECT_EQ(ID1, ID2); + + ObjectID ID3 = digest("world", {}); + EXPECT_FALSE(DB->containsObject(ID3)); + std::optional<ondisk::ObjectHandle> Obj2; + ASSERT_THAT_ERROR(DB->load(ID3).moveInto(Obj2), Succeeded()); + EXPECT_FALSE(Obj2.has_value()); + + ASSERT_THAT_ERROR(DB->store(ID3, {}, arrayRefFromStringRef<char>("world")), + Succeeded()); + EXPECT_TRUE(DB->containsObject(ID3)); + ASSERT_THAT_ERROR(DB->load(ID3).moveInto(Obj2), Succeeded()); + ASSERT_TRUE(Obj2.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj2)), "world"); + + size_t LargeDataSize = 256LL * 1024LL; // 256K. + // The precise size number is not important, we mainly check that the large + // object will be properly accounted for. + EXPECT_TRUE(DB->getStorageSize() > 10 && + DB->getStorageSize() < LargeDataSize); + + SmallString<16> Buffer; + Buffer.resize(LargeDataSize); + ASSERT_THAT_ERROR(store(Buffer, {}).moveInto(ID1), Succeeded()); + size_t StorageSize = DB->getStorageSize(); + EXPECT_TRUE(StorageSize > LargeDataSize); + + // Close & re-open the DB and check that it reports the same storage size. + DB.reset(); + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType)).moveInto(DB), + Succeeded()); + EXPECT_EQ(DB->getStorageSize(), StorageSize); +} + +TEST_F(OnDiskCASTest, OnDiskGraphDBFaultInSingleNode) { + unittest::TempDir TempUpstream("ondiskcas-upstream", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> UpstreamDB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(TempUpstream.path(), "blake3", sizeof(HashType)) + .moveInto(UpstreamDB), + Succeeded()); + { + std::optional<ObjectID> ID1; + ASSERT_THAT_ERROR(store(*UpstreamDB, "hello", {}).moveInto(ID1), + Succeeded()); + std::optional<ObjectID> ID2; + ASSERT_THAT_ERROR(store(*UpstreamDB, "another", {}).moveInto(ID2), + Succeeded()); + std::optional<ObjectID> ID3; + ASSERT_THAT_ERROR(store(*UpstreamDB, "world", {*ID1, *ID2}).moveInto(ID3), + Succeeded()); + } + + unittest::TempDir Temp("ondiskcas", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> DB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType), + std::move(UpstreamDB), + OnDiskGraphDB::FaultInPolicy::SingleNode) + .moveInto(DB), + Succeeded()); + + ObjectID ID1 = digest(*DB, "hello", {}); + ObjectID ID2 = digest(*DB, "another", {}); + ObjectID ID3 = digest(*DB, "world", {ID1, ID2}); + ObjectID ID4 = digest(*DB, "world", {}); + + EXPECT_TRUE(DB->containsObject(ID1)); + EXPECT_TRUE(DB->containsObject(ID2)); + EXPECT_TRUE(DB->containsObject(ID3)); + EXPECT_FALSE(DB->containsObject(ID4)); + + EXPECT_TRUE(DB->getExistingReference(digest("hello", {})).has_value()); + EXPECT_TRUE(DB->getExistingReference(DB->getDigest(ID3)).has_value()); + EXPECT_FALSE(DB->getExistingReference(digest("world", {})).has_value()); + + { + std::optional<ondisk::ObjectHandle> Obj; + ASSERT_THAT_ERROR(DB->load(ID1).moveInto(Obj), Succeeded()); + ASSERT_TRUE(Obj.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj)), "hello"); + auto Refs = DB->getObjectRefs(*Obj); + EXPECT_TRUE(Refs.empty()); + } + { + std::optional<ondisk::ObjectHandle> Obj; + ASSERT_THAT_ERROR(DB->load(ID3).moveInto(Obj), Succeeded()); + ASSERT_TRUE(Obj.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj)), "world"); + auto Refs = DB->getObjectRefs(*Obj); + ASSERT_EQ(std::distance(Refs.begin(), Refs.end()), 2); + EXPECT_EQ(Refs.begin()[0], ID1); + EXPECT_EQ(Refs.begin()[1], ID2); + } + { + std::optional<ondisk::ObjectHandle> Obj; + ASSERT_THAT_ERROR(DB->load(ID4).moveInto(Obj), Succeeded()); + EXPECT_FALSE(Obj.has_value()); + } + + // Re-open the primary without chaining, to verify the data were copied from + // the upstream. + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType), + /*UpstreamDB=*/nullptr, + OnDiskGraphDB::FaultInPolicy::SingleNode) + .moveInto(DB), + Succeeded()); + ID1 = digest(*DB, "hello", {}); + ID2 = digest(*DB, "another", {}); + ID3 = digest(*DB, "world", {ID1, ID2}); + EXPECT_TRUE(DB->containsObject(ID1)); + EXPECT_FALSE(DB->containsObject(ID2)); + EXPECT_TRUE(DB->containsObject(ID3)); + { + std::optional<ondisk::ObjectHandle> Obj; + ASSERT_THAT_ERROR(DB->load(ID1).moveInto(Obj), Succeeded()); + ASSERT_TRUE(Obj.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj)), "hello"); + auto Refs = DB->getObjectRefs(*Obj); + EXPECT_TRUE(Refs.empty()); + } +} + +TEST_F(OnDiskCASTest, OnDiskGraphDBFaultInFullTree) { + unittest::TempDir TempUpstream("ondiskcas-upstream", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> UpstreamDB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(TempUpstream.path(), "blake3", sizeof(HashType)) + .moveInto(UpstreamDB), + Succeeded()); + HashType RootHash; + { + std::optional<ObjectID> ID11; + ASSERT_THAT_ERROR(store(*UpstreamDB, "11", {}).moveInto(ID11), Succeeded()); + std::optional<ObjectID> ID121; + ASSERT_THAT_ERROR(store(*UpstreamDB, "121", {}).moveInto(ID121), + Succeeded()); + std::optional<ObjectID> ID12; + ASSERT_THAT_ERROR(store(*UpstreamDB, "12", {*ID121}).moveInto(ID12), + Succeeded()); + std::optional<ObjectID> ID1; + ASSERT_THAT_ERROR(store(*UpstreamDB, "1", {*ID11, *ID12}).moveInto(ID1), + Succeeded()); + std::optional<ObjectID> ID21; + ASSERT_THAT_ERROR(store(*UpstreamDB, "21", {}).moveInto(ID21), Succeeded()); + std::optional<ObjectID> ID22; + ASSERT_THAT_ERROR(store(*UpstreamDB, "22", {}).moveInto(ID22), Succeeded()); + std::optional<ObjectID> ID2; + ASSERT_THAT_ERROR( + store(*UpstreamDB, "2", {*ID12, *ID21, *ID22}).moveInto(ID2), + Succeeded()); + std::optional<ObjectID> IDRoot; + ASSERT_THAT_ERROR(store(*UpstreamDB, "root", {*ID1, *ID2}).moveInto(IDRoot), + Succeeded()); + ArrayRef<uint8_t> Digest = UpstreamDB->getDigest(*IDRoot); + ASSERT_EQ(Digest.size(), RootHash.size()); + llvm::copy(Digest, RootHash.data()); + } + + unittest::TempDir Temp("ondiskcas", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> DB; + ASSERT_THAT_ERROR(OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType), + std::move(UpstreamDB), + OnDiskGraphDB::FaultInPolicy::FullTree) + .moveInto(DB), + Succeeded()); + + { + std::optional<ObjectID> IDRoot; + ASSERT_THAT_ERROR(DB->getReference(RootHash).moveInto(IDRoot), Succeeded()); + std::optional<ondisk::ObjectHandle> Obj; + ASSERT_THAT_ERROR(DB->load(*IDRoot).moveInto(Obj), Succeeded()); + ASSERT_TRUE(Obj.has_value()); + EXPECT_EQ(toStringRef(DB->getObjectData(*Obj)), "root"); + auto Refs = DB->getObjectRefs(*Obj); + ASSERT_EQ(std::distance(Refs.begin(), Refs.end()), 2); + } + + // Re-open the primary without chaining, to verify the data were copied from + // the upstream. + ASSERT_THAT_ERROR(OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType), + /*UpstreamDB=*/nullptr, + OnDiskGraphDB::FaultInPolicy::FullTree) + .moveInto(DB), + Succeeded()); + + std::optional<ObjectID> IDRoot; + ASSERT_THAT_ERROR(DB->getReference(RootHash).moveInto(IDRoot), Succeeded()); + std::string PrintedTree; + raw_string_ostream OS(PrintedTree); + ASSERT_THAT_ERROR(printTree(*DB, *IDRoot, OS), Succeeded()); + StringRef Expected = R"(root + 1 + 11 + 12 + 121 + 2 + 12 + 121 + 21 + 22 +)"; + EXPECT_EQ(PrintedTree, Expected); +} + +TEST_F(OnDiskCASTest, OnDiskGraphDBFaultInPolicyConflict) { + auto tryFaultInPolicyConflict = [](OnDiskGraphDB::FaultInPolicy Policy1, + OnDiskGraphDB::FaultInPolicy Policy2) { + unittest::TempDir TempUpstream("ondiskcas-upstream", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> UpstreamDB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(TempUpstream.path(), "blake3", sizeof(HashType)) + .moveInto(UpstreamDB), + Succeeded()); + + unittest::TempDir Temp("ondiskcas", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> DB; + ASSERT_THAT_ERROR(OnDiskGraphDB::open(Temp.path(), "blake3", + sizeof(HashType), + std::move(UpstreamDB), Policy1) + .moveInto(DB), + Succeeded()); + DB.reset(); + ASSERT_THAT_ERROR(OnDiskGraphDB::open(Temp.path(), "blake3", + sizeof(HashType), + std::move(UpstreamDB), Policy2) + .moveInto(DB), + Failed()); + }; + // Open as 'single', then as 'full'. + tryFaultInPolicyConflict(OnDiskGraphDB::FaultInPolicy::SingleNode, + OnDiskGraphDB::FaultInPolicy::FullTree); + // Open as 'full', then as 'single'. + tryFaultInPolicyConflict(OnDiskGraphDB::FaultInPolicy::FullTree, + OnDiskGraphDB::FaultInPolicy::SingleNode); +} + +#if defined(EXPENSIVE_CHECKS) +TEST_F(OnDiskCASTest, OnDiskGraphDBSpaceLimit) { + setMaxOnDiskCASMappingSize(); + unittest::TempDir Temp("ondiskcas", /*Unique=*/true); + std::unique_ptr<OnDiskGraphDB> DB; + ASSERT_THAT_ERROR( + OnDiskGraphDB::open(Temp.path(), "blake3", sizeof(HashType)).moveInto(DB), + Succeeded()); + + std::optional<ObjectID> ID; + std::string Data(500, '0'); + auto storeSmallObject = [&]() { + SmallVector<ObjectID, 1> Refs; + if (ID) + Refs.push_back(*ID); + ASSERT_THAT_ERROR(store(*DB, Data, Refs).moveInto(ID), Succeeded()); + }; + + // Insert enough small elements to overflow the data pool. + for (unsigned I = 0; I < 1024 * 256; ++I) + storeSmallObject(); + + EXPECT_GE(DB->getHardStorageLimitUtilization(), 99U); +} +#endif diff --git a/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp b/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp new file mode 100644 index 0000000..89c03b8 --- /dev/null +++ b/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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/CAS/OnDiskKeyValueDB.h" +#include "CASTestConfig.h" +#include "OnDiskCommonUtils.h" +#include "llvm/Testing/Support/Error.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::cas; +using namespace llvm::cas::ondisk; +using namespace llvm::unittest::cas; + +TEST_F(OnDiskCASTest, OnDiskKeyValueDBTest) { + unittest::TempDir Temp("ondiskkv", /*Unique=*/true); + std::unique_ptr<OnDiskKeyValueDB> DB; + ASSERT_THAT_ERROR(OnDiskKeyValueDB::open(Temp.path(), "blake3", + sizeof(HashType), "test", + sizeof(ValueType)) + .moveInto(DB), + Succeeded()); + { + std::optional<ArrayRef<char>> Val; + ASSERT_THAT_ERROR(DB->get(digest("hello")).moveInto(Val), Succeeded()); + EXPECT_FALSE(Val.has_value()); + } + + ValueType ValW = valueFromString("world"); + ArrayRef<char> Val; + ASSERT_THAT_ERROR(DB->put(digest("hello"), ValW).moveInto(Val), Succeeded()); + EXPECT_EQ(Val, ArrayRef(ValW)); + ASSERT_THAT_ERROR( + DB->put(digest("hello"), valueFromString("other")).moveInto(Val), + Succeeded()); + EXPECT_EQ(Val, ArrayRef(ValW)); + + { + std::optional<ArrayRef<char>> Val; + ASSERT_THAT_ERROR(DB->get(digest("hello")).moveInto(Val), Succeeded()); + EXPECT_TRUE(Val.has_value()); + EXPECT_EQ(*Val, ArrayRef(ValW)); + } + + // Validate + { + auto ValidateFunc = [](FileOffset Offset, ArrayRef<char> Data) -> Error { + EXPECT_EQ(Data.size(), sizeof(ValueType)); + return Error::success(); + }; + ASSERT_THAT_ERROR(DB->validate(ValidateFunc), Succeeded()); + } + + // Size + { + size_t InitSize = DB->getStorageSize(); + unsigned InitPrecent = DB->getHardStorageLimitUtilization(); + + // Insert a lot of entries. + for (unsigned I = 0; I < 1024 * 100; ++I) { + std::string Index = Twine(I).str(); + ArrayRef<char> Val; + ASSERT_THAT_ERROR( + DB->put(digest(Index), valueFromString(Index)).moveInto(Val), + Succeeded()); + } + + EXPECT_GT(DB->getStorageSize(), InitSize); + EXPECT_GT(DB->getHardStorageLimitUtilization(), InitPrecent); + } +} diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 37826b2..4d5bbe9 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -201,7 +201,6 @@ TEST_F(IRBuilderTest, IntrinsicsWithScalableVectors) { Args.clear(); Args.push_back(UndefValue::get(PtrToVecTy)); - Args.push_back(UndefValue::get(Builder.getInt32Ty())); Args.push_back(UndefValue::get(PredTy)); Args.push_back(UndefValue::get(VecTy)); |