2424
2525#include " cachelib/allocator/CacheAllocator.h"
2626#include " cachelib/interface/CacheComponent.h"
27+ #include " cachelib/interface/components/FlashCacheComponent.h"
2728#include " cachelib/interface/components/RAMCacheComponent.h"
2829#include " cachelib/interface/tests/Utils.h"
30+ #include " cachelib/navy/block_cache/tests/TestHelpers.h"
31+ #include " cachelib/navy/common/Device.h"
2932
3033using namespace ::testing;
3134using namespace facebook ::cachelib;
@@ -75,6 +78,38 @@ class RAMCacheFactory : public CacheFactory {
7578 }
7679};
7780
81+ class FlashCacheFactory : public CacheFactory {
82+ public:
83+ FlashCacheFactory ()
84+ : hits_(/* count */ kDeviceSize / kRegionSize , /* value */ 0 ) {}
85+
86+ std::unique_ptr<CacheComponent> create () override {
87+ device_ = navy::createMemoryDevice (kDeviceSize , /* encryptor */ nullptr );
88+ auto flashCache = ASSERT_OK (
89+ FlashCacheComponent::create (" CacheComponentTest" , makeConfig ()));
90+ return std::make_unique<FlashCacheComponent>(std::move (flashCache));
91+ }
92+
93+ private:
94+ using BlockCache = navy::BlockCache;
95+
96+ static constexpr uint64_t kRegionSize {/* 16KB */ 16 * 1024 };
97+ static constexpr uint64_t kDeviceSize {/* 256KB */ 256 * 1024 };
98+
99+ std::unique_ptr<navy::Device> device_;
100+ std::vector<uint32_t > hits_;
101+
102+ BlockCache::Config makeConfig () {
103+ BlockCache::Config config;
104+ config.regionSize = kRegionSize ;
105+ config.cacheSize = kDeviceSize ;
106+ config.device = device_.get ();
107+ config.evictionPolicy =
108+ std::make_unique<NiceMock<navy::MockPolicy>>(&hits_);
109+ return config;
110+ }
111+ };
112+
78113template <typename FactoryType>
79114class CacheComponentTest : public ::testing::Test {
80115 protected:
@@ -97,7 +132,7 @@ class CacheComponentTest : public ::testing::Test {
97132};
98133
99134// Define the list of factory types to test
100- using FactoryTypes = ::testing::Types<RAMCacheFactory>;
135+ using FactoryTypes = ::testing::Types<RAMCacheFactory, FlashCacheFactory >;
101136TYPED_TEST_SUITE (CacheComponentTest, FactoryTypes);
102137
103138// ============================================================================
@@ -231,13 +266,15 @@ CO_TYPED_TEST(CacheComponentTest, InsertOrReplaceExistingItem) {
231266 auto result2 =
232267 ASSERT_OK (co_await this ->cache_ ->insertOrReplace (std::move (handle2)));
233268
234- CO_ASSERT_TRUE (result2.has_value ());
235- auto & replacedHandle = result2.value ();
236- EXPECT_EQ (replacedHandle->getKey (), key);
269+ // Some implementations may not return the old data -- and that's ok!
270+ if (result2.has_value ()) {
271+ auto & replacedHandle = result2.value ();
272+ EXPECT_EQ (replacedHandle->getKey (), key);
237273
238- std::string replacedData (replacedHandle->template getMemoryAs <const char >(),
239- data1.size ());
240- EXPECT_EQ (replacedData, data1);
274+ std::string replacedData (replacedHandle->template getMemoryAs <const char >(),
275+ data1.size ());
276+ EXPECT_EQ (replacedData, data1);
277+ }
241278
242279 auto findResult = ASSERT_OK (co_await this ->cache_ ->find (key));
243280 CO_ASSERT_TRUE (findResult.has_value ());
@@ -252,13 +289,14 @@ CO_TYPED_TEST(CacheComponentTest, InsertOrReplaceMultipleTimes) {
252289 for (int i = 0 ; i < 5 ; ++i) {
253290 auto handle =
254291 ASSERT_OK (co_await this ->cache_ ->allocate (key, 100 , this ->now (), 3600 ));
292+ *handle->template getMemoryAs <uint32_t >() = i;
255293 auto result =
256294 ASSERT_OK (co_await this ->cache_ ->insertOrReplace (std::move (handle)));
257295
258296 if (i == 0 ) {
259297 EXPECT_FALSE (result.has_value ());
260- } else {
261- EXPECT_TRUE ( result.has_value () );
298+ } else if (result. has_value ()) {
299+ EXPECT_EQ (* result.value ()-> template getMemoryAs < uint32_t >(), i - 1 );
262300 }
263301 }
264302}
@@ -283,14 +321,15 @@ CO_TYPED_TEST(CacheComponentTest, InsertOrReplaceDifferentSizes) {
283321 auto result2 =
284322 ASSERT_OK (co_await this ->cache_ ->insertOrReplace (std::move (handle2)));
285323
286- CO_ASSERT_TRUE (result2.has_value ());
287- auto & replacedSmallHandle = result2.value ();
288- EXPECT_EQ (replacedSmallHandle->getKey (), key);
289- EXPECT_GE (replacedSmallHandle->getMemorySize (), smallData.size ());
290- std::string retrievedSmall (
291- replacedSmallHandle->template getMemoryAs <const char >(),
292- smallData.size ());
293- EXPECT_EQ (retrievedSmall, smallData);
324+ if (result2.has_value ()) {
325+ auto & replacedSmallHandle = result2.value ();
326+ EXPECT_EQ (replacedSmallHandle->getKey (), key);
327+ EXPECT_GE (replacedSmallHandle->getMemorySize (), smallData.size ());
328+ std::string retrievedSmall (
329+ replacedSmallHandle->template getMemoryAs <const char >(),
330+ smallData.size ());
331+ EXPECT_EQ (retrievedSmall, smallData);
332+ }
294333
295334 // Verify large data is now in cache
296335 auto findResult1 = ASSERT_OK (co_await this ->cache_ ->find (key));
@@ -308,14 +347,15 @@ CO_TYPED_TEST(CacheComponentTest, InsertOrReplaceDifferentSizes) {
308347 auto result3 =
309348 ASSERT_OK (co_await this ->cache_ ->insertOrReplace (std::move (handle3)));
310349
311- CO_ASSERT_TRUE (result3.has_value ());
312- auto & replacedLargeHandle = result3.value ();
313- EXPECT_EQ (replacedLargeHandle->getKey (), key);
314- EXPECT_GE (replacedLargeHandle->getMemorySize (), largeData.size ());
315- std::string retrievedLarge2 (
316- replacedLargeHandle->template getMemoryAs <const char >(),
317- largeData.size ());
318- EXPECT_EQ (retrievedLarge2, largeData);
350+ if (result3.has_value ()) {
351+ auto & replacedLargeHandle = result3.value ();
352+ EXPECT_EQ (replacedLargeHandle->getKey (), key);
353+ EXPECT_GE (replacedLargeHandle->getMemorySize (), largeData.size ());
354+ std::string retrievedLarge2 (
355+ replacedLargeHandle->template getMemoryAs <const char >(),
356+ largeData.size ());
357+ EXPECT_EQ (retrievedLarge2, largeData);
358+ }
319359
320360 // Verify small data is now in cache
321361 auto findResult2 = ASSERT_OK (co_await this ->cache_ ->find (key));
0 commit comments