@ -3,24 +3,131 @@
# include <components/detournavigator/navmeshtilescache.hpp>
# include <components/detournavigator/navmeshtilescache.hpp>
# include <components/detournavigator/exceptions.hpp>
# include <components/detournavigator/exceptions.hpp>
# include <components/detournavigator/recastmesh.hpp>
# include <components/detournavigator/recastmesh.hpp>
# include <components/detournavigator/preparednavmeshdata.hpp>
# include <components/detournavigator/ref.hpp>
# include <components/detournavigator/preparednavmeshdatatuple.hpp>
# include <RecastAlloc.h>
# include <LinearMath/btTransform.h>
# include <LinearMath/btTransform.h>
# include <gtest/gtest.h>
# include <gtest/gtest.h>
namespace DetourNavigator
# include <random>
{
# include <stdexcept>
static inline bool operator = = ( const NavMeshDataRef & lhs , const NavMeshDataRef & rhs )
{
return std : : make_pair ( lhs . mValue , lhs . mSize ) = = std : : make_pair ( rhs . mValue , rhs . mSize ) ;
}
}
namespace
namespace
{
{
using namespace testing ;
using namespace testing ;
using namespace DetourNavigator ;
using namespace DetourNavigator ;
void * permRecastAlloc ( int size )
{
void * result = rcAlloc ( static_cast < std : : size_t > ( size ) , RC_ALLOC_PERM ) ;
if ( result = = nullptr )
throw std : : bad_alloc ( ) ;
return result ;
}
template < class T >
void generate ( T * & values , int size )
{
values = static_cast < T * > ( permRecastAlloc ( size * sizeof ( T ) ) ) ;
std : : generate_n ( values , static_cast < std : : size_t > ( size ) , [ ] { return static_cast < T > ( std : : rand ( ) ) ; } ) ;
}
void generate ( rcPolyMesh & value , int size )
{
value . nverts = size ;
value . maxpolys = size ;
value . nvp = size ;
value . npolys = size ;
rcVcopy ( value . bmin , osg : : Vec3f ( - 1 , - 2 , - 3 ) . ptr ( ) ) ;
rcVcopy ( value . bmax , osg : : Vec3f ( 3 , 2 , 1 ) . ptr ( ) ) ;
value . cs = 1.0f / ( std : : rand ( ) % 999 + 1 ) ;
value . ch = 1.0f / ( std : : rand ( ) % 999 + 1 ) ;
value . borderSize = std : : rand ( ) ;
value . maxEdgeError = 1.0f / ( std : : rand ( ) % 999 + 1 ) ;
generate ( value . verts , 3 * value . nverts ) ;
generate ( value . polys , value . maxpolys * 2 * value . nvp ) ;
generate ( value . regs , value . maxpolys ) ;
generate ( value . flags , value . maxpolys ) ;
generate ( value . areas , value . maxpolys ) ;
}
void generate ( rcPolyMeshDetail & value , int size )
{
value . nmeshes = size ;
value . nverts = size ;
value . ntris = size ;
generate ( value . meshes , 4 * value . nmeshes ) ;
generate ( value . verts , 3 * value . nverts ) ;
generate ( value . tris , 4 * value . ntris ) ;
}
void generate ( PreparedNavMeshData & value , int size )
{
value . mUserId = std : : rand ( ) ;
value . mCellHeight = 1.0f / ( std : : rand ( ) % 999 + 1 ) ;
value . mCellSize = 1.0f / ( std : : rand ( ) % 999 + 1 ) ;
generate ( value . mPolyMesh , size ) ;
generate ( value . mPolyMeshDetail , size ) ;
}
std : : unique_ptr < PreparedNavMeshData > makePeparedNavMeshData ( int size )
{
auto result = std : : make_unique < PreparedNavMeshData > ( ) ;
generate ( * result , size ) ;
return result ;
}
template < class T >
void clone ( const T * src , T * & dst , int size )
{
dst = static_cast < T * > ( permRecastAlloc ( size * sizeof ( T ) ) ) ;
std : : memcpy ( dst , src , static_cast < std : : size_t > ( size ) * sizeof ( T ) ) ;
}
void clone ( const rcPolyMesh & src , rcPolyMesh & dst )
{
dst . nverts = src . nverts ;
dst . npolys = src . npolys ;
dst . maxpolys = src . maxpolys ;
dst . nvp = src . nvp ;
rcVcopy ( dst . bmin , src . bmin ) ;
rcVcopy ( dst . bmax , src . bmax ) ;
dst . cs = src . cs ;
dst . ch = src . ch ;
dst . borderSize = src . borderSize ;
dst . maxEdgeError = src . maxEdgeError ;
clone ( src . verts , dst . verts , 3 * dst . nverts ) ;
clone ( src . polys , dst . polys , dst . maxpolys * 2 * dst . nvp ) ;
clone ( src . regs , dst . regs , dst . maxpolys ) ;
clone ( src . flags , dst . flags , dst . maxpolys ) ;
clone ( src . areas , dst . areas , dst . maxpolys ) ;
}
void clone ( const rcPolyMeshDetail & src , rcPolyMeshDetail & dst )
{
dst . nmeshes = src . nmeshes ;
dst . nverts = src . nverts ;
dst . ntris = src . ntris ;
clone ( src . meshes , dst . meshes , 4 * dst . nmeshes ) ;
clone ( src . verts , dst . verts , 3 * dst . nverts ) ;
clone ( src . tris , dst . tris , 4 * dst . ntris ) ;
}
std : : unique_ptr < PreparedNavMeshData > clone ( const PreparedNavMeshData & value )
{
auto result = std : : make_unique < PreparedNavMeshData > ( ) ;
result - > mUserId = value . mUserId ;
result - > mCellHeight = value . mCellHeight ;
result - > mCellSize = value . mCellSize ;
clone ( value . mPolyMesh , result - > mPolyMesh ) ;
clone ( value . mPolyMeshDetail , result - > mPolyMeshDetail ) ;
return result ;
}
struct DetourNavigatorNavMeshTilesCacheTest : Test
struct DetourNavigatorNavMeshTilesCacheTest : Test
{
{
const osg : : Vec3f mAgentHalfExtents { 1 , 2 , 3 } ;
const osg : : Vec3f mAgentHalfExtents { 1 , 2 , 3 } ;
@ -32,17 +139,11 @@ namespace
const std : : vector < AreaType > mAreaTypes { 1 , AreaType_ground } ;
const std : : vector < AreaType > mAreaTypes { 1 , AreaType_ground } ;
const std : : vector < RecastMesh : : Water > mWater { } ;
const std : : vector < RecastMesh : : Water > mWater { } ;
const RecastMesh mRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , mWater } ;
const RecastMesh mRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , mWater } ;
const std : : vector < OffMeshConnection > mOffMeshConnections { } ;
std : : unique_ptr < PreparedNavMeshData > mPreparedNavMeshData { makePeparedNavMeshData ( 3 ) } ;
unsigned char * const mData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
NavMeshData mNavMeshData { mData , 1 } ;
const size_t cRecastMeshKeySize = mRecastMesh . getIndices ( ) . size ( ) * sizeof ( int )
+ mRecastMesh . getVertices ( ) . size ( ) * sizeof ( float )
+ mRecastMesh . getAreaTypes ( ) . size ( ) * sizeof ( AreaType )
+ mRecastMesh . getWater ( ) . size ( ) * sizeof ( RecastMesh : : Water )
+ mOffMeshConnections . size ( ) * sizeof ( OffMeshConnection ) ;
const size_t cRecastMeshWithWaterKeySize = cRecastMeshKeySize + sizeof ( RecastMesh : : Water ) ;
const std : : size_t mRecastMeshSize = sizeof ( mRecastMesh ) + getSize ( mRecastMesh ) ;
const std : : size_t mRecastMeshWithWaterSize = mRecastMeshSize + sizeof ( RecastMesh : : Water ) ;
const std : : size_t mPreparedNavMeshDataSize = sizeof ( * mPreparedNavMeshData ) + getSize ( * mPreparedNavMeshData ) ;
} ;
} ;
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_empty_cache_should_return_empty_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_empty_cache_should_return_empty_value )
@ -50,7 +151,7 @@ namespace
const std : : size_t maxSize = 0 ;
const std : : size_t maxSize = 0 ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_for_not_enought_cache_size_should_return_empty_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_for_not_enought_cache_size_should_return_empty_value )
@ -58,51 +159,46 @@ namespace
const std : : size_t maxSize = 0 ;
const std : : size_t maxSize = 0 ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std : : move ( mPreparedNavMeshData ) ) ) ;
std : : move ( mNavMeshData ) ) ) ;
EXPECT_NE ( mPreparedNavMeshData , nullptr ) ;
EXPECT_NE ( mNavMeshData . mValue , nullptr ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_return_cached_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_return_cached_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const auto copy = clone ( * mPreparedNavMeshData ) ;
ASSERT_EQ ( * mPreparedNavMeshData , * copy ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std : : move ( mPreparedNavMeshData ) ) ;
std : : move ( mNavMeshData ) ) ;
ASSERT_TRUE ( result ) ;
ASSERT_TRUE ( result ) ;
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { mData , 1 } ) ) ;
EXPECT_EQ ( result . get ( ) , * copy ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_existing_element_should_return_cached_element )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_existing_element_should_return_cached_element )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = 2 * ( mRecastMeshSize + mPreparedNavMeshDataSize ) ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = 2 * ( navMeshDataSize + navMeshKeySize ) ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto copy = clone ( * mPreparedNavMeshData ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
const auto sameCopy = clone ( * mPreparedNavMeshData ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
EXPECT_EQ ( m NavMeshData. mValue , nullptr ) ;
EXPECT_EQ ( m Prepared NavMeshData, nullptr ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( anotherNavMeshData ) ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( copy ) ) ;
ASSERT_TRUE ( result ) ;
ASSERT_TRUE ( result ) ;
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { mData , 1 } ) ) ;
EXPECT_EQ ( result . get ( ) , * sameCopy ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_should_return_cached_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_should_return_cached_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const auto copy = clone ( * mPreparedNavMeshData ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
const auto result = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections );
const auto result = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh );
ASSERT_TRUE ( result ) ;
ASSERT_TRUE ( result ) ;
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { mData , 1 } ) ) ;
EXPECT_EQ ( result . get ( ) , * copy ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_agent_half_extents_should_return_empty_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_agent_half_extents_should_return_empty_value )
@ -111,8 +207,8 @@ namespace
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const osg : : Vec3f unexsistentAgentHalfExtents { 1 , 1 , 1 } ;
const osg : : Vec3f unexsistentAgentHalfExtents { 1 , 1 , 1 } ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
EXPECT_FALSE ( cache . get ( unexsistentAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( unexsistentAgentHalfExtents , mTilePosition , mRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_tile_position_should_return_empty_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_tile_position_should_return_empty_value )
@ -121,8 +217,8 @@ namespace
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const TilePosition unexistentTilePosition { 1 , 1 } ;
const TilePosition unexistentTilePosition { 1 , 1 } ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , unexistentTilePosition , mRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , unexistentTilePosition , mRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_recast_mesh_should_return_empty_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , get_for_cache_miss_by_recast_mesh_should_return_empty_value )
@ -132,217 +228,189 @@ namespace
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh unexistentRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const RecastMesh unexistentRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , unexistentRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , unexistentRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshWithWaterKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto anotherPreparedNavMeshData = makePeparedNavMeshData ( 3 ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
const auto copy = clone ( * anotherPreparedNavMeshData ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections ,
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh ,
std : : move ( another NavMeshData) ) ;
std : : move ( another Prepared NavMeshData) ) ;
ASSERT_TRUE ( result ) ;
ASSERT_TRUE ( result ) ;
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { anotherData , 1 } ) ) ;
EXPECT_EQ ( result . get ( ) , * copy ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_used_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_used_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto anotherPreparedNavMeshData = makePeparedNavMeshData ( 3 ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
const auto value = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
const auto value = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh ,
std : : move ( m NavMeshData) ) ;
std : : move ( m Prepared NavMeshData) ) ;
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh ,
std : : move ( another NavMeshData) ) ) ;
std : : move ( another Prepared NavMeshData) ) ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_least_recently_set_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_least_recently_set_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = 2 * ( mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ) ;
const std : : size_t navMeshKeySize = cRecastMeshWithWaterKeySize ;
const std : : size_t maxSize = 2 * ( navMeshDataSize + navMeshKeySize ) ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const auto copy = clone ( * mPreparedNavMeshData ) ;
const std : : vector < RecastMesh : : Water > leastRecentlySetWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > leastRecentlySetWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh leastRecentlySetRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh leastRecentlySetRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , leastRecentlySetWater } ;
mAreaTypes , leastRecentlySetWater } ;
const auto leastRecentlySetData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto leastRecentlySetData = makePeparedNavMeshData ( 3 ) ;
NavMeshData leastRecentlySetNavMeshData { leastRecentlySetData , 1 } ;
const std : : vector < RecastMesh : : Water > mostRecentlySetWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > mostRecentlySetWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const RecastMesh mostRecentlySetRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh mostRecentlySetRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , mostRecentlySetWater } ;
mAreaTypes , mostRecentlySetWater } ;
const auto mostRecentlySetData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto mostRecentlySetData = makePeparedNavMeshData ( 3 ) ;
NavMeshData mostRecentlySetNavMeshData { mostRecentlySetData , 1 } ;
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , leastRecentlySetRecastMesh , mOffMeshConnections ,
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , leastRecentlySetRecastMesh ,
std : : move ( leastRecentlySet NavMesh Data) ) ) ;
std : : move ( leastRecentlySet Data) ) ) ;
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , mostRecentlySetRecastMesh , mOffMeshConnections ,
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , mostRecentlySetRecastMesh ,
std : : move ( mostRecentlySet NavMesh Data) ) ) ;
std : : move ( mostRecentlySet Data) ) ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh ,
std : : move ( m NavMeshData) ) ;
std : : move ( m Prepared NavMeshData) ) ;
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { mData , 1 } ) ) ;
EXPECT_EQ ( result . get ( ) , * copy ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlySetRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlySetRecastMesh )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlySetRecastMesh , mOffMeshConnections )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlySetRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_least_recently_used_value )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_replace_unused_least_recently_used_value )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = 2 * ( mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ) ;
const std : : size_t navMeshKeySize = cRecastMeshWithWaterKeySize ;
const std : : size_t maxSize = 2 * ( navMeshDataSize + navMeshKeySize ) ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > leastRecentlyUsedWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > leastRecentlyUsedWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh leastRecentlyUsedRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh leastRecentlyUsedRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , leastRecentlyUsedWater } ;
mAreaTypes , leastRecentlyUsedWater } ;
const auto leastRecentlyUsedData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto leastRecentlyUsedData = makePeparedNavMeshData ( 3 ) ;
NavMeshData leastRecentlyUsedNavMeshData { leastRecentlyUsedData , 1 } ;
const auto leastRecentlyUsedCopy = clone ( * leastRecentlyUsedData ) ;
const std : : vector < RecastMesh : : Water > mostRecentlyUsedWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > mostRecentlyUsedWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const RecastMesh mostRecentlyUsedRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh mostRecentlyUsedRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , mostRecentlyUsedWater } ;
mAreaTypes , mostRecentlyUsedWater } ;
const auto mostRecentlyUsedData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto mostRecentlyUsedData = makePeparedNavMeshData ( 3 ) ;
NavMeshData mostRecentlyUsedNavMeshData { mostRecentlyUsedData , 1 } ;
const auto mostRecentlyUsedCopy = clone ( * mostRecentlyUsedData ) ;
cache . set ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh , mOffMeshConnections ,
cache . set ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh , std : : move ( leastRecentlyUsedData ) ) ;
std : : move ( leastRecentlyUsedNavMeshData ) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh , std : : move ( mostRecentlyUsedData ) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh , mOffMeshConnections ,
std : : move ( mostRecentlyUsedNavMeshData ) ) ;
{
{
const auto value = cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh , mOffMeshConnections );
const auto value = cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh );
ASSERT_TRUE ( value ) ;
ASSERT_TRUE ( value ) ;
ASSERT_EQ ( value . get ( ) , ( NavMeshDataRef { leastRecentlyUsedData , 1 } ) ) ;
ASSERT_EQ ( value . get ( ) , * leastRecentlyUsedCopy ) ;
}
}
{
{
const auto value = cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh , mOffMeshConnections );
const auto value = cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh );
ASSERT_TRUE ( value ) ;
ASSERT_TRUE ( value ) ;
ASSERT_EQ ( value . get ( ) , ( NavMeshDataRef { mostRecentlyUsedData , 1 } ) ) ;
ASSERT_EQ ( value . get ( ) , * mostRecentlyUsedCopy ) ;
}
}
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
const auto copy = clone ( * mPreparedNavMeshData ) ;
std : : move ( mNavMeshData ) ) ;
const auto result = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh ,
EXPECT_EQ ( result . get ( ) , ( NavMeshDataRef { mData , 1 } ) ) ;
std : : move ( mPreparedNavMeshData ) ) ;
EXPECT_EQ ( result . get ( ) , * copy ) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh , mOffMeshConnections )) ;
EXPECT_FALSE ( cache . get ( mAgentHalfExtents , mTilePosition , leastRecentlyUsedRecastMesh )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh , mOffMeshConnections )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mostRecentlyUsedRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_unused_least_recently_used_value_when_item_does_not_not_fit_cache_max_size )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_unused_least_recently_used_value_when_item_does_not_not_fit_cache_max_size )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = 2 * ( mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ) ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = 2 * ( navMeshDataSize + navMeshKeySize ) ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh tooLargeRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const RecastMesh tooLargeRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const auto tooLargeData = reinterpret_cast < unsigned char * > ( dtAlloc ( 2 , DT_ALLOC_PERM ) ) ;
auto tooLargeData = makePeparedNavMeshData ( 10 ) ;
NavMeshData tooLargeNavMeshData { tooLargeData , 2 } ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections , std : : move ( mNavMeshData ) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std : : move ( mPreparedNavMeshData ) ) ;
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , tooLargeRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , tooLargeRecastMesh , std : : move ( tooLargeData ) ) ) ;
std : : move ( tooLargeNavMeshData ) ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ) ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_unused_least_recently_used_value_when_item_does_not_not_fit_size_of_unused_items )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , set_should_not_replace_unused_least_recently_used_value_when_item_does_not_not_fit_size_of_unused_items )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = 2 * ( mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ) ;
const std : : size_t navMeshKeySize1 = cRecastMeshKeySize ;
const std : : size_t navMeshKeySize2 = cRecastMeshWithWaterKeySize ;
const std : : size_t maxSize = 2 * navMeshDataSize + navMeshKeySize1 + navMeshKeySize2 ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > anotherWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > anotherWater { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , anotherWater } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , anotherWater } ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto anotherData = makePeparedNavMeshData ( 3 ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
const std : : vector < RecastMesh : : Water > tooLargeWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > tooLargeWater { 1 , RecastMesh : : Water { 2 , btTransform : : getIdentity ( ) } } ;
const RecastMesh tooLargeRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh tooLargeRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , tooLargeWater } ;
mAreaTypes , tooLargeWater } ;
const auto tooLargeData = reinterpret_cast < unsigned char * > ( dtAlloc ( 2 , DT_ALLOC_PERM ) ) ;
auto tooLargeData = makePeparedNavMeshData ( 10 ) ;
NavMeshData tooLargeNavMeshData { tooLargeData , 2 } ;
const auto value = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ,
const auto value = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh ,
std : : move ( m NavMeshData) ) ;
std : : move ( m Prepared NavMeshData) ) ;
ASSERT_TRUE ( value ) ;
ASSERT_TRUE ( value ) ;
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections ,
ASSERT_TRUE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh ,
std : : move ( another NavMesh Data) ) ) ;
std : : move ( another Data) ) ) ;
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , tooLargeRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , tooLargeRecastMesh ,
std : : move ( tooLarge NavMesh Data) ) ) ;
std : : move ( tooLarge Data) ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections )) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , anotherRecastMesh )) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , release_used_after_set_then_used_by_get_item_should_left_this_item_available )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , release_used_after_set_then_used_by_get_item_should_left_this_item_available )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices ,
mAreaTypes , water } ;
mAreaTypes , water } ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto anotherData = makePeparedNavMeshData ( 3 ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
const auto firstCopy = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
const auto firstCopy = cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
ASSERT_TRUE ( firstCopy ) ;
ASSERT_TRUE ( firstCopy ) ;
{
{
const auto secondCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections );
const auto secondCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh );
ASSERT_TRUE ( secondCopy ) ;
ASSERT_TRUE ( secondCopy ) ;
}
}
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , std : : move ( anotherData ) ) ) ;
std : : move ( anotherNavMeshData ) ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ) ) ;
}
}
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , release_twice_used_item_should_left_this_item_available )
TEST_F ( DetourNavigatorNavMeshTilesCacheTest , release_twice_used_item_should_left_this_item_available )
{
{
const std : : size_t navMeshDataSize = 1 ;
const std : : size_t maxSize = mRecastMeshWithWaterSize + mPreparedNavMeshDataSize ;
const std : : size_t navMeshKeySize = cRecastMeshKeySize ;
const std : : size_t maxSize = navMeshDataSize + navMeshKeySize ;
NavMeshTilesCache cache ( maxSize ) ;
NavMeshTilesCache cache ( maxSize ) ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const std : : vector < RecastMesh : : Water > water { 1 , RecastMesh : : Water { 1 , btTransform : : getIdentity ( ) } } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const RecastMesh anotherRecastMesh { mGeneration , mRevision , mIndices , mVertices , mAreaTypes , water } ;
const auto anotherData = reinterpret_cast < unsigned char * > ( dtAlloc ( 1 , DT_ALLOC_PERM ) ) ;
auto anotherData = makePeparedNavMeshData ( 3 ) ;
NavMeshData anotherNavMeshData { anotherData , 1 } ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections, std: : move ( m NavMeshData) ) ;
cache . set ( mAgentHalfExtents , mTilePosition , mRecastMesh , std: : move ( m Prepared NavMeshData) ) ;
const auto firstCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections );
const auto firstCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh );
ASSERT_TRUE ( firstCopy ) ;
ASSERT_TRUE ( firstCopy ) ;
{
{
const auto secondCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections );
const auto secondCopy = cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh );
ASSERT_TRUE ( secondCopy ) ;
ASSERT_TRUE ( secondCopy ) ;
}
}
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , mOffMeshConnections ,
EXPECT_FALSE ( cache . set ( mAgentHalfExtents , mTilePosition , anotherRecastMesh , std : : move ( anotherData ) ) ) ;
std : : move ( anotherNavMeshData ) ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh ) ) ;
EXPECT_TRUE ( cache . get ( mAgentHalfExtents , mTilePosition , mRecastMesh , mOffMeshConnections ) ) ;
}
}
}
}