Skip to content

Commit 8c58a0f

Browse files
[UnitTest] Add unit-test for LLVMCAS
1 parent dbb48a0 commit 8c58a0f

12 files changed

+1626
-19
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//===- ActionCacheTest.cpp ------------------------------------------------===//
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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/CAS/ActionCache.h"
10+
#include "CASTestConfig.h"
11+
#include "llvm/CAS/ObjectStore.h"
12+
#include "llvm/Support/FileSystem.h"
13+
#include "llvm/Testing/Support/Error.h"
14+
#include "llvm/Testing/Support/SupportHelpers.h"
15+
#include "gtest/gtest.h"
16+
17+
using namespace llvm;
18+
using namespace llvm::cas;
19+
20+
TEST_P(CASTest, ActionCacheHit) {
21+
std::shared_ptr<ObjectStore> CAS = createObjectStore();
22+
std::unique_ptr<ActionCache> Cache = createActionCache();
23+
24+
std::optional<ObjectProxy> ID;
25+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "1").moveInto(ID),
26+
Succeeded());
27+
std::optional<CASID> ResultID;
28+
ASSERT_THAT_ERROR(Cache->put(*ID, *ID), Succeeded());
29+
ASSERT_THAT_ERROR(Cache->get(*ID).moveInto(ResultID), Succeeded());
30+
ASSERT_TRUE(ResultID);
31+
std::optional<ObjectRef> Result = CAS->getReference(*ResultID);
32+
ASSERT_TRUE(Result);
33+
ASSERT_EQ(*ID, *Result);
34+
}
35+
36+
TEST_P(CASTest, ActionCacheMiss) {
37+
std::shared_ptr<ObjectStore> CAS = createObjectStore();
38+
std::unique_ptr<ActionCache> Cache = createActionCache();
39+
40+
std::optional<ObjectProxy> ID1, ID2;
41+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "1").moveInto(ID1),
42+
Succeeded());
43+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "2").moveInto(ID2),
44+
Succeeded());
45+
ASSERT_THAT_ERROR(Cache->put(*ID1, *ID2), Succeeded());
46+
// This is a cache miss for looking up a key doesn't exist.
47+
std::optional<CASID> Result1;
48+
ASSERT_THAT_ERROR(Cache->get(*ID2).moveInto(Result1), Succeeded());
49+
ASSERT_FALSE(Result1);
50+
51+
ASSERT_THAT_ERROR(Cache->put(*ID2, *ID1), Succeeded());
52+
// Cache hit after adding the value.
53+
std::optional<CASID> Result2;
54+
ASSERT_THAT_ERROR(Cache->get(*ID2).moveInto(Result2), Succeeded());
55+
ASSERT_TRUE(Result2);
56+
std::optional<ObjectRef> Ref = CAS->getReference(*Result2);
57+
ASSERT_TRUE(Ref);
58+
ASSERT_EQ(*ID1, *Ref);
59+
}
60+
61+
TEST_P(CASTest, ActionCacheRewrite) {
62+
std::shared_ptr<ObjectStore> CAS = createObjectStore();
63+
std::unique_ptr<ActionCache> Cache = createActionCache();
64+
65+
std::optional<ObjectProxy> ID1, ID2;
66+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "1").moveInto(ID1),
67+
Succeeded());
68+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "2").moveInto(ID2),
69+
Succeeded());
70+
ASSERT_THAT_ERROR(Cache->put(*ID1, *ID1), Succeeded());
71+
// Writing to the same key with different value is error.
72+
ASSERT_THAT_ERROR(Cache->put(*ID1, *ID2), Failed());
73+
// Writing the same value multiple times to the same key is fine.
74+
ASSERT_THAT_ERROR(Cache->put(*ID1, *ID1), Succeeded());
75+
}
76+
77+
#if LLVM_ENABLE_ONDISK_CAS
78+
TEST(OnDiskActionCache, ActionCacheResultInvalid) {
79+
unittest::TempDir Temp("on-disk-cache", /*Unique=*/true);
80+
std::unique_ptr<ObjectStore> CAS1 = createInMemoryCAS();
81+
std::unique_ptr<ObjectStore> CAS2 = createInMemoryCAS();
82+
83+
std::optional<ObjectProxy> ID1, ID2, ID3;
84+
ASSERT_THAT_ERROR(CAS1->createProxy(std::nullopt, "1").moveInto(ID1),
85+
Succeeded());
86+
ASSERT_THAT_ERROR(CAS1->createProxy(std::nullopt, "2").moveInto(ID2),
87+
Succeeded());
88+
ASSERT_THAT_ERROR(CAS2->createProxy(std::nullopt, "1").moveInto(ID3),
89+
Succeeded());
90+
91+
std::unique_ptr<ActionCache> Cache1 =
92+
cantFail(createOnDiskActionCache(Temp.path()));
93+
// Test put and get.
94+
ASSERT_THAT_ERROR(Cache1->put(*ID1, *ID2), Succeeded());
95+
std::optional<CASID> Result;
96+
ASSERT_THAT_ERROR(Cache1->get(*ID1).moveInto(Result), Succeeded());
97+
ASSERT_TRUE(Result);
98+
99+
// Create OnDiskCAS from the same location but a different underlying CAS.
100+
std::unique_ptr<ActionCache> Cache2 =
101+
cantFail(createOnDiskActionCache(Temp.path()));
102+
// Loading an key that points to an invalid object.
103+
std::optional<CASID> Result2;
104+
// Get will work but the resulting CASID doesn't exist in ObjectStore.
105+
ASSERT_THAT_ERROR(Cache2->get(*ID3).moveInto(Result2), Succeeded());
106+
ASSERT_FALSE(CAS2->getReference(*Result2));
107+
// Write a different value will cause error.
108+
ASSERT_THAT_ERROR(Cache2->put(*ID3, *ID3), Failed());
109+
}
110+
#endif
111+
112+
TEST_P(CASTest, ActionCacheAsync) {
113+
std::shared_ptr<ObjectStore> CAS = createObjectStore();
114+
std::unique_ptr<ActionCache> Cache = createActionCache();
115+
116+
{
117+
std::optional<ObjectProxy> ID;
118+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "1").moveInto(ID),
119+
Succeeded());
120+
auto PutFuture = Cache->putFuture(*ID, *ID);
121+
ASSERT_THAT_ERROR(PutFuture.get().take(), Succeeded());
122+
auto GetFuture = Cache->getFuture(*ID);
123+
std::optional<CASID> ResultID;
124+
ASSERT_THAT_ERROR(GetFuture.get().take().moveInto(ResultID), Succeeded());
125+
ASSERT_TRUE(ResultID);
126+
}
127+
128+
std::optional<ObjectProxy> ID2;
129+
ASSERT_THAT_ERROR(CAS->createProxy(std::nullopt, "2").moveInto(ID2),
130+
Succeeded());
131+
{
132+
std::promise<AsyncErrorValue> Promise;
133+
auto Future = Promise.get_future();
134+
Cache->putAsync(*ID2, *ID2, false,
135+
[Promise = std::move(Promise)](Error E) mutable {
136+
Promise.set_value(std::move(E));
137+
});
138+
ASSERT_THAT_ERROR(Future.get().take(), Succeeded());
139+
}
140+
{
141+
std::promise<AsyncCASIDValue> Promise;
142+
auto Future = Promise.get_future();
143+
Cache->getAsync(*ID2, false,
144+
[Promise = std::move(Promise)](
145+
Expected<std::optional<CASID>> Value) mutable {
146+
Promise.set_value(std::move(Value));
147+
});
148+
std::optional<CASID> ResultID;
149+
ASSERT_THAT_ERROR(Future.get().take().moveInto(ResultID), Succeeded());
150+
ASSERT_TRUE(ResultID);
151+
}
152+
}

llvm/unittests/CAS/CASTestConfig.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,45 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "CASTestConfig.h"
10+
#include "llvm/CAS/ActionCache.h"
1011
#include "llvm/CAS/ObjectStore.h"
1112
#include "gtest/gtest.h"
13+
#include <mutex>
1214

1315
using namespace llvm;
1416
using namespace llvm::cas;
1517

16-
CASTestingEnv createInMemory(int I) {
18+
TestingAndDir createInMemory(int I) {
1719
std::unique_ptr<ObjectStore> CAS = createInMemoryCAS();
18-
return CASTestingEnv{std::move(CAS)};
20+
std::unique_ptr<ActionCache> Cache = createInMemoryActionCache();
21+
return TestingAndDir{std::move(CAS), std::move(Cache), std::nullopt};
1922
}
2023

2124
INSTANTIATE_TEST_SUITE_P(InMemoryCAS, CASTest,
2225
::testing::Values(createInMemory));
26+
27+
#if LLVM_ENABLE_ONDISK_CAS
28+
__attribute__((constructor)) static void configureCASTestEnv() {
29+
// Restrict the size of the on-disk CAS for tests. This allows testing in
30+
// constrained environments (e.g. small TMPDIR). It also prevents leaving
31+
// behind large files on file systems that do not support sparse files if a
32+
// test crashes before resizing the file.
33+
static std::once_flag Flag;
34+
std::call_once(Flag, [] {
35+
size_t Limit = 100 * 1024 * 1024;
36+
std::string LimitStr = std::to_string(Limit);
37+
setenv("LLVM_CAS_MAX_MAPPING_SIZE", LimitStr.c_str(), /*overwrite=*/false);
38+
});
39+
}
40+
41+
TestingAndDir createOnDisk(int I) {
42+
unittest::TempDir Temp("on-disk-cas", /*Unique=*/true);
43+
std::unique_ptr<ObjectStore> CAS;
44+
EXPECT_THAT_ERROR(createOnDiskCAS(Temp.path()).moveInto(CAS), Succeeded());
45+
std::unique_ptr<ActionCache> Cache;
46+
EXPECT_THAT_ERROR(createOnDiskActionCache(Temp.path()).moveInto(Cache),
47+
Succeeded());
48+
return TestingAndDir{std::move(CAS), std::move(Cache), std::move(Temp)};
49+
}
50+
INSTANTIATE_TEST_SUITE_P(OnDiskCAS, CASTest, ::testing::Values(createOnDisk));
51+
#endif /* LLVM_ENABLE_ONDISK_CAS */

llvm/unittests/CAS/CASTestConfig.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,47 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#ifndef LLVM_UNITTESTS_CASTESTCONFIG_H
10+
#define LLVM_UNITTESTS_CASTESTCONFIG_H
11+
12+
#include "llvm/CAS/ActionCache.h"
913
#include "llvm/CAS/ObjectStore.h"
10-
#include "llvm/Config/llvm-config.h"
1114
#include "llvm/Support/FileSystem.h"
1215
#include "llvm/Testing/Support/Error.h"
1316
#include "llvm/Testing/Support/SupportHelpers.h"
1417
#include "gtest/gtest.h"
18+
#include <memory>
1519

16-
#ifndef LLVM_UNITTESTS_CASTESTCONFIG_H
17-
#define LLVM_UNITTESTS_CASTESTCONFIG_H
18-
19-
struct CASTestingEnv {
20-
std::unique_ptr<llvm::cas::ObjectStore> CAS;
20+
struct TestingAndDir {
21+
std::shared_ptr<llvm::cas::ObjectStore> CAS;
22+
std::unique_ptr<llvm::cas::ActionCache> Cache;
23+
std::optional<llvm::unittest::TempDir> Temp;
2124
};
2225

2326
class CASTest
24-
: public testing::TestWithParam<std::function<CASTestingEnv(int)>> {
27+
: public testing::TestWithParam<std::function<TestingAndDir(int)>> {
2528
protected:
2629
std::optional<int> NextCASIndex;
2730

28-
std::unique_ptr<llvm::cas::ObjectStore> createObjectStore() {
31+
llvm::SmallVector<llvm::unittest::TempDir> Dirs;
32+
33+
std::shared_ptr<llvm::cas::ObjectStore> createObjectStore() {
2934
auto TD = GetParam()(++(*NextCASIndex));
35+
if (TD.Temp)
36+
Dirs.push_back(std::move(*TD.Temp));
3037
return std::move(TD.CAS);
3138
}
39+
std::unique_ptr<llvm::cas::ActionCache> createActionCache() {
40+
auto TD = GetParam()(++(*NextCASIndex));
41+
if (TD.Temp)
42+
Dirs.push_back(std::move(*TD.Temp));
43+
return std::move(TD.Cache);
44+
}
3245
void SetUp() { NextCASIndex = 0; }
33-
void TearDown() { NextCASIndex = std::nullopt; }
46+
void TearDown() {
47+
NextCASIndex = std::nullopt;
48+
Dirs.clear();
49+
}
3450
};
3551

3652
#endif

llvm/unittests/CAS/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
1+
if (LLVM_ENABLE_ONDISK_CAS)
2+
add_definitions(-DLLVM_ENABLE_ONDISK_CAS=1)
3+
endif()
4+
15
set(LLVM_LINK_COMPONENTS
26
Support
37
CAS
48
TestingSupport
59
)
610

711
add_llvm_unittest(CASTests
12+
ActionCacheTest.cpp
813
CASTestConfig.cpp
14+
HierarchicalTreeBuilderTest.cpp
915
ObjectStoreTest.cpp
16+
OnDiskCommonUtils.h
17+
OnDiskGraphDBTest.cpp
18+
OnDiskHashMappedTrieTest.cpp
19+
OnDiskKeyValueDBTest.cpp
20+
TreeSchemaTest.cpp
21+
UnifiedOnDiskCacheTest.cpp
1022
)
1123

1224
target_link_libraries(CASTests PRIVATE LLVMTestingSupport)

0 commit comments

Comments
 (0)