mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-14 03:58:18 +00:00
d30ebf33e5
`CPacker` is simply used as a byte buffer in the teehistorian tests. When the number of UUIDs is increased (in the future or in downstream projects) the tests will start to fail due to the buffer size being limited to 2048 bytes. This is fixed by using an `std::vector<unsigned char>` instead.
767 lines
19 KiB
C++
767 lines
19 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <base/detect.h>
|
|
#include <engine/server.h>
|
|
#include <engine/shared/config.h>
|
|
#include <game/gamecore.h>
|
|
#include <game/server/teehistorian.h>
|
|
|
|
#include <vector>
|
|
|
|
void RegisterGameUuids(CUuidManager *pManager);
|
|
|
|
class TeeHistorian : public ::testing::Test
|
|
{
|
|
protected:
|
|
CTeeHistorian m_TH;
|
|
CConfig m_Config;
|
|
CTuningParams m_Tuning;
|
|
CUuidManager m_UuidManager;
|
|
CTeeHistorian::CGameInfo m_GameInfo;
|
|
|
|
std::vector<unsigned char> m_vBuffer;
|
|
|
|
enum
|
|
{
|
|
STATE_NONE,
|
|
STATE_PLAYERS,
|
|
STATE_INPUTS,
|
|
};
|
|
|
|
int m_State;
|
|
|
|
TeeHistorian()
|
|
{
|
|
mem_zero(&m_Config, sizeof(m_Config));
|
|
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Save, Desc) \
|
|
m_Config.m_##Name = (Def);
|
|
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Save, Desc) MACRO_CONFIG_INT(Name, ScriptName, Def, 0, 0, Save, Desc)
|
|
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Save, Desc) \
|
|
str_copy(m_Config.m_##Name, (Def), sizeof(m_Config.m_##Name));
|
|
#include <engine/shared/config_variables.h>
|
|
#undef MACRO_CONFIG_STR
|
|
#undef MACRO_CONFIG_COL
|
|
#undef MACRO_CONFIG_INT
|
|
|
|
RegisterUuids(&m_UuidManager);
|
|
RegisterTeehistorianUuids(&m_UuidManager);
|
|
RegisterGameUuids(&m_UuidManager);
|
|
|
|
SHA256_DIGEST Sha256 = {{0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89,
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89,
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89,
|
|
0x01, 0x23}};
|
|
|
|
mem_zero(&m_GameInfo, sizeof(m_GameInfo));
|
|
|
|
m_GameInfo.m_GameUuid = CalculateUuid("test@ddnet.tw");
|
|
m_GameInfo.m_pServerVersion = "DDNet test";
|
|
m_GameInfo.m_StartTime = time(0);
|
|
m_GameInfo.m_pPrngDescription = "test-prng:02468ace";
|
|
|
|
m_GameInfo.m_pServerName = "server name";
|
|
m_GameInfo.m_ServerPort = 8303;
|
|
m_GameInfo.m_pGameType = "game type";
|
|
|
|
m_GameInfo.m_pMapName = "Kobra 3 Solo";
|
|
m_GameInfo.m_MapSize = 903514;
|
|
m_GameInfo.m_MapSha256 = Sha256;
|
|
m_GameInfo.m_MapCrc = 0xeceaf25c;
|
|
|
|
m_GameInfo.m_pConfig = &m_Config;
|
|
m_GameInfo.m_pTuning = &m_Tuning;
|
|
m_GameInfo.m_pUuids = &m_UuidManager;
|
|
|
|
Reset(&m_GameInfo);
|
|
}
|
|
|
|
static void WriteBuffer(std::vector<unsigned char> &vBuffer, const void *pData, size_t DataSize)
|
|
{
|
|
if(DataSize <= 0)
|
|
return;
|
|
|
|
const size_t OldSize = vBuffer.size();
|
|
vBuffer.resize(OldSize + DataSize);
|
|
mem_copy(&vBuffer[OldSize], pData, DataSize);
|
|
}
|
|
|
|
static void Write(const void *pData, int DataSize, void *pUser)
|
|
{
|
|
TeeHistorian *pThis = (TeeHistorian *)pUser;
|
|
WriteBuffer(pThis->m_vBuffer, pData, DataSize);
|
|
}
|
|
|
|
void Reset(const CTeeHistorian::CGameInfo *pGameInfo)
|
|
{
|
|
m_vBuffer.clear();
|
|
m_TH.Reset(pGameInfo, Write, this);
|
|
m_State = STATE_NONE;
|
|
}
|
|
|
|
void Expect(const unsigned char *pOutput, size_t OutputSize)
|
|
{
|
|
static CUuid TEEHISTORIAN_UUID = CalculateUuid("teehistorian@ddnet.tw");
|
|
static const char PREFIX1[] = "{\"comment\":\"teehistorian@ddnet.tw\",\"version\":\"2\",\"version_minor\":\"4\",\"game_uuid\":\"a1eb7182-796e-3b3e-941d-38ca71b2a4a8\",\"server_version\":\"DDNet test\",\"start_time\":\"";
|
|
static const char PREFIX2[] = "\",\"server_name\":\"server name\",\"server_port\":\"8303\",\"game_type\":\"game type\",\"map_name\":\"Kobra 3 Solo\",\"map_size\":\"903514\",\"map_sha256\":\"0123456789012345678901234567890123456789012345678901234567890123\",\"map_crc\":\"eceaf25c\",\"prng_description\":\"test-prng:02468ace\",\"config\":{},\"tuning\":{},\"uuids\":[";
|
|
static const char PREFIX3[] = "]}";
|
|
|
|
char aTimeBuf[64];
|
|
str_timestamp_ex(m_GameInfo.m_StartTime, aTimeBuf, sizeof(aTimeBuf), "%Y-%m-%dT%H:%M:%S%z");
|
|
|
|
std::vector<unsigned char> vBuffer;
|
|
WriteBuffer(vBuffer, &TEEHISTORIAN_UUID, sizeof(TEEHISTORIAN_UUID));
|
|
WriteBuffer(vBuffer, PREFIX1, str_length(PREFIX1));
|
|
WriteBuffer(vBuffer, aTimeBuf, str_length(aTimeBuf));
|
|
WriteBuffer(vBuffer, PREFIX2, str_length(PREFIX2));
|
|
for(int i = 0; i < m_UuidManager.NumUuids(); i++)
|
|
{
|
|
char aBuf[64];
|
|
str_format(aBuf, sizeof(aBuf), "%s\"%s\"",
|
|
i == 0 ? "" : ",",
|
|
m_UuidManager.GetName(OFFSET_UUID + i));
|
|
WriteBuffer(vBuffer, aBuf, str_length(aBuf));
|
|
}
|
|
WriteBuffer(vBuffer, PREFIX3, str_length(PREFIX3));
|
|
WriteBuffer(vBuffer, "", 1);
|
|
WriteBuffer(vBuffer, pOutput, OutputSize);
|
|
|
|
ExpectFull(vBuffer.data(), vBuffer.size());
|
|
}
|
|
|
|
void ExpectFull(const unsigned char *pOutput, size_t OutputSize)
|
|
{
|
|
const ::testing::TestInfo *pTestInfo =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
const char *pTestName = pTestInfo->name();
|
|
|
|
if(m_vBuffer.size() != OutputSize || mem_comp(m_vBuffer.data(), pOutput, OutputSize) != 0)
|
|
{
|
|
char aFilename[IO_MAX_PATH_LENGTH];
|
|
IOHANDLE File;
|
|
|
|
str_format(aFilename, sizeof(aFilename), "%sGot.teehistorian", pTestName);
|
|
File = io_open(aFilename, IOFLAG_WRITE);
|
|
ASSERT_TRUE(File);
|
|
io_write(File, m_vBuffer.data(), m_vBuffer.size());
|
|
io_close(File);
|
|
|
|
str_format(aFilename, sizeof(aFilename), "%sExpected.teehistorian", pTestName);
|
|
File = io_open(aFilename, IOFLAG_WRITE);
|
|
ASSERT_TRUE(File);
|
|
io_write(File, pOutput, OutputSize);
|
|
io_close(File);
|
|
}
|
|
|
|
printf("pOutput = {");
|
|
size_t Start = 0; // skip over header;
|
|
for(size_t i = 0; i < m_vBuffer.size(); i++)
|
|
{
|
|
if(Start == 0)
|
|
{
|
|
if(m_vBuffer[i] == 0)
|
|
Start = i + 1;
|
|
continue;
|
|
}
|
|
if((i - Start) % 10 == 0)
|
|
printf("\n\t");
|
|
else
|
|
printf(", ");
|
|
printf("0x%.2x", m_vBuffer[i]);
|
|
}
|
|
printf("\n}\n");
|
|
ASSERT_EQ(m_vBuffer.size(), OutputSize);
|
|
ASSERT_TRUE(mem_comp(m_vBuffer.data(), pOutput, OutputSize) == 0);
|
|
}
|
|
|
|
void Tick(int Tick)
|
|
{
|
|
if(m_State == STATE_PLAYERS)
|
|
{
|
|
Inputs();
|
|
}
|
|
if(m_State == STATE_INPUTS)
|
|
{
|
|
m_TH.EndInputs();
|
|
m_TH.EndTick();
|
|
}
|
|
m_TH.BeginTick(Tick);
|
|
m_TH.BeginPlayers();
|
|
m_State = STATE_PLAYERS;
|
|
}
|
|
void Inputs()
|
|
{
|
|
m_TH.EndPlayers();
|
|
m_TH.BeginInputs();
|
|
m_State = STATE_INPUTS;
|
|
}
|
|
void Finish()
|
|
{
|
|
if(m_State == STATE_PLAYERS)
|
|
{
|
|
Inputs();
|
|
}
|
|
if(m_State == STATE_INPUTS)
|
|
{
|
|
m_TH.EndInputs();
|
|
m_TH.EndTick();
|
|
}
|
|
m_TH.Finish();
|
|
}
|
|
void DeadPlayer(int ClientID)
|
|
{
|
|
m_TH.RecordDeadPlayer(ClientID);
|
|
}
|
|
void Player(int ClientID, int x, int y)
|
|
{
|
|
CNetObj_CharacterCore Char;
|
|
mem_zero(&Char, sizeof(Char));
|
|
Char.m_X = x;
|
|
Char.m_Y = y;
|
|
m_TH.RecordPlayer(ClientID, &Char);
|
|
}
|
|
};
|
|
|
|
TEST_F(TeeHistorian, Empty)
|
|
{
|
|
Expect((const unsigned char *)"", 0);
|
|
}
|
|
|
|
TEST_F(TeeHistorian, Finished)
|
|
{
|
|
const unsigned char EXPECTED[] = {0x40}; // FINISH
|
|
m_TH.Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickImplicitOneTick)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x42, 0x00, 0x01, 0x02, // PLAYERNEW cid=0 x=1 y=2
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
Player(0, 1, 2);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickImplicitTwoTicks)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x42, 0x00, 0x01, 0x02, // PLAYER_NEW cid=0 x=1 y=2
|
|
0x00, 0x01, 0x40, // PLAYER cid=0 dx=1 dy=-1
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
Player(0, 1, 2);
|
|
Tick(2);
|
|
Player(0, 2, 1);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickImplicitDescendingClientID)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x42, 0x01, 0x02, 0x03, // PLAYER_NEW cid=1 x=2 y=3
|
|
0x42, 0x00, 0x04, 0x05, // PLAYER_NEW cid=0 x=4 y=5
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
DeadPlayer(0);
|
|
Player(1, 2, 3);
|
|
Tick(2);
|
|
Player(0, 4, 5);
|
|
Player(1, 2, 3);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickExplicitAscendingClientID)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x42, 0x00, 0x04, 0x05, // PLAYER_NEW cid=0 x=4 y=5
|
|
0x41, 0x00, // TICK_SKIP dt=0
|
|
0x42, 0x01, 0x02, 0x03, // PLAYER_NEW cid=1 x=2 y=3
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
Player(0, 4, 5);
|
|
DeadPlayer(1);
|
|
Tick(2);
|
|
Player(0, 4, 5);
|
|
Player(1, 2, 3);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickImplicitEmpty)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x40, // FINISH
|
|
};
|
|
for(int i = 1; i < 500; i++)
|
|
{
|
|
Tick(i);
|
|
}
|
|
for(int i = 1000; i < 100000; i += 1000)
|
|
{
|
|
Tick(i);
|
|
}
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickExplicitStart)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x41, 0xb3, 0x07, // TICK_SKIP dt=499
|
|
0x42, 0x00, 0x40, 0x40, // PLAYER_NEW cid=0 x=-1 y=-1
|
|
0x40, // FINISH
|
|
};
|
|
Tick(500);
|
|
Player(0, -1, -1);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TickExplicitPlayerMessage)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x41, 0x00, // TICK_SKIP dt=0
|
|
0x46, 0x3f, 0x01, 0x00, // MESSAGE cid=63 msg="\0"
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
Inputs();
|
|
m_TH.RecordPlayerMessage(63, "", 1);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, ExtraMessage)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
0x41, 0x00, // TICK_SKIP dt=0
|
|
// EX uuid=6bb8ba88-0f0b-382e-8dae-dbf4052b8b7d data_len=0
|
|
0x4a,
|
|
0x6b, 0xb8, 0xba, 0x88, 0x0f, 0x0b, 0x38, 0x2e,
|
|
0x8d, 0xae, 0xdb, 0xf4, 0x05, 0x2b, 0x8b, 0x7d,
|
|
0x00,
|
|
0x40, // FINISH
|
|
};
|
|
Tick(1);
|
|
Inputs();
|
|
m_TH.RecordTestExtra();
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, DDNetVersion)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=60daba5c-52c4-3aeb-b8ba-b2953fb55a17 data_len=50
|
|
0x4a,
|
|
0x13, 0x97, 0xb6, 0x3e, 0xee, 0x4e, 0x39, 0x19,
|
|
0xb8, 0x6a, 0xb0, 0x58, 0x88, 0x7f, 0xca, 0xf5,
|
|
0x32,
|
|
// (DDNETVER) cid=0 connection_id=fb13a576-d35f-4893-b815-eedc6d98015b
|
|
// ddnet_version=13010 ddnet_version_str=DDNet 13.1 (3623f5e4cd184556)
|
|
0x00,
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b,
|
|
0x92, 0xcb, 0x01, 'D', 'D', 'N', 'e', 't',
|
|
' ', '1', '3', '.', '1', ' ', '(', '3',
|
|
'6', '2', '3', 'f', '5', 'e', '4', 'c',
|
|
'd', '1', '8', '4', '5', '5', '6', ')',
|
|
0x00,
|
|
// EX uuid=41b49541-f26f-325d-8715-9baf4b544ef9 data_len=4
|
|
0x4a,
|
|
0x41, 0xb4, 0x95, 0x41, 0xf2, 0x6f, 0x32, 0x5d,
|
|
0x87, 0x15, 0x9b, 0xaf, 0x4b, 0x54, 0x4e, 0xf9,
|
|
0x04,
|
|
// (DDNETVER_OLD) cid=1 ddnet_version=13010
|
|
0x01, 0x92, 0xcb, 0x01,
|
|
0x40, // FINISH
|
|
};
|
|
CUuid ConnectionID = {
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b};
|
|
m_TH.RecordDDNetVersion(0, ConnectionID, 13010, "DDNet 13.1 (3623f5e4cd184556)");
|
|
m_TH.RecordDDNetVersionOld(1, 13010);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, Auth)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=60daba5c-52c4-3aeb-b8ba-b2953fb55a17 data_len=16
|
|
0x4a,
|
|
0x60, 0xda, 0xba, 0x5c, 0x52, 0xc4, 0x3a, 0xeb,
|
|
0xb8, 0xba, 0xb2, 0x95, 0x3f, 0xb5, 0x5a, 0x17,
|
|
0x10,
|
|
// (AUTH_INIT) cid=0 level=3 auth_name="default_admin"
|
|
0x00, 0x03, 'd', 'e', 'f', 'a', 'u', 'l',
|
|
't', '_', 'a', 'd', 'm', 'i', 'n', 0x00,
|
|
// EX uuid=37ecd3b8-9218-3bb9-a71b-a935b86f6a81 data_len=9
|
|
0x4a,
|
|
0x37, 0xec, 0xd3, 0xb8, 0x92, 0x18, 0x3b, 0xb9,
|
|
0xa7, 0x1b, 0xa9, 0x35, 0xb8, 0x6f, 0x6a, 0x81,
|
|
0x09,
|
|
// (AUTH_LOGIN) cid=1 level=2 auth_name="foobar"
|
|
0x01, 0x02, 'f', 'o', 'o', 'b', 'a', 'r',
|
|
0x00,
|
|
// EX uuid=37ecd3b8-9218-3bb9-a71b-a935b86f6a81 data_len=7
|
|
0x4a,
|
|
0x37, 0xec, 0xd3, 0xb8, 0x92, 0x18, 0x3b, 0xb9,
|
|
0xa7, 0x1b, 0xa9, 0x35, 0xb8, 0x6f, 0x6a, 0x81,
|
|
0x07,
|
|
// (AUTH_LOGIN) cid=1 level=2 auth_name="foobar"
|
|
0x02, 0x01, 'h', 'e', 'l', 'p', 0x00,
|
|
// EX uuid=d4f5abe8-edd2-3fb9-abd8-1c8bb84f4a63 data_len=7
|
|
0x4a,
|
|
0xd4, 0xf5, 0xab, 0xe8, 0xed, 0xd2, 0x3f, 0xb9,
|
|
0xab, 0xd8, 0x1c, 0x8b, 0xb8, 0x4f, 0x4a, 0x63,
|
|
0x01,
|
|
// (AUTH_LOGOUT) cid=1
|
|
0x01,
|
|
0x40, // FINISH
|
|
};
|
|
m_TH.RecordAuthInitial(0, AUTHED_ADMIN, "default_admin");
|
|
m_TH.RecordAuthLogin(1, AUTHED_MOD, "foobar");
|
|
m_TH.RecordAuthLogin(2, AUTHED_HELPER, "help");
|
|
m_TH.RecordAuthLogout(1);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, JoinLeave)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=1899a382-71e3-36da-937d-c9de6bb95b1d data_len=1
|
|
0x4a,
|
|
0x18, 0x99, 0xa3, 0x82, 0x71, 0xe3, 0x36, 0xda,
|
|
0x93, 0x7d, 0xc9, 0xde, 0x6b, 0xb9, 0x5b, 0x1d,
|
|
0x01,
|
|
// (JOINVER6) cid=6
|
|
0x06,
|
|
// JOIN cid=7
|
|
0x47, 0x06,
|
|
// EX uuid=59239b05-0540-318d-bea4-9aa1e80e7d2b data_len=1
|
|
0x4a,
|
|
0x59, 0x23, 0x9b, 0x05, 0x05, 0x40, 0x31, 0x8d,
|
|
0xbe, 0xa4, 0x9a, 0xa1, 0xe8, 0x0e, 0x7d, 0x2b,
|
|
0x01,
|
|
// (JOINVER7) cid=7
|
|
0x07,
|
|
// JOIN cid=7
|
|
0x47, 0x07,
|
|
// LEAVE cid=6 reason="too many pancakes"
|
|
0x48, 0x06, 't', 'o', 'o', ' ', 'm', 'a',
|
|
'n', 'y', ' ', 'p', 'a', 'n', 'c', 'a',
|
|
'k', 'e', 's', 0x00,
|
|
0x40, // FINISH
|
|
};
|
|
m_TH.RecordPlayerJoin(6, CTeeHistorian::PROTOCOL_6);
|
|
m_TH.RecordPlayerJoin(7, CTeeHistorian::PROTOCOL_7);
|
|
m_TH.RecordPlayerDrop(6, "too many pancakes");
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, Input)
|
|
{
|
|
CNetObj_PlayerInput Input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
|
const unsigned char EXPECTED[] = {
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// new player -> InputNew
|
|
0x45,
|
|
0x00, // ClientID 0
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
|
|
// same unique id, same input -> nothing
|
|
// same unique id, different input -> InputDiff
|
|
0x44,
|
|
0x00, // ClientID 0
|
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
// different unique id, same input -> InputNew
|
|
0x45,
|
|
0x00, // ClientID 0
|
|
0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
|
|
// FINISH
|
|
0x40};
|
|
|
|
Tick(1);
|
|
|
|
// new player -> InputNew
|
|
m_TH.RecordPlayerInput(0, 1, &Input);
|
|
// same unique id, same input -> nothing
|
|
m_TH.RecordPlayerInput(0, 1, &Input);
|
|
|
|
Input.m_Direction = 0;
|
|
|
|
// same unique id, different input -> InputDiff
|
|
m_TH.RecordPlayerInput(0, 1, &Input);
|
|
|
|
// different unique id, same input -> InputNew
|
|
m_TH.RecordPlayerInput(0, 2, &Input);
|
|
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, SaveSuccess)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=4560c756-da29-3036-81d4-90a50f0182cd datalen=42
|
|
0x4a,
|
|
0x45, 0x60, 0xc7, 0x56, 0xda, 0x29, 0x30, 0x36,
|
|
0x81, 0xd4, 0x90, 0xa5, 0x0f, 0x01, 0x82, 0xcd,
|
|
0x1a,
|
|
// team=21
|
|
0x15,
|
|
// save_id
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b,
|
|
// team_save
|
|
'2', '\t', 'H', '.', '\n', 'l', 'l', '0', 0x00,
|
|
// FINISH
|
|
0x40};
|
|
|
|
CUuid SaveID = {
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b};
|
|
const char *pTeamSave = "2\tH.\nll0";
|
|
m_TH.RecordTeamSaveSuccess(21, SaveID, pTeamSave);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, SaveFailed)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=b29901d5-1244-3bd0-bbde-23d04b1f7ba9 datalen=42
|
|
0x4a,
|
|
0xb2, 0x99, 0x01, 0xd5, 0x12, 0x44, 0x3b, 0xd0,
|
|
0xbb, 0xde, 0x23, 0xd0, 0x4b, 0x1f, 0x7b, 0xa9,
|
|
0x01,
|
|
// team=12
|
|
0x0c,
|
|
0x40};
|
|
|
|
m_TH.RecordTeamSaveFailure(12);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, LoadSuccess)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=e05408d3-a313-33df-9eb3-ddb990ab954a datalen=42
|
|
0x4a,
|
|
0xe0, 0x54, 0x08, 0xd3, 0xa3, 0x13, 0x33, 0xdf,
|
|
0x9e, 0xb3, 0xdd, 0xb9, 0x90, 0xab, 0x95, 0x4a,
|
|
0x1a,
|
|
// team=21
|
|
0x15,
|
|
// save_id
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b,
|
|
// team_save
|
|
'2', '\t', 'H', '.', '\n', 'l', 'l', '0', 0x00,
|
|
// FINISH
|
|
0x40};
|
|
|
|
CUuid SaveID = {
|
|
0xfb, 0x13, 0xa5, 0x76, 0xd3, 0x5f, 0x48, 0x93,
|
|
0xb8, 0x15, 0xee, 0xdc, 0x6d, 0x98, 0x01, 0x5b};
|
|
const char *pTeamSave = "2\tH.\nll0";
|
|
m_TH.RecordTeamLoadSuccess(21, SaveID, pTeamSave);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, LoadFailed)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=ef8905a2-c695-3591-a1cd-53d2015992dd datalen=42
|
|
0x4a,
|
|
0xef, 0x89, 0x05, 0xa2, 0xc6, 0x95, 0x35, 0x91,
|
|
0xa1, 0xcd, 0x53, 0xd2, 0x01, 0x59, 0x92, 0xdd,
|
|
0x01,
|
|
// team=12
|
|
0x0c,
|
|
0x40};
|
|
|
|
m_TH.RecordTeamLoadFailure(12);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, PlayerSwap)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=5de9b633-49cf-3e99-9a25-d4a78e9717d7 datalen=2
|
|
0x4a,
|
|
0x5d, 0xe9, 0xb6, 0x33, 0x49, 0xcf, 0x3e, 0x99,
|
|
0x9a, 0x25, 0xd4, 0xa7, 0x8e, 0x97, 0x17, 0xd7,
|
|
0x02,
|
|
// playerId1=11
|
|
0x0b,
|
|
// playerId2=21
|
|
0x15,
|
|
// FINISH
|
|
0x40};
|
|
Tick(1);
|
|
m_TH.RecordPlayerSwap(11, 21);
|
|
Finish();
|
|
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, PlayerTeam)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=a111c04e-1ea8-38e0-90b1-d7f993ca0da9 datalen=2
|
|
0x4a,
|
|
0xa1, 0x11, 0xc0, 0x4e, 0x1e, 0xa8, 0x38, 0xe0,
|
|
0x90, 0xb1, 0xd7, 0xf9, 0x93, 0xca, 0x0d, 0xa9,
|
|
0x02,
|
|
// (PLAYER_TEAM) cid=33 team=54
|
|
0x21, 0x36,
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=a111c04e-1ea8-38e0-90b1-d7f993ca0da9 datalen=2
|
|
0x4a,
|
|
0xa1, 0x11, 0xc0, 0x4e, 0x1e, 0xa8, 0x38, 0xe0,
|
|
0x90, 0xb1, 0xd7, 0xf9, 0x93, 0xca, 0x0d, 0xa9,
|
|
0x02,
|
|
// (PLAYER_TEAM) cid=3 team=12
|
|
0x03, 0x0c,
|
|
// EX uuid=a111c04e-1ea8-38e0-90b1-d7f993ca0da9 datalen=2
|
|
0x4a,
|
|
0xa1, 0x11, 0xc0, 0x4e, 0x1e, 0xa8, 0x38, 0xe0,
|
|
0x90, 0xb1, 0xd7, 0xf9, 0x93, 0xca, 0x0d, 0xa9,
|
|
0x02,
|
|
// (PLAYER_TEAM) cid=33 team=0
|
|
0x21, 0x00,
|
|
// FINISH
|
|
0x40};
|
|
|
|
Tick(1);
|
|
m_TH.RecordPlayerTeam(3, 0);
|
|
m_TH.RecordPlayerTeam(33, 54);
|
|
m_TH.RecordPlayerTeam(45, 0);
|
|
Tick(2);
|
|
m_TH.RecordPlayerTeam(3, 12);
|
|
m_TH.RecordPlayerTeam(33, 0);
|
|
m_TH.RecordPlayerTeam(45, 0);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, TeamPractice)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=5792834e-81d1-34c9-a29b-b5ff25dac3bc datalen=2
|
|
0x4a,
|
|
0x57, 0x92, 0x83, 0x4e, 0x81, 0xd1, 0x34, 0xc9,
|
|
0xa2, 0x9b, 0xb5, 0xff, 0x25, 0xda, 0xc3, 0xbc,
|
|
0x02,
|
|
// (TEAM_PRACTICE) team=23 practice=1
|
|
0x17, 0x01,
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=5792834e-81d1-34c9-a29b-b5ff25dac3bc datalen=2
|
|
0x4a,
|
|
0x57, 0x92, 0x83, 0x4e, 0x81, 0xd1, 0x34, 0xc9,
|
|
0xa2, 0x9b, 0xb5, 0xff, 0x25, 0xda, 0xc3, 0xbc,
|
|
0x02,
|
|
// (TEAM_PRACTICE) team=1 practice=1
|
|
0x01, 0x01,
|
|
// EX uuid=5792834e-81d1-34c9-a29b-b5ff25dac3bc datalen=2
|
|
0x4a,
|
|
0x57, 0x92, 0x83, 0x4e, 0x81, 0xd1, 0x34, 0xc9,
|
|
0xa2, 0x9b, 0xb5, 0xff, 0x25, 0xda, 0xc3, 0xbc,
|
|
0x02,
|
|
// (TEAM_PRACTICE) team=23 practice=0
|
|
0x17, 0x00,
|
|
// FINISH
|
|
0x40};
|
|
|
|
Tick(1);
|
|
m_TH.RecordTeamPractice(1, false);
|
|
m_TH.RecordTeamPractice(16, false);
|
|
m_TH.RecordTeamPractice(23, true);
|
|
Tick(2);
|
|
m_TH.RecordTeamPractice(1, true);
|
|
m_TH.RecordTeamPractice(16, false);
|
|
m_TH.RecordTeamPractice(23, false);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, PlayerReady)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// EX uuid=638587c9-3f75-3887-918e-a3c2614ffaa0 datalen=1
|
|
0x4a,
|
|
0x63, 0x85, 0x87, 0xc9, 0x3f, 0x75, 0x38, 0x87,
|
|
0x91, 0x8e, 0xa3, 0xc2, 0x61, 0x4f, 0xfa, 0xa0,
|
|
0x01,
|
|
// (PLAYER_READY) cid=1
|
|
0x3f,
|
|
// FINISH
|
|
0x40};
|
|
|
|
m_TH.RecordPlayerReady(63);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|
|
|
|
TEST_F(TeeHistorian, PlayerReadyMultiple)
|
|
{
|
|
const unsigned char EXPECTED[] = {
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=638587c9-3f75-3887-918e-a3c2614ffaa0 datalen=1
|
|
0x4a,
|
|
0x63, 0x85, 0x87, 0xc9, 0x3f, 0x75, 0x38, 0x87,
|
|
0x91, 0x8e, 0xa3, 0xc2, 0x61, 0x4f, 0xfa, 0xa0,
|
|
0x01,
|
|
// (PLAYER_READY) cid=0
|
|
0x00,
|
|
// EX uuid=638587c9-3f75-3887-918e-a3c2614ffaa0 datalen=1
|
|
0x4a,
|
|
0x63, 0x85, 0x87, 0xc9, 0x3f, 0x75, 0x38, 0x87,
|
|
0x91, 0x8e, 0xa3, 0xc2, 0x61, 0x4f, 0xfa, 0xa0,
|
|
0x01,
|
|
// (PLAYER_READY) cid=11
|
|
0x0b,
|
|
// TICK_SKIP dt=0
|
|
0x41, 0x00,
|
|
// EX uuid=638587c9-3f75-3887-918e-a3c2614ffaa0 datalen=1
|
|
0x4a,
|
|
0x63, 0x85, 0x87, 0xc9, 0x3f, 0x75, 0x38, 0x87,
|
|
0x91, 0x8e, 0xa3, 0xc2, 0x61, 0x4f, 0xfa, 0xa0,
|
|
0x01,
|
|
// (PLAYER_READY) cid=63
|
|
0x3f,
|
|
0x40};
|
|
|
|
Tick(1);
|
|
m_TH.RecordPlayerReady(0);
|
|
m_TH.RecordPlayerReady(11);
|
|
Tick(2);
|
|
m_TH.RecordPlayerReady(63);
|
|
Finish();
|
|
Expect(EXPECTED, sizeof(EXPECTED));
|
|
}
|