mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-22 05:27:19 +00:00
Implement GTest and change windows output path
Implement GTest as a testing infrastructure. Make windows output binaries to the build folder instead of the release type folder (potentially issue further down the line) Add a simple unit test for DestroyableComponent
This commit is contained in:
parent
9c58ea5c41
commit
1464762bcd
2
.gitignore
vendored
2
.gitignore
vendored
@ -121,4 +121,4 @@ docker/__pycache__
|
|||||||
|
|
||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
|
||||||
!/tests/TestBitStreams/*.bin
|
!*Test.bin
|
||||||
|
@ -76,6 +76,15 @@ endif()
|
|||||||
|
|
||||||
# Our output dir
|
# Our output dir
|
||||||
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
|
set(CMAKE_BINARY_DIR ${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
|
# TODO make this not have to override the build type directories
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
@ -239,6 +248,11 @@ set(INCLUDED_DIRECTORIES
|
|||||||
"thirdparty/recastnavigation"
|
"thirdparty/recastnavigation"
|
||||||
"thirdparty/SQLite"
|
"thirdparty/SQLite"
|
||||||
"thirdparty/cpplinq"
|
"thirdparty/cpplinq"
|
||||||
|
|
||||||
|
"tests"
|
||||||
|
"tests/dCommonTests"
|
||||||
|
"tests/dGameTests"
|
||||||
|
"tests/dGameTests/dComponentsTests"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||||
@ -320,8 +334,6 @@ if (UNIX)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(tests)
|
|
||||||
|
|
||||||
# Include all of our binary directories
|
# Include all of our binary directories
|
||||||
add_subdirectory(dWorldServer)
|
add_subdirectory(dWorldServer)
|
||||||
add_subdirectory(dAuthServer)
|
add_subdirectory(dAuthServer)
|
||||||
@ -354,3 +366,7 @@ target_precompile_headers(
|
|||||||
tinyxml2 PRIVATE
|
tinyxml2 PRIVATE
|
||||||
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
|
"$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_SOURCE_DIR}/thirdparty/tinyxml2/tinyxml2.h>"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (${__enable_testing__} MATCHES "1")
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
@ -118,14 +118,14 @@
|
|||||||
"execution": {
|
"execution": {
|
||||||
"jobs": 2
|
"jobs": 2
|
||||||
},
|
},
|
||||||
|
"output": {
|
||||||
|
"outputOnFailure": true
|
||||||
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"exclude": {
|
"exclude": {
|
||||||
"name": "((example)|(minigzip))+"
|
"name": "((example)|(minigzip))+"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"output": {
|
|
||||||
"outputOnFailure": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -18,3 +18,5 @@ __dynamic=1
|
|||||||
# Set __compile_backtrace__ to 1 to compile the backtrace library instead of using system libraries.
|
# Set __compile_backtrace__ to 1 to compile the backtrace library instead of using system libraries.
|
||||||
__maria_db_connector_compile_jobs__=1
|
__maria_db_connector_compile_jobs__=1
|
||||||
# Set to the number of jobs (make -j equivalent) to compile the mariadbconn files with.
|
# Set to the number of jobs (make -j equivalent) to compile the mariadbconn files with.
|
||||||
|
__enable_testing__=1
|
||||||
|
# When set to 1 and uncommented, compiling and linking testing folders and libraries will be done.
|
||||||
|
@ -42,6 +42,10 @@ This was done make sure that older and incomplete clients wouldn't produce false
|
|||||||
|
|
||||||
If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number.
|
If you're using a DLU client you'll have to go into the "CMakeVariables.txt" file and change the NET_VERSION variable to 171023 to match the modified client's version number.
|
||||||
|
|
||||||
|
### Enabling testing
|
||||||
|
While it is highly recommended to enable testing, if you would like to save compilation time, you'll want to comment out the enable_testing variable in CMakeVariables.txt.
|
||||||
|
It is recommended that after building and if testing is enabled, to run `ctest` and make sure all the tests pass.
|
||||||
|
|
||||||
### Using Docker
|
### Using Docker
|
||||||
Refer to [Docker.md](/Docker.md).
|
Refer to [Docker.md](/Docker.md).
|
||||||
|
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
set(DAUTHSERVER_SOURCES "AuthServer.cpp")
|
add_executable(AuthServer "AuthServer.cpp")
|
||||||
|
|
||||||
add_executable(AuthServer ${DAUTHSERVER_SOURCES})
|
|
||||||
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
|
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
set(DCHATSERVER_SOURCES "ChatPacketHandler.cpp"
|
set(DCHATSERVER_SOURCES
|
||||||
"ChatServer.cpp"
|
"ChatPacketHandler.cpp"
|
||||||
"PlayerContainer.cpp")
|
"PlayerContainer.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(ChatServer ${DCHATSERVER_SOURCES})
|
add_executable(ChatServer "ChatServer.cpp")
|
||||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter)
|
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
||||||
|
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer)
|
||||||
|
@ -138,25 +138,17 @@ void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn
|
|||||||
|
|
||||||
if (m_IsSmashable) {
|
if (m_IsSmashable) {
|
||||||
outBitStream->Write(m_HasBricks);
|
outBitStream->Write(m_HasBricks);
|
||||||
|
outBitStream->Write(m_ExplodeFactor != 1.0f);
|
||||||
if (m_ExplodeFactor != 1.0f) {
|
if (m_ExplodeFactor != 1.0f) outBitStream->Write(m_ExplodeFactor);
|
||||||
outBitStream->Write1();
|
|
||||||
outBitStream->Write(m_ExplodeFactor);
|
|
||||||
} else {
|
|
||||||
outBitStream->Write0();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m_DirtyHealth = false;
|
m_DirtyHealth = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outBitStream->Write(m_DirtyThreatList || bIsInitialUpdate);
|
||||||
if (m_DirtyThreatList || bIsInitialUpdate) {
|
if (m_DirtyThreatList || bIsInitialUpdate) {
|
||||||
outBitStream->Write1();
|
|
||||||
outBitStream->Write(m_HasThreats);
|
outBitStream->Write(m_HasThreats);
|
||||||
m_DirtyThreatList = false;
|
m_DirtyThreatList = false;
|
||||||
} else {
|
|
||||||
outBitStream->Write0();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +430,6 @@ void DestroyableComponent::AddEnemyFaction(int32_t factionID) {
|
|||||||
void DestroyableComponent::SetIsSmashable(bool value) {
|
void DestroyableComponent::SetIsSmashable(bool value) {
|
||||||
m_DirtyHealth = true;
|
m_DirtyHealth = true;
|
||||||
m_IsSmashable = value;
|
m_IsSmashable = value;
|
||||||
//m_HasBricks = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::SetAttacksToBlock(const uint32_t value) {
|
void DestroyableComponent::SetAttacksToBlock(const uint32_t value) {
|
||||||
|
@ -239,7 +239,7 @@ public:
|
|||||||
* Sets the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
* Sets the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
||||||
* @param value the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
* @param value the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
||||||
*/
|
*/
|
||||||
void SetExplodeFactor(float value);
|
void SetExplodeFactor(float value) { m_ExplodeFactor = value; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current multiplier for explosions
|
* Returns the current multiplier for explosions
|
||||||
@ -414,6 +414,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void AddOnHitCallback(const std::function<void(Entity*)>& callback);
|
void AddOnHitCallback(const std::function<void(Entity*)>& callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes a faction back to the list of factions.
|
||||||
|
* @param value Faction to add to list.
|
||||||
|
*
|
||||||
|
* This method should only be used for testing. Use AddFaction(int32_t, bool) for adding a faction properly.
|
||||||
|
*/
|
||||||
|
void AddFactionNoLookup(int32_t faction) { m_FactionIDs.push_back(faction); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Whether or not the health should be serialized
|
* Whether or not the health should be serialized
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
set(DMASTERSERVER_SOURCES "InstanceManager.cpp"
|
set(DMASTERSERVER_SOURCES
|
||||||
"MasterServer.cpp"
|
"InstanceManager.cpp"
|
||||||
"ObjectIDManager.cpp")
|
"ObjectIDManager.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(MasterServer ${DMASTERSERVER_SOURCES})
|
add_library(dMasterServer ${DMASTERSERVER_SOURCES})
|
||||||
target_link_libraries(MasterServer ${COMMON_LIBRARIES})
|
add_executable(MasterServer "MasterServer.cpp")
|
||||||
|
|
||||||
|
target_link_libraries(dMasterServer ${COMMON_LIBRARIES})
|
||||||
|
target_link_libraries(MasterServer ${COMMON_LIBRARIES} dMasterServer)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
||||||
|
@ -50,7 +50,6 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
|
|||||||
mNetIDManager = nullptr;
|
mNetIDManager = nullptr;
|
||||||
mReplicaManager = nullptr;
|
mReplicaManager = nullptr;
|
||||||
mServerType = serverType;
|
mServerType = serverType;
|
||||||
|
|
||||||
//Attempt to start our server here:
|
//Attempt to start our server here:
|
||||||
mIsOkay = Startup();
|
mIsOkay = Startup();
|
||||||
|
|
||||||
@ -193,7 +192,10 @@ bool dServer::Startup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dServer::Shutdown() {
|
void dServer::Shutdown() {
|
||||||
|
if (mPeer) {
|
||||||
mPeer->Shutdown(1000);
|
mPeer->Shutdown(1000);
|
||||||
|
RakNetworkFactory::DestroyRakPeerInterface(mPeer);
|
||||||
|
}
|
||||||
|
|
||||||
if (mNetIDManager) {
|
if (mNetIDManager) {
|
||||||
delete mNetIDManager;
|
delete mNetIDManager;
|
||||||
@ -205,10 +207,9 @@ void dServer::Shutdown() {
|
|||||||
mReplicaManager = nullptr;
|
mReplicaManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//RakNetworkFactory::DestroyRakPeerInterface(mPeer); //Not needed, we already called Shutdown ourselves.
|
if (mServerType != ServerType::Master && mMasterPeer) {
|
||||||
if (mServerType != ServerType::Master) {
|
|
||||||
mMasterPeer->Shutdown(1000);
|
mMasterPeer->Shutdown(1000);
|
||||||
//RakNetworkFactory::DestroyRakPeerInterface(mMasterPeer);
|
RakNetworkFactory::DestroyRakPeerInterface(mMasterPeer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ enum class ServerType : uint32_t {
|
|||||||
|
|
||||||
class dServer {
|
class dServer {
|
||||||
public:
|
public:
|
||||||
|
// Default constructor should only used for testing!
|
||||||
|
dServer() {};
|
||||||
dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, dLogger* logger, const std::string masterIP, int masterPort, ServerType serverType, unsigned int zoneID = 0);
|
dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, dLogger* logger, const std::string masterIP, int masterPort, ServerType serverType, unsigned int zoneID = 0);
|
||||||
~dServer();
|
~dServer();
|
||||||
|
|
||||||
@ -22,7 +24,7 @@ public:
|
|||||||
Packet* Receive();
|
Packet* Receive();
|
||||||
void DeallocatePacket(Packet* packet);
|
void DeallocatePacket(Packet* packet);
|
||||||
void DeallocateMasterPacket(Packet* packet);
|
void DeallocateMasterPacket(Packet* packet);
|
||||||
void Send(RakNet::BitStream* bitStream, const SystemAddress& sysAddr, bool broadcast);
|
virtual void Send(RakNet::BitStream* bitStream, const SystemAddress& sysAddr, bool broadcast);
|
||||||
void SendToMaster(RakNet::BitStream* bitStream);
|
void SendToMaster(RakNet::BitStream* bitStream);
|
||||||
|
|
||||||
void Disconnect(const SystemAddress& sysAddr, uint32_t disconNotifyID);
|
void Disconnect(const SystemAddress& sysAddr, uint32_t disconNotifyID);
|
||||||
@ -55,10 +57,10 @@ private:
|
|||||||
bool ConnectToMaster();
|
bool ConnectToMaster();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dLogger* mLogger;
|
dLogger* mLogger = nullptr;
|
||||||
RakPeerInterface* mPeer;
|
RakPeerInterface* mPeer = nullptr;
|
||||||
ReplicaManager* mReplicaManager;
|
ReplicaManager* mReplicaManager = nullptr;
|
||||||
NetworkIDManager* mNetIDManager;
|
NetworkIDManager* mNetIDManager = nullptr;
|
||||||
SocketDescriptor mSocketDescriptor;
|
SocketDescriptor mSocketDescriptor;
|
||||||
std::string mIP;
|
std::string mIP;
|
||||||
int mPort;
|
int mPort;
|
||||||
@ -71,7 +73,7 @@ private:
|
|||||||
bool mMasterConnectionActive;
|
bool mMasterConnectionActive;
|
||||||
ServerType mServerType;
|
ServerType mServerType;
|
||||||
|
|
||||||
RakPeerInterface* mMasterPeer;
|
RakPeerInterface* mMasterPeer = nullptr;
|
||||||
SocketDescriptor mMasterSocketDescriptor;
|
SocketDescriptor mMasterSocketDescriptor;
|
||||||
SystemAddress mMasterSystemAddress;
|
SystemAddress mMasterSystemAddress;
|
||||||
std::string mMasterIP;
|
std::string mMasterIP;
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
set(DWORLDSERVER_SOURCES "ObjectIDManager.cpp"
|
set(DWORLDSERVER_SOURCES
|
||||||
|
"ObjectIDManager.cpp"
|
||||||
"PerformanceManager.cpp"
|
"PerformanceManager.cpp"
|
||||||
"WorldServer.cpp")
|
)
|
||||||
|
|
||||||
|
add_library(dWorldServer ${DWORLDSERVER_SOURCES})
|
||||||
|
add_executable(WorldServer "WorldServer.cpp")
|
||||||
|
|
||||||
|
target_link_libraries(dWorldServer ${COMMON_LIBRARIES})
|
||||||
|
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics Detour Recast tinyxml2 dWorldServer dNavigation)
|
||||||
|
|
||||||
add_executable(WorldServer ${DWORLDSERVER_SOURCES})
|
|
||||||
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager Detour Recast dPhysics tinyxml2 dNavigation)
|
|
||||||
|
@ -1,34 +1,21 @@
|
|||||||
# create the testing file and list of tests
|
message (STATUS "Testing is enabled. Fetching gtest...")
|
||||||
create_test_sourcelist (Tests
|
enable_testing()
|
||||||
CommonCxxTests.cpp
|
|
||||||
AMFDeserializeTests.cpp
|
include(FetchContent)
|
||||||
TestNiPoint3.cpp
|
FetchContent_Declare(
|
||||||
TestLDFFormat.cpp
|
googletest
|
||||||
TestEncoding.cpp
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
|
GIT_TAG release-1.12.1
|
||||||
)
|
)
|
||||||
|
|
||||||
# add the executable
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
add_executable (CommonCxxTests ${Tests})
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
target_link_libraries(CommonCxxTests ${COMMON_LIBRARIES})
|
|
||||||
|
|
||||||
# remove the test driver source file
|
FetchContent_MakeAvailable(GoogleTest)
|
||||||
set (TestsToRun ${Tests})
|
include(GoogleTest)
|
||||||
remove (TestsToRun CommonCxxTests.cpp)
|
|
||||||
|
|
||||||
# Copy test files to testing directory
|
message(STATUS "gtest fetched and is now ready.")
|
||||||
configure_file(
|
|
||||||
${CMAKE_SOURCE_DIR}/tests/TestBitStreams/AMFBitStreamTest.bin ${PROJECT_BINARY_DIR}/tests/AMFBitStreamTest.bin
|
|
||||||
COPYONLY
|
|
||||||
)
|
|
||||||
|
|
||||||
configure_file(
|
# Add the subdirectories
|
||||||
${CMAKE_SOURCE_DIR}/tests/TestBitStreams/AMFBitStreamUnimplementedTest.bin ${PROJECT_BINARY_DIR}/tests/AMFBitStreamUnimplementedTest.bin
|
add_subdirectory(dCommonTests)
|
||||||
COPYONLY
|
add_subdirectory(dGameTests)
|
||||||
)
|
|
||||||
|
|
||||||
# Add all the ADD_TEST for each test
|
|
||||||
foreach (test ${TestsToRun})
|
|
||||||
get_filename_component (TName ${test} NAME_WE)
|
|
||||||
add_test (NAME ${TName} COMMAND CommonCxxTests ${TName})
|
|
||||||
set_property(TEST ${TName} PROPERTY ENVIRONMENT CTEST_OUTPUT_ON_FAILURE=1)
|
|
||||||
endforeach ()
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#define ASSERT_EQ(a,b) { if (!(a == b)) { printf("Failed assertion: " #a " == " #b " \n in %s:%d\n", __FILE__, __LINE__); return 1; }}
|
|
||||||
#define ASSERT_NE(a,b) { if (!(a != b)) { printf("Failed assertion: " #a " != " #b " \n in %s:%d\n", __FILE__, __LINE__); return 1; }}
|
|
@ -1,52 +0,0 @@
|
|||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "GeneralUtils.h"
|
|
||||||
#include "CommonCxxTests.h"
|
|
||||||
|
|
||||||
int TestEncoding(int argc, char** const argv) {
|
|
||||||
std::string x = "Hello World!";
|
|
||||||
std::string_view v(x);
|
|
||||||
|
|
||||||
uint32_t out;
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 'H');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 'e');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 'l');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 'l');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 'o');
|
|
||||||
ASSERT_EQ(GeneralUtils::_NextUTF8Char(v, out), true);
|
|
||||||
|
|
||||||
x = u8"Frühling";
|
|
||||||
v = x;
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'F');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'r');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'ü');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'h');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'l');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'i');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'n');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'g');
|
|
||||||
ASSERT_EQ(GeneralUtils::_NextUTF8Char(v, out), false);
|
|
||||||
|
|
||||||
x = "中文字";
|
|
||||||
v = x;
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'中');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'文');
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, U'字');
|
|
||||||
ASSERT_EQ(GeneralUtils::_NextUTF8Char(v, out), false);
|
|
||||||
|
|
||||||
x = "👨⚖️";
|
|
||||||
v = x;
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 0x1F468);
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 0x200D);
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 0x2696);
|
|
||||||
GeneralUtils::_NextUTF8Char(v, out); ASSERT_EQ(out, 0xFE0F);
|
|
||||||
ASSERT_EQ(GeneralUtils::_NextUTF8Char(v, out), false);
|
|
||||||
|
|
||||||
ASSERT_EQ(GeneralUtils::UTF8ToUTF16("Hello World!"), u"Hello World!");
|
|
||||||
ASSERT_EQ(GeneralUtils::UTF8ToUTF16("Frühling"), u"Frühling");
|
|
||||||
ASSERT_EQ(GeneralUtils::UTF8ToUTF16("中文字"), u"中文字");
|
|
||||||
ASSERT_EQ(GeneralUtils::UTF8ToUTF16("👨⚖️"), u"👨⚖️");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,52 +1,65 @@
|
|||||||
#include <chrono>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "AMFDeserialize.h"
|
#include "AMFDeserialize.h"
|
||||||
#include "AMFFormat.h"
|
#include "AMFFormat.h"
|
||||||
#include "CommonCxxTests.h"
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that all tests use to get their respective AMF.
|
||||||
|
*/
|
||||||
std::unique_ptr<AMFValue> ReadFromBitStream(RakNet::BitStream* bitStream) {
|
std::unique_ptr<AMFValue> ReadFromBitStream(RakNet::BitStream* bitStream) {
|
||||||
AMFDeserialize deserializer;
|
AMFDeserialize deserializer;
|
||||||
std::unique_ptr<AMFValue> returnValue(deserializer.Read(bitStream));
|
std::unique_ptr<AMFValue> returnValue(deserializer.Read(bitStream));
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFUndefinedFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFUndefined value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFUndefinedTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x00);
|
bitStream.Write<uint8_t>(0x00);
|
||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFUndefined);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFUndefined);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFNullFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFNull value from a BitStream.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFNullTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x01);
|
bitStream.Write<uint8_t>(0x01);
|
||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFNull);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFNull);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFFalseFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFFalse value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFFalseTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x02);
|
bitStream.Write<uint8_t>(0x02);
|
||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFFalse);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFFalse);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFTrueFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFTrue value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFTrueTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x03);
|
bitStream.Write<uint8_t>(0x03);
|
||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFTrue);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFTrue);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFIntegerFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFInteger value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFIntegerTest) {
|
||||||
|
CBITSTREAM
|
||||||
{
|
{
|
||||||
bitStream.Write<uint8_t>(0x04);
|
bitStream.Write<uint8_t>(0x04);
|
||||||
// 127 == 01111111
|
// 127 == 01111111
|
||||||
@ -91,21 +104,25 @@ int ReadAMFIntegerFromBitStream() {
|
|||||||
// Check that 2 byte max can be read correctly
|
// Check that 2 byte max can be read correctly
|
||||||
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), 16383);
|
ASSERT_EQ(static_cast<AMFIntegerValue*>(res.get())->GetIntegerValue(), 16383);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFDoubleFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFDouble value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFDoubleTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x05);
|
bitStream.Write<uint8_t>(0x05);
|
||||||
bitStream.Write<double>(25346.4f);
|
bitStream.Write<double>(25346.4f);
|
||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFDouble);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFDouble);
|
||||||
ASSERT_EQ(static_cast<AMFDoubleValue*>(res.get())->GetDoubleValue(), 25346.4f);
|
ASSERT_EQ(static_cast<AMFDoubleValue*>(res.get())->GetDoubleValue(), 25346.4f);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFStringFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFString value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFStringTest) {
|
||||||
|
CBITSTREAM
|
||||||
bitStream.Write<uint8_t>(0x06);
|
bitStream.Write<uint8_t>(0x06);
|
||||||
bitStream.Write<uint8_t>(0x0F);
|
bitStream.Write<uint8_t>(0x0F);
|
||||||
std::string toWrite = "stateID";
|
std::string toWrite = "stateID";
|
||||||
@ -113,11 +130,13 @@ int ReadAMFStringFromBitStream() {
|
|||||||
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
std::unique_ptr<AMFValue> res(ReadFromBitStream(&bitStream));
|
||||||
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFString);
|
ASSERT_EQ(res->GetValueType(), AMFValueType::AMFString);
|
||||||
ASSERT_EQ(static_cast<AMFStringValue*>(res.get())->GetStringValue(), "stateID");
|
ASSERT_EQ(static_cast<AMFStringValue*>(res.get())->GetStringValue(), "stateID");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadAMFArrayFromBitStream() {
|
/**
|
||||||
CBITSTREAM;
|
* @brief Test reading an AMFArray value from a BitStream.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeAMFArrayTest) {
|
||||||
|
CBITSTREAM
|
||||||
// Test empty AMFArray
|
// Test empty AMFArray
|
||||||
bitStream.Write<uint8_t>(0x09);
|
bitStream.Write<uint8_t>(0x09);
|
||||||
bitStream.Write<uint8_t>(0x01);
|
bitStream.Write<uint8_t>(0x01);
|
||||||
@ -149,15 +168,15 @@ int ReadAMFArrayFromBitStream() {
|
|||||||
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->FindValue<AMFStringValue>("BehaviorID")->GetStringValue(), "10447");
|
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->FindValue<AMFStringValue>("BehaviorID")->GetStringValue(), "10447");
|
||||||
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetValueAt<AMFStringValue>(0)->GetStringValue(), "10447");
|
ASSERT_EQ(static_cast<AMFArrayValue*>(res.get())->GetValueAt<AMFStringValue>(0)->GetStringValue(), "10447");
|
||||||
}
|
}
|
||||||
// Test a dense array
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test checks that if we recieve an unimplemented AMFValueType
|
* @brief This test checks that if we recieve an unimplemented AMFValueType
|
||||||
* we correctly throw an error and can actch it.
|
* we correctly throw an error and can actch it.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int TestUnimplementedAMFValues() {
|
#pragma message("-- The AMFDeserializeUnimplementedValuesTest causes a known memory leak of 880 bytes since it throws errors! --")
|
||||||
|
TEST(dCommonTests, AMFDeserializeUnimplementedValuesTest) {
|
||||||
std::vector<AMFValueType> unimplementedValues = {
|
std::vector<AMFValueType> unimplementedValues = {
|
||||||
AMFValueType::AMFXMLDoc,
|
AMFValueType::AMFXMLDoc,
|
||||||
AMFValueType::AMFDate,
|
AMFValueType::AMFDate,
|
||||||
@ -196,13 +215,15 @@ int TestUnimplementedAMFValues() {
|
|||||||
} catch (AMFValueType unimplementedValueType) {
|
} catch (AMFValueType unimplementedValueType) {
|
||||||
caughtException = true;
|
caughtException = true;
|
||||||
}
|
}
|
||||||
std::cout << "Testing unimplemented value " << amfValueType << " Did we catch an exception: " << (caughtException ? "YES" : "NO") << std::endl;
|
|
||||||
ASSERT_EQ(caughtException, true);
|
ASSERT_EQ(caughtException, true);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TestLiveCapture() {
|
/**
|
||||||
|
* @brief Test reading a packet capture from live from a BitStream
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeLivePacketTest) {
|
||||||
std::ifstream testFileStream;
|
std::ifstream testFileStream;
|
||||||
testFileStream.open("AMFBitStreamTest.bin", std::ios::binary);
|
testFileStream.open("AMFBitStreamTest.bin", std::ios::binary);
|
||||||
|
|
||||||
@ -267,7 +288,7 @@ int TestLiveCapture() {
|
|||||||
|
|
||||||
auto actionID = firstStrip->FindValue<AMFDoubleValue>("id");
|
auto actionID = firstStrip->FindValue<AMFDoubleValue>("id");
|
||||||
|
|
||||||
ASSERT_EQ(actionID->GetDoubleValue(), 0.0f)
|
ASSERT_EQ(actionID->GetDoubleValue(), 0.0f);
|
||||||
|
|
||||||
auto uiArray = firstStrip->FindValue<AMFArrayValue>("ui");
|
auto uiArray = firstStrip->FindValue<AMFArrayValue>("ui");
|
||||||
|
|
||||||
@ -279,7 +300,7 @@ int TestLiveCapture() {
|
|||||||
|
|
||||||
auto stripID = firstStrip->FindValue<AMFDoubleValue>("id");
|
auto stripID = firstStrip->FindValue<AMFDoubleValue>("id");
|
||||||
|
|
||||||
ASSERT_EQ(stripID->GetDoubleValue(), 0.0f)
|
ASSERT_EQ(stripID->GetDoubleValue(), 0.0f);
|
||||||
|
|
||||||
auto firstAction = dynamic_cast<AMFArrayValue*>(actionsInFirstStrip[0]);
|
auto firstAction = dynamic_cast<AMFArrayValue*>(actionsInFirstStrip[0]);
|
||||||
|
|
||||||
@ -318,17 +339,17 @@ int TestLiveCapture() {
|
|||||||
auto thirdDistance = thirdAction->FindValue<AMFDoubleValue>("Distance");
|
auto thirdDistance = thirdAction->FindValue<AMFDoubleValue>("Distance");
|
||||||
|
|
||||||
ASSERT_EQ(thirdDistance->GetDoubleValue(), 25.0f);
|
ASSERT_EQ(thirdDistance->GetDoubleValue(), 25.0f);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TestNullStream() {
|
/**
|
||||||
|
* @brief Tests that having no BitStream returns a nullptr.
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, AMFDeserializeNullTest) {
|
||||||
auto result = ReadFromBitStream(nullptr);
|
auto result = ReadFromBitStream(nullptr);
|
||||||
ASSERT_EQ(result.get(), nullptr);
|
ASSERT_EQ(result.get(), nullptr);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TestBadConversion() {
|
TEST(dCommonTests, AMFBadConversionTest) {
|
||||||
std::ifstream testFileStream;
|
std::ifstream testFileStream;
|
||||||
testFileStream.open("AMFBitStreamTest.bin", std::ios::binary);
|
testFileStream.open("AMFBitStreamTest.bin", std::ios::binary);
|
||||||
|
|
||||||
@ -360,30 +381,6 @@ int TestBadConversion() {
|
|||||||
|
|
||||||
// Value is out of bounds
|
// Value is out of bounds
|
||||||
ASSERT_EQ(result->GetValueAt<AMFTrueValue>(1), nullptr);
|
ASSERT_EQ(result->GetValueAt<AMFTrueValue>(1), nullptr);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AMFDeserializeTests(int argc, char** const argv) {
|
|
||||||
std::cout << "Checking that using a null bitstream doesnt cause exception" << std::endl;
|
|
||||||
if (TestNullStream()) return 1;
|
|
||||||
std::cout << "passed nullptr test, checking basic tests" << std::endl;
|
|
||||||
if (ReadAMFUndefinedFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFNullFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFFalseFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFTrueFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFIntegerFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFDoubleFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFStringFromBitStream() != 0) return 1;
|
|
||||||
if (ReadAMFArrayFromBitStream() != 0) return 1;
|
|
||||||
std::cout << "Passed basic test, checking live capture" << std::endl;
|
|
||||||
if (TestLiveCapture() != 0) return 1;
|
|
||||||
std::cout << "Passed live capture, checking unimplemented amf values" << std::endl;
|
|
||||||
if (TestUnimplementedAMFValues() != 0) return 1;
|
|
||||||
std::cout << "Passed unimplemented values, checking poor casting" << std::endl;
|
|
||||||
if (TestBadConversion() != 0) return 1;
|
|
||||||
std::cout << "Passed all tests." << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
19
tests/dCommonTests/CMakeLists.txt
Normal file
19
tests/dCommonTests/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
set(DCOMMONTEST_SOURCES
|
||||||
|
"AMFDeserializeTests.cpp"
|
||||||
|
"TestLDFFormat.cpp"
|
||||||
|
"TestNiPoint3.cpp"
|
||||||
|
"TestEncoding.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set our executable
|
||||||
|
add_executable(dCommonTests ${DCOMMONTEST_SOURCES})
|
||||||
|
|
||||||
|
# Link needed libraries
|
||||||
|
target_link_libraries(dCommonTests ${COMMON_LIBRARIES} GTest::gtest_main)
|
||||||
|
|
||||||
|
# Copy test files to testing directory
|
||||||
|
add_subdirectory(TestBitStreams)
|
||||||
|
file(COPY ${TESTBITSTREAMS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
# Discover the tests
|
||||||
|
gtest_discover_tests(dCommonTests)
|
11
tests/dCommonTests/TestBitStreams/CMakeLists.txt
Normal file
11
tests/dCommonTests/TestBitStreams/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
set(TESTBITSTREAMS
|
||||||
|
"AMFBitStreamTest.bin"
|
||||||
|
"AMFBitStreamUnimplementedTest.bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the folder name and prepend it to the files above
|
||||||
|
get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||||
|
list(TRANSFORM TESTBITSTREAMS PREPEND "${thisFolderName}/")
|
||||||
|
|
||||||
|
# Export our list of files
|
||||||
|
set(TESTBITSTREAMS ${TESTBITSTREAMS} PARENT_SCOPE)
|
68
tests/dCommonTests/TestEncoding.cpp
Normal file
68
tests/dCommonTests/TestEncoding.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
|
class EncodingTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
std::string originalWord;
|
||||||
|
std::string_view originalWordSv;
|
||||||
|
uint32_t out;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(EncodingTest, TestEncodingHello) {
|
||||||
|
originalWord = "Hello World!";
|
||||||
|
originalWordSv = originalWord;
|
||||||
|
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 'H');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 'e');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 'l');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 'l');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 'o');
|
||||||
|
EXPECT_EQ(GeneralUtils::_NextUTF8Char(originalWordSv, out), true);
|
||||||
|
|
||||||
|
EXPECT_EQ(GeneralUtils::UTF8ToUTF16("Hello World!"), u"Hello World!");
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(EncodingTest, TestEncodingUmlaut) {
|
||||||
|
originalWord = u8"Frühling";
|
||||||
|
originalWordSv = originalWord;
|
||||||
|
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'F');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'r');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'ü');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'h');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'l');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'i');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'n');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'g');
|
||||||
|
EXPECT_EQ(GeneralUtils::_NextUTF8Char(originalWordSv, out), false);
|
||||||
|
|
||||||
|
EXPECT_EQ(GeneralUtils::UTF8ToUTF16("Frühling"), u"Frühling");
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(EncodingTest, TestEncodingChinese) {
|
||||||
|
originalWord = "中文字";
|
||||||
|
originalWordSv = originalWord;
|
||||||
|
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'中');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'文');
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, U'字');
|
||||||
|
EXPECT_EQ(GeneralUtils::_NextUTF8Char(originalWordSv, out), false);
|
||||||
|
|
||||||
|
EXPECT_EQ(GeneralUtils::UTF8ToUTF16("中文字"), u"中文字");
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(EncodingTest, TestEncodingEmoji) {
|
||||||
|
originalWord = "👨⚖️";
|
||||||
|
originalWordSv = originalWord;
|
||||||
|
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 0x1F468);
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 0x200D);
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 0x2696);
|
||||||
|
GeneralUtils::_NextUTF8Char(originalWordSv, out); EXPECT_EQ(out, 0xFE0F);
|
||||||
|
EXPECT_EQ(GeneralUtils::_NextUTF8Char(originalWordSv, out), false);
|
||||||
|
|
||||||
|
EXPECT_EQ(GeneralUtils::UTF8ToUTF16("👨⚖️"), u"👨⚖️");
|
||||||
|
};
|
@ -1,14 +1,10 @@
|
|||||||
#include "LDFFormat.h"
|
#include "LDFFormat.h"
|
||||||
#include "CommonCxxTests.h"
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Test parsing an LDF value
|
* @brief Test parsing an LDF value
|
||||||
*
|
|
||||||
* @param argc Number of command line arguments for this test
|
|
||||||
* @param argv Command line arguments
|
|
||||||
* @return 0 on success, non-zero on failure
|
|
||||||
*/
|
*/
|
||||||
int TestLDFFormat(int argc, char** const argv) {
|
TEST(dCommonTests, LDFTest) {
|
||||||
// Create
|
// Create
|
||||||
auto* data = LDFBaseData::DataFromString("KEY=0:VALUE");
|
auto* data = LDFBaseData::DataFromString("KEY=0:VALUE");
|
||||||
|
|
||||||
@ -26,6 +22,4 @@ int TestLDFFormat(int argc, char** const argv) {
|
|||||||
|
|
||||||
// Cleanup the object
|
// Cleanup the object
|
||||||
delete data;
|
delete data;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
@ -1,13 +1,14 @@
|
|||||||
#include <stdexcept>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
#include "CommonCxxTests.h"
|
|
||||||
|
|
||||||
int TestNiPoint3(int argc, char** const argv) {
|
/**
|
||||||
|
* @brief Basic test for NiPoint3 functionality
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
TEST(dCommonTests, NiPoint3Test) {
|
||||||
// Check that Unitize works
|
// Check that Unitize works
|
||||||
ASSERT_EQ(NiPoint3(3, 0, 0).Unitize(), NiPoint3::UNIT_X);
|
ASSERT_EQ(NiPoint3(3, 0, 0).Unitize(), NiPoint3::UNIT_X);
|
||||||
// Check what unitize does to a vector of length 0
|
// Check what unitize does to a vector of length 0
|
||||||
ASSERT_EQ(NiPoint3::ZERO.Unitize(), NiPoint3::ZERO);
|
ASSERT_EQ(NiPoint3::ZERO.Unitize(), NiPoint3::ZERO);
|
||||||
// If we get here, all was successful
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
14
tests/dGameTests/CMakeLists.txt
Normal file
14
tests/dGameTests/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
set(DGAMETEST_SOURCES
|
||||||
|
"GameDependencies.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(dComponentsTests)
|
||||||
|
list(APPEND DGAMETEST_SOURCES ${DCOMPONENTS_TESTS})
|
||||||
|
|
||||||
|
# Add the executable. Remember to add all tests above this!
|
||||||
|
add_executable(dGameTests ${DGAMETEST_SOURCES})
|
||||||
|
|
||||||
|
target_link_libraries(dGameTests ${COMMON_LIBRARIES} GTest::gtest_main dGame dZoneManager dPhysics Detour Recast tinyxml2 dWorldServer dChatFilter dNavigation)
|
||||||
|
|
||||||
|
# Discover the tests
|
||||||
|
gtest_discover_tests(dGameTests)
|
15
tests/dGameTests/GameDependencies.cpp
Normal file
15
tests/dGameTests/GameDependencies.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "GameDependencies.h"
|
||||||
|
|
||||||
|
namespace Game {
|
||||||
|
dLogger* logger;
|
||||||
|
dServer* server;
|
||||||
|
dZoneManager* zoneManager;
|
||||||
|
dpWorld* physicsWorld;
|
||||||
|
dChatFilter* chatFilter;
|
||||||
|
dConfig* config;
|
||||||
|
dLocale* locale;
|
||||||
|
std::mt19937 randomEngine;
|
||||||
|
RakPeerInterface* chatServer;
|
||||||
|
AssetManager* assetManager;
|
||||||
|
SystemAddress chatSysAddr;
|
||||||
|
}
|
43
tests/dGameTests/GameDependencies.h
Normal file
43
tests/dGameTests/GameDependencies.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __GAMEDEPENDENCIES__H__
|
||||||
|
#define __GAMEDEPENDENCIES__H__
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "dServer.h"
|
||||||
|
#include "EntityManager.h"
|
||||||
|
class dZoneManager;
|
||||||
|
class AssetManager;
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
class dServerMock : public dServer {
|
||||||
|
public:
|
||||||
|
dServerMock() {};
|
||||||
|
~dServerMock() {};
|
||||||
|
void Send(RakNet::BitStream* bitStream, const SystemAddress& sysAddr, bool broadcast) override {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class GameDependenciesTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
void SetUpDependencies() {
|
||||||
|
info.pos = NiPoint3::ZERO;
|
||||||
|
info.rot = NiQuaternion::IDENTITY;
|
||||||
|
info.scale = 1.0f;
|
||||||
|
info.spawner = nullptr;
|
||||||
|
info.lot = 999;
|
||||||
|
Game::logger = new dLogger("./testing.log", true, true);
|
||||||
|
Game::server = new dServerMock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDownDependencies() {
|
||||||
|
if (Game::server) delete Game::server;
|
||||||
|
delete EntityManager::Instance();
|
||||||
|
if (Game::logger) {
|
||||||
|
Game::logger->Flush();
|
||||||
|
delete Game::logger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__GAMEDEPENDENCIES__H__
|
10
tests/dGameTests/dComponentsTests/CMakeLists.txt
Normal file
10
tests/dGameTests/dComponentsTests/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
set(DCOMPONENTS_TESTS
|
||||||
|
"DestroyableComponentTests.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the folder name and prepend it to the files above
|
||||||
|
get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||||
|
list(TRANSFORM DCOMPONENTS_TESTS PREPEND "${thisFolderName}/")
|
||||||
|
|
||||||
|
# Export to parent scope
|
||||||
|
set(DCOMPONENTS_TESTS ${DCOMPONENTS_TESTS} PARENT_SCOPE)
|
300
tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp
Normal file
300
tests/dGameTests/dComponentsTests/DestroyableComponentTests.cpp
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
#include "GameDependencies.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "BitStream.h"
|
||||||
|
#include "DestroyableComponent.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
|
class DestroyableTest : public GameDependenciesTest {
|
||||||
|
protected:
|
||||||
|
Entity* baseEntity;
|
||||||
|
DestroyableComponent* destroyableComponent;
|
||||||
|
CBITSTREAM
|
||||||
|
uint32_t flags = 0;
|
||||||
|
void SetUp() override {
|
||||||
|
SetUpDependencies();
|
||||||
|
baseEntity = new Entity(15, GameDependenciesTest::info);
|
||||||
|
destroyableComponent = new DestroyableComponent(baseEntity);
|
||||||
|
baseEntity->AddComponent(COMPONENT_TYPE_DESTROYABLE, destroyableComponent);
|
||||||
|
// Initialize some values to be not default
|
||||||
|
destroyableComponent->SetMaxHealth(12345.0f);
|
||||||
|
destroyableComponent->SetHealth(23);
|
||||||
|
destroyableComponent->SetMaxArmor(14.0f);
|
||||||
|
destroyableComponent->SetArmor(7);
|
||||||
|
destroyableComponent->SetMaxImagination(14000.0f);
|
||||||
|
destroyableComponent->SetImagination(6000);
|
||||||
|
destroyableComponent->SetIsSmashable(true);
|
||||||
|
destroyableComponent->SetExplodeFactor(1.1f);
|
||||||
|
destroyableComponent->AddFactionNoLookup(-1);
|
||||||
|
destroyableComponent->AddFactionNoLookup(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override {
|
||||||
|
delete baseEntity;
|
||||||
|
TearDownDependencies();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Construction of a DestroyableComponent
|
||||||
|
*/
|
||||||
|
TEST_F(DestroyableTest, DestroyableComponentSerializeConstructionTest) {
|
||||||
|
destroyableComponent->Serialize(&bitStream, true, flags);
|
||||||
|
// Assert that the full number of bits are present
|
||||||
|
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 460);
|
||||||
|
{
|
||||||
|
// Now read in the full serialized construction BitStream
|
||||||
|
bool optionStatusImmunityInfo{}; // Values under this option are unused.
|
||||||
|
bool optionStatsInfo{};
|
||||||
|
uint32_t currentHealth{};
|
||||||
|
float maxHealth{};
|
||||||
|
uint32_t currentArmor{};
|
||||||
|
float maxArmor{};
|
||||||
|
uint32_t currentImagination{};
|
||||||
|
float maxImagination{};
|
||||||
|
uint32_t damageAbsorptionPoints{};
|
||||||
|
bool hasImmunity{};
|
||||||
|
bool isGmImmune{};
|
||||||
|
bool isShielded{};
|
||||||
|
float actualMaxHealth{};
|
||||||
|
float actualMaxArmor{};
|
||||||
|
float actualMaxImagination{};
|
||||||
|
uint32_t factionsSize{};
|
||||||
|
std::vector<int32_t> factions{};
|
||||||
|
bool isSmashable{};
|
||||||
|
bool isDead{};
|
||||||
|
bool isSmashed{};
|
||||||
|
bool isModuleAssembly{};
|
||||||
|
bool optionExplodeFactor{};
|
||||||
|
float explodeFactor{};
|
||||||
|
bool optionIsOnThreatList{};
|
||||||
|
bool isThreatened{};
|
||||||
|
bitStream.Read(optionStatusImmunityInfo);
|
||||||
|
|
||||||
|
bitStream.Read(optionStatsInfo);
|
||||||
|
bitStream.Read(currentHealth);
|
||||||
|
bitStream.Read(maxHealth);
|
||||||
|
bitStream.Read(currentArmor);
|
||||||
|
bitStream.Read(maxArmor);
|
||||||
|
bitStream.Read(currentImagination);
|
||||||
|
bitStream.Read(maxImagination);
|
||||||
|
bitStream.Read(damageAbsorptionPoints);
|
||||||
|
bitStream.Read(hasImmunity);
|
||||||
|
bitStream.Read(isGmImmune);
|
||||||
|
bitStream.Read(isShielded);
|
||||||
|
bitStream.Read(actualMaxHealth);
|
||||||
|
bitStream.Read(actualMaxArmor);
|
||||||
|
bitStream.Read(actualMaxImagination);
|
||||||
|
bitStream.Read(factionsSize);
|
||||||
|
for (uint32_t i = 0; i < factionsSize; i++) {
|
||||||
|
int32_t factionID{};
|
||||||
|
bitStream.Read(factionID);
|
||||||
|
factions.push_back(factionID);
|
||||||
|
}
|
||||||
|
bitStream.Read(isSmashable); // This is an option later and also a flag at this spot
|
||||||
|
bitStream.Read(isDead);
|
||||||
|
bitStream.Read(isSmashed);
|
||||||
|
// if IsSmashable is true, read the next bits.
|
||||||
|
bitStream.Read(isModuleAssembly);
|
||||||
|
bitStream.Read(optionExplodeFactor);
|
||||||
|
bitStream.Read(explodeFactor);
|
||||||
|
|
||||||
|
bitStream.Read(optionIsOnThreatList);
|
||||||
|
bitStream.Read(isThreatened);
|
||||||
|
EXPECT_EQ(optionStatusImmunityInfo, false);
|
||||||
|
|
||||||
|
EXPECT_EQ(optionStatsInfo, true);
|
||||||
|
EXPECT_EQ(currentHealth, 23);
|
||||||
|
EXPECT_EQ(maxHealth, 12345.0f);
|
||||||
|
EXPECT_EQ(currentArmor, 7);
|
||||||
|
EXPECT_EQ(maxArmor, 14.0f);
|
||||||
|
EXPECT_EQ(currentImagination, 6000);
|
||||||
|
EXPECT_EQ(maxImagination, 14000.0f);
|
||||||
|
EXPECT_EQ(damageAbsorptionPoints, 0.0f);
|
||||||
|
EXPECT_EQ(hasImmunity, false);
|
||||||
|
EXPECT_EQ(isGmImmune, false);
|
||||||
|
EXPECT_EQ(isShielded, false);
|
||||||
|
EXPECT_EQ(actualMaxHealth, 12345.0f);
|
||||||
|
EXPECT_EQ(actualMaxArmor, 14.0f);
|
||||||
|
EXPECT_EQ(actualMaxImagination, 14000.0f);
|
||||||
|
EXPECT_EQ(factionsSize, 2);
|
||||||
|
EXPECT_NE(std::find(factions.begin(), factions.end(), -1), factions.end());
|
||||||
|
EXPECT_NE(std::find(factions.begin(), factions.end(), 6), factions.end());
|
||||||
|
EXPECT_EQ(isSmashable, true);
|
||||||
|
EXPECT_EQ(isDead, false);
|
||||||
|
EXPECT_EQ(isSmashed, false);
|
||||||
|
EXPECT_EQ(isSmashable, true); // For the sake of readability with the struct viewers, we will test this twice since its used as an option here, but as a bool above.
|
||||||
|
EXPECT_EQ(isModuleAssembly, false);
|
||||||
|
EXPECT_EQ(optionExplodeFactor, true);
|
||||||
|
EXPECT_EQ(explodeFactor, 1.1f);
|
||||||
|
|
||||||
|
EXPECT_EQ(optionIsOnThreatList, true);
|
||||||
|
EXPECT_EQ(isThreatened, false);
|
||||||
|
}
|
||||||
|
bitStream.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test serialization of a DestroyableComponent
|
||||||
|
*/
|
||||||
|
TEST_F(DestroyableTest, DestroyableComponentSerializeTest) {
|
||||||
|
bitStream.Reset();
|
||||||
|
// Initialize some values to be not default so we can test a full serialization
|
||||||
|
destroyableComponent->SetMaxHealth(1233.0f);
|
||||||
|
|
||||||
|
// Now we test a serialization for correctness.
|
||||||
|
destroyableComponent->Serialize(&bitStream, false, flags);
|
||||||
|
ASSERT_EQ(bitStream.GetNumberOfUnreadBits(), 422);
|
||||||
|
{
|
||||||
|
// Now read in the full serialized BitStream
|
||||||
|
bool optionStatsInfo{};
|
||||||
|
uint32_t currentHealth{};
|
||||||
|
float maxHealth{};
|
||||||
|
uint32_t currentArmor{};
|
||||||
|
float maxArmor{};
|
||||||
|
uint32_t currentImagination{};
|
||||||
|
float maxImagination{};
|
||||||
|
uint32_t damageAbsorptionPoints{};
|
||||||
|
bool hasImmunity{};
|
||||||
|
bool isGmImmune{};
|
||||||
|
bool isShielded{};
|
||||||
|
float actualMaxHealth{};
|
||||||
|
float actualMaxArmor{};
|
||||||
|
float actualMaxImagination{};
|
||||||
|
uint32_t factionsSize{};
|
||||||
|
std::vector<int32_t> factions{};
|
||||||
|
bool isSmashable{};
|
||||||
|
bool optionIsOnThreatList{};
|
||||||
|
bitStream.Read(optionStatsInfo);
|
||||||
|
bitStream.Read(currentHealth);
|
||||||
|
bitStream.Read(maxHealth);
|
||||||
|
bitStream.Read(currentArmor);
|
||||||
|
bitStream.Read(maxArmor);
|
||||||
|
bitStream.Read(currentImagination);
|
||||||
|
bitStream.Read(maxImagination);
|
||||||
|
bitStream.Read(damageAbsorptionPoints);
|
||||||
|
bitStream.Read(hasImmunity);
|
||||||
|
bitStream.Read(isGmImmune);
|
||||||
|
bitStream.Read(isShielded);
|
||||||
|
bitStream.Read(actualMaxHealth);
|
||||||
|
bitStream.Read(actualMaxArmor);
|
||||||
|
bitStream.Read(actualMaxImagination);
|
||||||
|
bitStream.Read(factionsSize);
|
||||||
|
for (uint32_t i = 0; i < factionsSize; i++) {
|
||||||
|
int32_t factionID{};
|
||||||
|
bitStream.Read(factionID);
|
||||||
|
factions.push_back(factionID);
|
||||||
|
}
|
||||||
|
bitStream.Read(isSmashable);
|
||||||
|
|
||||||
|
bitStream.Read(optionIsOnThreatList);
|
||||||
|
|
||||||
|
EXPECT_EQ(optionStatsInfo, true);
|
||||||
|
EXPECT_EQ(currentHealth, 23);
|
||||||
|
EXPECT_EQ(maxHealth, 1233.0f);
|
||||||
|
EXPECT_EQ(currentArmor, 7);
|
||||||
|
EXPECT_EQ(maxArmor, 14.0f);
|
||||||
|
EXPECT_EQ(currentImagination, 6000);
|
||||||
|
EXPECT_EQ(maxImagination, 14000.0f);
|
||||||
|
EXPECT_EQ(damageAbsorptionPoints, 0.0f);
|
||||||
|
EXPECT_EQ(hasImmunity, false);
|
||||||
|
EXPECT_EQ(isGmImmune, false);
|
||||||
|
EXPECT_EQ(isShielded, false);
|
||||||
|
EXPECT_EQ(actualMaxHealth, 1233.0f);
|
||||||
|
EXPECT_EQ(actualMaxArmor, 14.0f);
|
||||||
|
EXPECT_EQ(actualMaxImagination, 14000.0f);
|
||||||
|
EXPECT_EQ(factionsSize, 2);
|
||||||
|
EXPECT_NE(std::find(factions.begin(), factions.end(), -1), factions.end());
|
||||||
|
EXPECT_NE(std::find(factions.begin(), factions.end(), 6), factions.end());
|
||||||
|
EXPECT_EQ(isSmashable, true);
|
||||||
|
|
||||||
|
EXPECT_EQ(optionIsOnThreatList, false); // Always zero for now on serialization
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the Damage method of DestroyableComponent
|
||||||
|
*/
|
||||||
|
TEST_F(DestroyableTest, DestroyableComponentDamageTest) {
|
||||||
|
// Do some actions
|
||||||
|
destroyableComponent->SetMaxHealth(100.0f);
|
||||||
|
destroyableComponent->SetHealth(100);
|
||||||
|
destroyableComponent->SetMaxArmor(0.0f);
|
||||||
|
destroyableComponent->Damage(10, LWOOBJID_EMPTY);
|
||||||
|
// Check that we take damage
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 90);
|
||||||
|
// Check that if we have armor, we take the correct amount of damage
|
||||||
|
destroyableComponent->SetMaxArmor(10.0f);
|
||||||
|
destroyableComponent->SetArmor(5);
|
||||||
|
destroyableComponent->Damage(10, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 85);
|
||||||
|
// Check that if we have damage absorption we take the correct damage
|
||||||
|
destroyableComponent->SetDamageToAbsorb(10);
|
||||||
|
destroyableComponent->Damage(9, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 85);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetDamageToAbsorb(), 1);
|
||||||
|
destroyableComponent->Damage(6, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 80);
|
||||||
|
// Check that we take the correct reduced damage if we take reduced damage
|
||||||
|
destroyableComponent->SetDamageReduction(2);
|
||||||
|
destroyableComponent->Damage(7, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 75);
|
||||||
|
destroyableComponent->Damage(2, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 74);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetDamageReduction(), 2);
|
||||||
|
destroyableComponent->SetDamageReduction(0);
|
||||||
|
// Check that blocking works
|
||||||
|
destroyableComponent->SetAttacksToBlock(1);
|
||||||
|
destroyableComponent->Damage(UINT32_MAX, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 74);
|
||||||
|
destroyableComponent->Damage(4, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 70);
|
||||||
|
// Check that immunity works
|
||||||
|
destroyableComponent->SetIsImmune(true);
|
||||||
|
destroyableComponent->Damage(UINT32_MAX, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 70);
|
||||||
|
ASSERT_TRUE(destroyableComponent->IsImmune());
|
||||||
|
destroyableComponent->SetIsImmune(false);
|
||||||
|
destroyableComponent->SetIsGMImmune(true);
|
||||||
|
destroyableComponent->Damage(UINT32_MAX, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 70);
|
||||||
|
ASSERT_TRUE(destroyableComponent->IsImmune());
|
||||||
|
destroyableComponent->SetIsGMImmune(false);
|
||||||
|
// Check knockback immunity
|
||||||
|
destroyableComponent->SetIsShielded(true);
|
||||||
|
ASSERT_TRUE(destroyableComponent->IsKnockbackImmune());
|
||||||
|
// Finally deal enough damage to kill the Entity
|
||||||
|
destroyableComponent->Damage(71, LWOOBJID_EMPTY);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 0);
|
||||||
|
// Now lets heal some stats
|
||||||
|
destroyableComponent->Heal(15);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 15);
|
||||||
|
destroyableComponent->Heal(15000);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetHealth(), 100);
|
||||||
|
destroyableComponent->Repair(10);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetArmor(), 10);
|
||||||
|
destroyableComponent->Repair(15000);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetArmor(), 10);
|
||||||
|
destroyableComponent->SetMaxImagination(100.0f);
|
||||||
|
destroyableComponent->SetImagination(0);
|
||||||
|
destroyableComponent->Imagine(99);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetImagination(), 99);
|
||||||
|
destroyableComponent->Imagine(4);
|
||||||
|
ASSERT_EQ(destroyableComponent->GetImagination(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyableTest, DestroyableComponentFactionTest) {
|
||||||
|
ASSERT_TRUE(destroyableComponent->HasFaction(-1));
|
||||||
|
ASSERT_TRUE(destroyableComponent->HasFaction(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DestroyableTest, DestroyableComponentValiditiyTest) {
|
||||||
|
auto* enemyEntity = new Entity(19, info);
|
||||||
|
auto* enemyDestroyableComponent = new DestroyableComponent(enemyEntity);
|
||||||
|
enemyEntity->AddComponent(COMPONENT_TYPE_DESTROYABLE, enemyDestroyableComponent);
|
||||||
|
enemyDestroyableComponent->AddFactionNoLookup(16);
|
||||||
|
destroyableComponent->AddEnemyFaction(16);
|
||||||
|
EXPECT_TRUE(destroyableComponent->IsEnemy(enemyEntity));
|
||||||
|
EXPECT_FALSE(destroyableComponent->IsFriend(enemyEntity));
|
||||||
|
delete enemyEntity;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user