mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-24 18:39:59 +00:00
Add unit tests for GenericObjectCache
This commit is contained in:
parent
225946b92b
commit
71e33cf8b2
@ -94,6 +94,8 @@ file(GLOB UNITTEST_SRC_FILES
|
|||||||
nifosg/testnifloader.cpp
|
nifosg/testnifloader.cpp
|
||||||
|
|
||||||
esmterrain/testgridsampling.cpp
|
esmterrain/testgridsampling.cpp
|
||||||
|
|
||||||
|
resource/testobjectcache.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
|
source_group(apps\\openmw_test_suite FILES openmw_test_suite.cpp ${UNITTEST_SRC_FILES})
|
||||||
|
308
apps/openmw_test_suite/resource/testobjectcache.cpp
Normal file
308
apps/openmw_test_suite/resource/testobjectcache.cpp
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
#include <components/resource/objectcache.hpp>
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <osg/Object>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace ::testing;
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getRefFromObjectCacheShouldReturnNullptrByDefault)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCache(42), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getRefFromObjectCacheOrNoneShouldReturnNulloptByDefault)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(42), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Object : osg::Object
|
||||||
|
{
|
||||||
|
Object() = default;
|
||||||
|
|
||||||
|
Object(const Object& other, const osg::CopyOp& copyOp = osg::CopyOp())
|
||||||
|
: osg::Object(other, copyOp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
META_Object(ResourceTest, Object)
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, shouldStoreValues)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCache(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, shouldStoreNullptrValues)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
const int key = 42;
|
||||||
|
cache->addEntryToObjectCache(key, nullptr);
|
||||||
|
EXPECT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, updateShouldExtendLifetimeForItemsWithZeroTimestamp)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value, 0);
|
||||||
|
value = nullptr;
|
||||||
|
|
||||||
|
const double referenceTime = 1000;
|
||||||
|
const double expiryDelay = 1;
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
EXPECT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, addEntryToObjectCacheShouldReplaceExistingItemByKey)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value1);
|
||||||
|
ASSERT_EQ(cache->getRefFromObjectCache(key), value1);
|
||||||
|
cache->addEntryToObjectCache(key, value2);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCache(key), value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, addEntryToObjectCacheShouldMarkLifetime)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 2;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
cache->addEntryToObjectCache(key, nullptr, referenceTime + expiryDelay);
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + 2 * expiryDelay);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime + expiryDelay);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, updateShouldRemoveExpiredItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 1;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value);
|
||||||
|
value = nullptr;
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, updateShouldKeepExternallyReferencedItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 1;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value);
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime);
|
||||||
|
EXPECT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, updateShouldKeepNotExpiredItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 2;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value);
|
||||||
|
value = nullptr;
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay / 2);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay / 2);
|
||||||
|
EXPECT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, updateShouldKeepNotExpiredNullptrItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 2;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
cache->addEntryToObjectCache(key, nullptr);
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay / 2);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay / 2);
|
||||||
|
EXPECT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getRefFromObjectCacheOrNoneShouldNotExtendItemLifetime)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const double referenceTime = 1;
|
||||||
|
const double expiryDelay = 2;
|
||||||
|
|
||||||
|
const int key = 42;
|
||||||
|
cache->addEntryToObjectCache(key, nullptr);
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay / 2);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime - expiryDelay / 2);
|
||||||
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
|
||||||
|
cache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime + expiryDelay);
|
||||||
|
cache->removeExpiredObjectsInCache(referenceTime);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldSupportHeterogeneousLookup)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<std::string>> cache(new GenericObjectCache<std::string>);
|
||||||
|
cache->addEntryToObjectCache("a", nullptr);
|
||||||
|
cache->addEntryToObjectCache("c", nullptr);
|
||||||
|
EXPECT_THAT(cache->lowerBound(std::string_view("b")), Optional(Pair("c", _)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, shouldSupportRemovingItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
const int key = 42;
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(key, value);
|
||||||
|
ASSERT_EQ(cache->getRefFromObjectCache(key), value);
|
||||||
|
cache->removeFromObjectCache(key);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, clearShouldRemoveAllItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
const int key1 = 42;
|
||||||
|
const int key2 = 13;
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
cache->addEntryToObjectCache(key1, value1);
|
||||||
|
cache->addEntryToObjectCache(key2, value2);
|
||||||
|
|
||||||
|
ASSERT_EQ(cache->getRefFromObjectCache(key1), value1);
|
||||||
|
ASSERT_EQ(cache->getRefFromObjectCache(key2), value2);
|
||||||
|
|
||||||
|
cache->clear();
|
||||||
|
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key1), std::nullopt);
|
||||||
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key2), std::nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, callShouldIterateOverAllItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
osg::ref_ptr<Object> value3(new Object);
|
||||||
|
cache->addEntryToObjectCache(1, value1);
|
||||||
|
cache->addEntryToObjectCache(2, value2);
|
||||||
|
cache->addEntryToObjectCache(3, value3);
|
||||||
|
|
||||||
|
std::vector<std::pair<int, osg::Object*>> actual;
|
||||||
|
cache->call([&](int key, osg::Object* value) { actual.emplace_back(key, value); });
|
||||||
|
|
||||||
|
EXPECT_THAT(actual, ElementsAre(Pair(1, value1.get()), Pair(2, value2.get()), Pair(3, value3.get())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getCacheSizeShouldReturnNumberOrAddedItems)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
cache->addEntryToObjectCache(13, value1);
|
||||||
|
cache->addEntryToObjectCache(42, value2);
|
||||||
|
|
||||||
|
EXPECT_EQ(cache->getCacheSize(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnFirstNotLessThatGivenKey)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
osg::ref_ptr<Object> value3(new Object);
|
||||||
|
cache->addEntryToObjectCache(1, value1);
|
||||||
|
cache->addEntryToObjectCache(2, value2);
|
||||||
|
cache->addEntryToObjectCache(4, value3);
|
||||||
|
|
||||||
|
EXPECT_THAT(cache->lowerBound(3), Optional(Pair(4, value3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnNulloptWhenKeyIsGreaterThanAnyOther)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value1(new Object);
|
||||||
|
osg::ref_ptr<Object> value2(new Object);
|
||||||
|
osg::ref_ptr<Object> value3(new Object);
|
||||||
|
cache->addEntryToObjectCache(1, value1);
|
||||||
|
cache->addEntryToObjectCache(2, value2);
|
||||||
|
cache->addEntryToObjectCache(3, value3);
|
||||||
|
|
||||||
|
EXPECT_EQ(cache->lowerBound(4), std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -180,7 +180,7 @@ namespace Resource
|
|||||||
|
|
||||||
/** call operator()(KeyType, osg::Object*) for each object in the cache. */
|
/** call operator()(KeyType, osg::Object*) for each object in the cache. */
|
||||||
template <class Functor>
|
template <class Functor>
|
||||||
void call(Functor& f)
|
void call(Functor&& f)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||||
for (typename ObjectCacheMap::iterator it = _objectCache.begin(); it != _objectCache.end(); ++it)
|
for (typename ObjectCacheMap::iterator it = _objectCache.begin(); it != _objectCache.end(); ++it)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user