Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/tests/test_RangeManager.h
Show All 11 Lines | |||||
* GNU General Public License for more details. | * GNU General Public License for more details. | ||||
* | * | ||||
* You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include "simulation2/system/ComponentTest.h" | #include "simulation2/system/ComponentTest.h" | ||||
#include "simulation2/components/ICmpRangeManager.h" | #include "simulation2/components/ICmpRangeManager.h" | ||||
#include "simulation2/components/ICmpObstruction.h" | |||||
#include "simulation2/components/ICmpPosition.h" | #include "simulation2/components/ICmpPosition.h" | ||||
#include "simulation2/components/ICmpVision.h" | #include "simulation2/components/ICmpVision.h" | ||||
#include <boost/random/mersenne_twister.hpp> | #include <boost/random/mersenne_twister.hpp> | ||||
#include <boost/random/uniform_real_distribution.hpp> | #include <boost/random/uniform_real_distribution.hpp> | ||||
class MockVision : public ICmpVision | class MockVisionRgm : public ICmpVision | ||||
{ | { | ||||
public: | public: | ||||
DEFAULT_MOCK_COMPONENT() | DEFAULT_MOCK_COMPONENT() | ||||
virtual entity_pos_t GetRange() const { return entity_pos_t::FromInt(66); } | virtual entity_pos_t GetRange() const { return entity_pos_t::FromInt(66); } | ||||
virtual bool GetRevealShore() const { return false; } | virtual bool GetRevealShore() const { return false; } | ||||
}; | }; | ||||
class MockPosition : public ICmpPosition | class MockPositionRgm : public ICmpPosition | ||||
{ | { | ||||
public: | public: | ||||
DEFAULT_MOCK_COMPONENT() | DEFAULT_MOCK_COMPONENT() | ||||
virtual void SetTurretParent(entity_id_t UNUSED(id), const CFixedVector3D& UNUSED(pos)) {} | virtual void SetTurretParent(entity_id_t UNUSED(id), const CFixedVector3D& UNUSED(pos)) {} | ||||
virtual entity_id_t GetTurretParent() const {return INVALID_ENTITY;} | virtual entity_id_t GetTurretParent() const {return INVALID_ENTITY;} | ||||
virtual void UpdateTurretPosition() {} | virtual void UpdateTurretPosition() {} | ||||
virtual std::set<entity_id_t>* GetTurrets() { return NULL; } | virtual std::set<entity_id_t>* GetTurrets() { return NULL; } | ||||
virtual bool IsInWorld() const { return true; } | virtual bool IsInWorld() const { return true; } | ||||
virtual void MoveOutOfWorld() { } | virtual void MoveOutOfWorld() { } | ||||
virtual void MoveTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { } | virtual void MoveTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { } | ||||
virtual void MoveAndTurnTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z), entity_angle_t UNUSED(a)) { } | virtual void MoveAndTurnTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z), entity_angle_t UNUSED(a)) { } | ||||
virtual void JumpTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { } | virtual void JumpTo(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) { } | ||||
virtual void SetHeightOffset(entity_pos_t UNUSED(dy)) { } | virtual void SetHeightOffset(entity_pos_t UNUSED(dy)) { } | ||||
virtual entity_pos_t GetHeightOffset() const { return entity_pos_t::Zero(); } | virtual entity_pos_t GetHeightOffset() const { return entity_pos_t::Zero(); } | ||||
virtual void SetHeightFixed(entity_pos_t UNUSED(y)) { } | virtual void SetHeightFixed(entity_pos_t UNUSED(y)) { } | ||||
virtual entity_pos_t GetHeightFixed() const { return entity_pos_t::Zero(); } | virtual entity_pos_t GetHeightFixed() const { return entity_pos_t::Zero(); } | ||||
virtual bool IsHeightRelative() const { return true; } | virtual bool IsHeightRelative() const { return true; } | ||||
virtual void SetHeightRelative(bool UNUSED(relative)) { } | virtual void SetHeightRelative(bool UNUSED(relative)) { } | ||||
virtual bool CanFloat() const { return false; } | virtual bool CanFloat() const { return false; } | ||||
virtual void SetFloating(bool UNUSED(flag)) { } | virtual void SetFloating(bool UNUSED(flag)) { } | ||||
virtual void SetActorFloating(bool UNUSED(flag)) { } | virtual void SetActorFloating(bool UNUSED(flag)) { } | ||||
virtual void SetConstructionProgress(fixed UNUSED(progress)) { } | virtual void SetConstructionProgress(fixed UNUSED(progress)) { } | ||||
virtual CFixedVector3D GetPosition() const { return CFixedVector3D(); } | virtual CFixedVector3D GetPosition() const { return m_Pos; } | ||||
virtual CFixedVector2D GetPosition2D() const { return CFixedVector2D(); } | virtual CFixedVector2D GetPosition2D() const { return CFixedVector2D(m_Pos.X, m_Pos.Z); } | ||||
virtual CFixedVector3D GetPreviousPosition() const { return CFixedVector3D(); } | virtual CFixedVector3D GetPreviousPosition() const { return CFixedVector3D(); } | ||||
virtual CFixedVector2D GetPreviousPosition2D() const { return CFixedVector2D(); } | virtual CFixedVector2D GetPreviousPosition2D() const { return CFixedVector2D(); } | ||||
virtual void TurnTo(entity_angle_t UNUSED(y)) { } | virtual void TurnTo(entity_angle_t UNUSED(y)) { } | ||||
virtual void SetYRotation(entity_angle_t UNUSED(y)) { } | virtual void SetYRotation(entity_angle_t UNUSED(y)) { } | ||||
virtual void SetXZRotation(entity_angle_t UNUSED(x), entity_angle_t UNUSED(z)) { } | virtual void SetXZRotation(entity_angle_t UNUSED(x), entity_angle_t UNUSED(z)) { } | ||||
virtual CFixedVector3D GetRotation() const { return CFixedVector3D(); } | virtual CFixedVector3D GetRotation() const { return CFixedVector3D(); } | ||||
virtual fixed GetDistanceTravelled() const { return fixed::Zero(); } | virtual fixed GetDistanceTravelled() const { return fixed::Zero(); } | ||||
virtual void GetInterpolatedPosition2D(float UNUSED(frameOffset), float& x, float& z, float& rotY) const { x = z = rotY = 0; } | virtual void GetInterpolatedPosition2D(float UNUSED(frameOffset), float& x, float& z, float& rotY) const { x = z = rotY = 0; } | ||||
virtual CMatrix3D GetInterpolatedTransform(float UNUSED(frameOffset)) const { return CMatrix3D(); } | virtual CMatrix3D GetInterpolatedTransform(float UNUSED(frameOffset)) const { return CMatrix3D(); } | ||||
CFixedVector3D m_Pos; | |||||
}; | |||||
class MockObstructionRgm : public ICmpObstruction | |||||
{ | |||||
public: | |||||
DEFAULT_MOCK_COMPONENT(); | |||||
MockObstructionRgm(entity_pos_t s) : m_Size(s) {}; | |||||
virtual ICmpObstructionManager::tag_t GetObstruction() const { return {}; }; | |||||
virtual bool GetObstructionSquare(ICmpObstructionManager::ObstructionSquare&) const { return false; }; | |||||
virtual bool GetPreviousObstructionSquare(ICmpObstructionManager::ObstructionSquare&) const { return false; }; | |||||
virtual entity_pos_t GetSize() const { return m_Size; }; | |||||
virtual CFixedVector2D GetStaticSize() const { return {}; }; | |||||
virtual EObstructionType GetObstructionType() const { return {}; }; | |||||
virtual void SetUnitClearance(const entity_pos_t&) {}; | |||||
virtual bool IsControlPersistent() const { return {}; }; | |||||
virtual bool CheckShorePlacement() const { return {}; }; | |||||
virtual EFoundationCheck CheckFoundation(const std::string&) const { return {}; }; | |||||
virtual EFoundationCheck CheckFoundation(const std::string& , bool) const { return {}; }; | |||||
virtual std::string CheckFoundation_wrapper(const std::string&, bool) const { return {}; }; | |||||
virtual bool CheckDuplicateFoundation() const { return {}; }; | |||||
virtual std::vector<entity_id_t> GetEntitiesByFlags(ICmpObstructionManager::flags_t) const { return {}; }; | |||||
virtual std::vector<entity_id_t> GetEntitiesBlockingMovement() const { return {}; }; | |||||
virtual std::vector<entity_id_t> GetEntitiesBlockingConstruction() const { return {}; }; | |||||
virtual std::vector<entity_id_t> GetEntitiesDeletedUponConstruction() const { return {}; }; | |||||
virtual void ResolveFoundationCollisions() const {}; | |||||
virtual void SetActive(bool) {}; | |||||
virtual void SetMovingFlag(bool) {}; | |||||
virtual void SetDisableBlockMovementPathfinding(bool, bool, int32_t) {}; | |||||
virtual bool GetBlockMovementFlag() const { return {}; }; | |||||
virtual void SetControlGroup(entity_id_t) {}; | |||||
virtual entity_id_t GetControlGroup() const { return {}; }; | |||||
virtual void SetControlGroup2(entity_id_t) {}; | |||||
virtual entity_id_t GetControlGroup2() const { return {}; }; | |||||
private: | |||||
entity_pos_t m_Size; | |||||
}; | }; | ||||
class TestCmpRangeManager : public CxxTest::TestSuite | class TestCmpRangeManager : public CxxTest::TestSuite | ||||
{ | { | ||||
public: | public: | ||||
void setUp() | void setUp() | ||||
{ | { | ||||
CXeromyces::Startup(); | CXeromyces::Startup(); | ||||
} | } | ||||
void tearDown() | void tearDown() | ||||
{ | { | ||||
CXeromyces::Terminate(); | CXeromyces::Terminate(); | ||||
} | } | ||||
// TODO It would be nice to call Verify() with the shore revealing system | // TODO It would be nice to call Verify() with the shore revealing system | ||||
// but that means testing on an actual map, with water and land. | // but that means testing on an actual map, with water and land. | ||||
void test_basic() | void test_basic() | ||||
{ | { | ||||
ComponentTestHelper test(g_ScriptContext); | ComponentTestHelper test(g_ScriptContext); | ||||
ICmpRangeManager* cmp = test.Add<ICmpRangeManager>(CID_RangeManager, "", SYSTEM_ENTITY); | ICmpRangeManager* cmp = test.Add<ICmpRangeManager>(CID_RangeManager, "", SYSTEM_ENTITY); | ||||
MockVision vision; | MockVisionRgm vision; | ||||
test.AddMock(100, IID_Vision, vision); | test.AddMock(100, IID_Vision, vision); | ||||
MockPosition position; | MockPositionRgm position; | ||||
test.AddMock(100, IID_Position, position); | test.AddMock(100, IID_Position, position); | ||||
// This tests that the incremental computation produces the correct result | // This tests that the incremental computation produces the correct result | ||||
// in various edge cases | // in various edge cases | ||||
cmp->SetBounds(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0), entity_pos_t::FromInt(512), entity_pos_t::FromInt(512), 512/TERRAIN_TILE_SIZE + 1); | cmp->SetBounds(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0), entity_pos_t::FromInt(512), entity_pos_t::FromInt(512), 512/TERRAIN_TILE_SIZE + 1); | ||||
cmp->Verify(); | cmp->Verify(); | ||||
{ CMessageCreate msg(100); cmp->HandleMessage(msg, false); } | { CMessageCreate msg(100); cmp->HandleMessage(msg, false); } | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | // Test OwnershipChange, GetEntitiesByPlayer, GetNonGaiaEntities | ||||
for (player_id_t i = 0; i < 8; ++i) | for (player_id_t i = 0; i < 8; ++i) | ||||
TS_ASSERT_EQUALS(cmp->GetEntitiesByPlayer(i).size(), i == newOwner ? 1 : 0); | TS_ASSERT_EQUALS(cmp->GetEntitiesByPlayer(i).size(), i == newOwner ? 1 : 0); | ||||
TS_ASSERT_EQUALS(cmp->GetNonGaiaEntities().size(), newOwner > 0 ? 1 : 0); | TS_ASSERT_EQUALS(cmp->GetNonGaiaEntities().size(), newOwner > 0 ? 1 : 0); | ||||
previousOwner = newOwner; | previousOwner = newOwner; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void test_queries() | |||||
{ | |||||
ComponentTestHelper test(g_ScriptContext); | |||||
ICmpRangeManager* cmp = test.Add<ICmpRangeManager>(CID_RangeManager, "", SYSTEM_ENTITY); | |||||
MockVisionRgm vision, vision2; | |||||
MockPositionRgm position, position2; | |||||
MockObstructionRgm obs(fixed::FromInt(2)), obs2(fixed::Zero()); | |||||
test.AddMock(100, IID_Vision, vision); | |||||
test.AddMock(100, IID_Position, position); | |||||
test.AddMock(100, IID_Obstruction, obs); | |||||
test.AddMock(101, IID_Vision, vision2); | |||||
test.AddMock(101, IID_Position, position2); | |||||
test.AddMock(101, IID_Obstruction, obs2); | |||||
cmp->SetBounds(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0), entity_pos_t::FromInt(512), entity_pos_t::FromInt(512), 512/TERRAIN_TILE_SIZE + 1); | |||||
cmp->Verify(); | |||||
{ CMessageCreate msg(100); cmp->HandleMessage(msg, false); } | |||||
{ CMessageCreate msg(101); cmp->HandleMessage(msg, false); } | |||||
{ CMessageOwnershipChanged msg(100, -1, 1); cmp->HandleMessage(msg, false); } | |||||
{ CMessageOwnershipChanged msg(101, -1, 1); cmp->HandleMessage(msg, false); } | |||||
auto move = [&cmp](entity_id_t ent, MockPositionRgm& pos, fixed x, fixed z) { | |||||
pos.m_Pos = CFixedVector3D(x, fixed::Zero(), z); | |||||
{ CMessagePositionChanged msg(ent, true, x, z, entity_angle_t::Zero()); cmp->HandleMessage(msg, false); } | |||||
}; | |||||
move(100, position, fixed::FromInt(10), fixed::FromInt(10)); | |||||
move(101, position2, fixed::FromInt(10), fixed::FromInt(20)); | |||||
std::vector<entity_id_t> nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{}); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
move(101, position2, fixed::FromInt(10), fixed::FromInt(10)); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{}); | |||||
move(101, position2, fixed::FromInt(10), fixed::FromInt(13)); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(4), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{}); | |||||
move(101, position2, fixed::FromInt(10), fixed::FromInt(15)); | |||||
// In range thanks to self obstruction size. | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
// In range thanks to target obstruction size. | |||||
nearby = cmp->ExecuteQuery(101, fixed::FromInt(0), fixed::FromInt(4), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{100}); | |||||
// Trickier: min-range is closest-to-closest, but rotation may change the real distance. | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(2), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(5), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{101}); | |||||
nearby = cmp->ExecuteQuery(100, fixed::FromInt(6), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{}); | |||||
nearby = cmp->ExecuteQuery(101, fixed::FromInt(5), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{100}); | |||||
nearby = cmp->ExecuteQuery(101, fixed::FromInt(6), fixed::FromInt(50), {1}, 0); | |||||
TS_ASSERT_EQUALS(nearby, std::vector<entity_id_t>{}); | |||||
} | |||||
}; | }; |
Wildfire Games · Phabricator