@@ -1837,6 +1837,118 @@ class ObjectCacheTest : public ::testing::Test {
18371837 ts[i].join ();
18381838 }
18391839 }
1840+
1841+ std::unique_ptr<ObjectCache> makeFooCache () {
1842+ ObjectCacheConfig config;
1843+ config.setCacheName (" test" ).setCacheCapacity (10'000 );
1844+ config.setItemDestructor (
1845+ [&](ObjectCacheDestructorData data) { data.deleteObject <Foo>(); });
1846+ return ObjectCache::create (config);
1847+ }
1848+
1849+ std::map<std::string, Foo> populateFooCache (ObjectCache& objcache, int n) {
1850+ std::map<std::string, Foo> expected;
1851+ for (int i = 0 ; i < n; i++) {
1852+ auto key = folly::sformat (" Foo_{}" , i);
1853+ auto foo = std::make_unique<Foo>();
1854+ foo->a = i;
1855+ foo->b = i * 2 ;
1856+ foo->c = i * 3 ;
1857+ expected[key] = *foo;
1858+ auto [allocRes, _, __] = objcache.insertOrReplace (key, std::move (foo));
1859+ EXPECT_EQ (ObjectCache::AllocStatus::kSuccess , allocRes);
1860+ }
1861+ return expected;
1862+ }
1863+
1864+ template <typename Iter>
1865+ void verifyVisitsAllFoos (Iter begin,
1866+ const Iter& end,
1867+ const std::map<std::string, Foo>& expected) {
1868+ std::map<std::string, Foo> visited;
1869+ for (auto it = std::move (begin); it != end; ++it) {
1870+ ASSERT_TRUE (static_cast <bool >(it));
1871+ visited[it.getKey ().str ()] = *it.template getObjectPtrAs <Foo>();
1872+ }
1873+ EXPECT_EQ (expected.size (), visited.size ());
1874+ for (const auto & [k, v] : expected) {
1875+ auto vIt = visited.find (k);
1876+ ASSERT_NE (visited.end (), vIt);
1877+ EXPECT_EQ (v.a , vIt->second .a );
1878+ EXPECT_EQ (v.b , vIt->second .b );
1879+ EXPECT_EQ (v.c , vIt->second .c );
1880+ }
1881+ }
1882+
1883+ void testAccessIteratorVisitsAll () {
1884+ auto objcache = makeFooCache ();
1885+ auto expected = populateFooCache (*objcache, 50 );
1886+ verifyVisitsAllFoos (objcache->begin (), objcache->end (), expected);
1887+ }
1888+
1889+ void testAccessIteratorEmpty () {
1890+ auto objcache = makeFooCache ();
1891+ EXPECT_EQ (objcache->begin (), objcache->end ());
1892+ }
1893+
1894+ void testLockGroupAccessIteratorVisitsAll () {
1895+ auto objcache = makeFooCache ();
1896+ auto expected = populateFooCache (*objcache, 50 );
1897+ verifyVisitsAllFoos (objcache->beginLockGroup (), objcache->endLockGroup (),
1898+ expected);
1899+ }
1900+
1901+ void testLockGroupAccessIteratorEmpty () {
1902+ auto objcache = makeFooCache ();
1903+ EXPECT_EQ (objcache->beginLockGroup (), objcache->endLockGroup ());
1904+ }
1905+
1906+ void testLockGroupAccessIteratorFilter () {
1907+ auto objcache = makeFooCache ();
1908+ populateFooCache (*objcache, 50 );
1909+
1910+ auto filter = [](folly::StringPiece key) {
1911+ return key == " Foo_0" || key == " Foo_1" || key == " Foo_2" ;
1912+ };
1913+ std::set<std::string> filteredVisited;
1914+ for (auto it = objcache->beginLockGroup (filter);
1915+ it != objcache->endLockGroup ();
1916+ ++it) {
1917+ filteredVisited.insert (it.getKey ().str ());
1918+ }
1919+ const std::set<std::string> filteredExpected{" Foo_0" , " Foo_1" , " Foo_2" };
1920+ EXPECT_EQ (filteredExpected, filteredVisited);
1921+ }
1922+
1923+ void testLockGroupAccessIteratorPrefixScan () {
1924+ auto objcache = makeFooCache ();
1925+ std::set<std::string> expectedAlpha;
1926+ std::set<std::string> expectedBeta;
1927+ for (int i = 0 ; i < 500 ; i++) {
1928+ auto alpha = folly::sformat (" alpha_{}" , i);
1929+ auto beta = folly::sformat (" beta_{}" , i);
1930+ expectedAlpha.insert (alpha);
1931+ expectedBeta.insert (beta);
1932+ auto [r1, _1, __1] =
1933+ objcache->insertOrReplace (alpha, std::make_unique<Foo>());
1934+ auto [r2, _2, __2] =
1935+ objcache->insertOrReplace (beta, std::make_unique<Foo>());
1936+ ASSERT_EQ (ObjectCache::AllocStatus::kSuccess , r1);
1937+ ASSERT_EQ (ObjectCache::AllocStatus::kSuccess , r2);
1938+ }
1939+
1940+ auto prefixFilter =
1941+ [prefix = folly::StringPiece{" alpha_" }](folly::StringPiece key) {
1942+ return key.startsWith (prefix);
1943+ };
1944+ std::set<std::string> visited;
1945+ for (auto it = objcache->beginLockGroup (prefixFilter);
1946+ it != objcache->endLockGroup ();
1947+ ++it) {
1948+ visited.insert (it.getKey ().str ());
1949+ }
1950+ EXPECT_EQ (expectedAlpha, visited);
1951+ }
18401952};
18411953
18421954using AllocatorTypes = ::testing::Types<LruAllocator,
@@ -1853,6 +1965,24 @@ TYPED_TEST(ObjectCacheTest, SetEvictionPolicyConfig) {
18531965 }
18541966}
18551967TYPED_TEST (ObjectCacheTest, Simple) { this ->testSimple (); }
1968+ TYPED_TEST (ObjectCacheTest, AccessIteratorVisitsAll) {
1969+ this ->testAccessIteratorVisitsAll ();
1970+ }
1971+ TYPED_TEST (ObjectCacheTest, AccessIteratorEmpty) {
1972+ this ->testAccessIteratorEmpty ();
1973+ }
1974+ TYPED_TEST (ObjectCacheTest, LockGroupAccessIteratorVisitsAll) {
1975+ this ->testLockGroupAccessIteratorVisitsAll ();
1976+ }
1977+ TYPED_TEST (ObjectCacheTest, LockGroupAccessIteratorEmpty) {
1978+ this ->testLockGroupAccessIteratorEmpty ();
1979+ }
1980+ TYPED_TEST (ObjectCacheTest, LockGroupAccessIteratorFilter) {
1981+ this ->testLockGroupAccessIteratorFilter ();
1982+ }
1983+ TYPED_TEST (ObjectCacheTest, LockGroupAccessIteratorPrefixScan) {
1984+ this ->testLockGroupAccessIteratorPrefixScan ();
1985+ }
18561986TYPED_TEST (ObjectCacheTest, MultiType) { this ->testMultiType (); }
18571987TYPED_TEST (ObjectCacheTest, testMultiTypePolymorphism) {
18581988 this ->testMultiTypePolymorphism ();
0 commit comments