mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-11 14:42:05 +08:00
engine: client: add simple test for titles.txt parser
This commit is contained in:
@@ -583,7 +583,7 @@ static void CL_InitTitles( const char *filename )
|
||||
pMemFile = FS_LoadFile( filename, &fileSize, false );
|
||||
if( !pMemFile ) return;
|
||||
|
||||
CL_TextMessageParse( pMemFile, fileSize );
|
||||
clgame.titles = CL_TextMessageParse( clgame.mempool, pMemFile, fileSize, &clgame.numTitles );
|
||||
Mem_Free( pMemFile );
|
||||
}
|
||||
|
||||
|
||||
@@ -851,7 +851,7 @@ void CL_ClearWorld( void );
|
||||
void CL_DrawCenterPrint( void );
|
||||
void CL_ClearSpriteTextures( void );
|
||||
void CL_CenterPrint( const char *text, float y );
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
client_textmessage_t *CL_TextMessageParse( poolhandle_t mempool, byte *pMemFile, int fileSize, int *numTitles );
|
||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
model_t *CL_LoadClientSprite( const char *filename );
|
||||
|
||||
+109
-18
@@ -15,6 +15,7 @@ GNU General Public License for more details.
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define MAX_MESSAGES 2048
|
||||
|
||||
@@ -208,7 +209,7 @@ static int ParseDirective( const char *pText )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
client_textmessage_t *CL_TextMessageParse( poolhandle_t mempool, byte *pMemFile, int fileSize, int *numTitles )
|
||||
{
|
||||
char buf[512], trim[512], currentName[512];
|
||||
char *pCurrentText = NULL, *pNameHeap;
|
||||
@@ -251,7 +252,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
if( IsEndOfText( trim ))
|
||||
{
|
||||
Con_Reportf( "%s: unexpected '}' found, line %d\n", __func__, lineNumber );
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
Q_strncpy( currentName, trim, sizeof( currentName ));
|
||||
break;
|
||||
@@ -264,7 +265,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
if( lastNamePos + length > 32768 )
|
||||
{
|
||||
Con_Reportf( "%s: error while parsing!\n", __func__ );
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Q_strncpy( nameHeap + lastNamePos, currentName, sizeof( nameHeap ) - lastNamePos );
|
||||
@@ -287,7 +288,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
if( IsStartOfText( trim ))
|
||||
{
|
||||
Con_Reportf( "%s: unexpected '{' found, line %d\n", __func__, lineNumber );
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -312,22 +313,19 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
|
||||
if(( textHeapSize + nameHeapSize + messageSize ) <= 0 )
|
||||
{
|
||||
clgame.titles = NULL;
|
||||
clgame.numTitles = 0;
|
||||
return;
|
||||
*numTitles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// must malloc because we need to be able to clear it after initialization
|
||||
clgame.titles = (client_textmessage_t *)Mem_Calloc( cls.mempool, textHeapSize + nameHeapSize + messageSize );
|
||||
client_textmessage_t *out = Mem_Calloc( mempool, textHeapSize + nameHeapSize + messageSize );
|
||||
|
||||
// copy table over
|
||||
memcpy( clgame.titles, textMessages, messageSize );
|
||||
memcpy( out, textMessages, messageSize );
|
||||
|
||||
// copy Name heap
|
||||
pNameHeap = ((char *)clgame.titles) + messageSize;
|
||||
pNameHeap = ((char *)out) + messageSize;
|
||||
memcpy( pNameHeap, nameHeap, nameHeapSize );
|
||||
//nameOffset = pNameHeap - clgame.titles[0].pName; //undefined on amd64
|
||||
|
||||
|
||||
// copy text & fixup pointers
|
||||
textHeapSizeRemaining = textHeapSize;
|
||||
@@ -335,19 +333,112 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
|
||||
for( i = 0; i < messageCount; i++ )
|
||||
{
|
||||
size_t currentTextSize = Q_strlen( clgame.titles[i].pMessage ) + 1;
|
||||
size_t currentTextSize = Q_strlen( out[i].pMessage ) + 1;
|
||||
|
||||
clgame.titles[i].pName = pNameHeap; // adjust name pointer (parallel buffer)
|
||||
Q_strncpy( pCurrentText, clgame.titles[i].pMessage, textHeapSizeRemaining ); // copy text over
|
||||
clgame.titles[i].pMessage = pCurrentText;
|
||||
out[i].pName = pNameHeap; // adjust name pointer (parallel buffer)
|
||||
Q_strncpy( pCurrentText, out[i].pMessage, textHeapSizeRemaining ); // copy text over
|
||||
out[i].pMessage = pCurrentText;
|
||||
|
||||
pNameHeap += Q_strlen( pNameHeap ) + 1;
|
||||
pCurrentText += currentTextSize;
|
||||
textHeapSizeRemaining -= currentTextSize;
|
||||
}
|
||||
|
||||
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))
|
||||
if(( pCurrentText - (char *)out ) != ( textHeapSize + nameHeapSize + messageSize ))
|
||||
Con_DPrintf( S_ERROR "%s: overflow text message buffer!\n", __func__ );
|
||||
|
||||
clgame.numTitles = messageCount;
|
||||
*numTitles = messageCount;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
|
||||
void Test_RunTitles( void )
|
||||
{
|
||||
poolhandle_t mempool = Mem_AllocPool( __func__ );
|
||||
client_textmessage_t *tmessages;
|
||||
client_textmessage_t *null;
|
||||
int num_titles = 0, num_null_titles = 0;
|
||||
char titles[] =
|
||||
"// this is a comment\n"
|
||||
"$effect 2\n"
|
||||
"$color 1 2 3\n"
|
||||
"$color2 4 5 6\n"
|
||||
"$position 7 8\n"
|
||||
"$fadein 0.1\n"
|
||||
"$fadeout 0.5\n"
|
||||
"$holdtime 321\n"
|
||||
"$fxtime 123\n"
|
||||
"TITLE\n"
|
||||
"{\n"
|
||||
"Hello to anybody reading test data\n"
|
||||
"Hope you have a good time\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"TITLE2\n"
|
||||
"{\n"
|
||||
"Still reading that nonsense huh?\n"
|
||||
"}\n"
|
||||
"// let's override some things\n"
|
||||
"$cats are\n"
|
||||
"$cute\n"
|
||||
"$color 10 10 10\n"
|
||||
"$position -1 -1\n"
|
||||
"UwU\n"
|
||||
"{\n"
|
||||
"OwO\n"
|
||||
"}\n"
|
||||
"Technically titles can have spaces\n"
|
||||
"{\n"
|
||||
"Oh yeah!\n"
|
||||
"}\n";
|
||||
char broken_titles[] = "}\n";
|
||||
char broken_titles2[] = "{\n{\n";
|
||||
|
||||
null = CL_TextMessageParse( mempool, broken_titles, Q_strlen( broken_titles ), &num_null_titles );
|
||||
TASSERT_EQi( num_null_titles, 0 );
|
||||
TASSERT_EQp( null, NULL );
|
||||
|
||||
null = CL_TextMessageParse( mempool, broken_titles2, Q_strlen( broken_titles2 ), &num_null_titles );
|
||||
TASSERT_EQi( num_null_titles, 0 );
|
||||
TASSERT_EQp( null, NULL );
|
||||
|
||||
tmessages = CL_TextMessageParse( mempool, titles, Q_strlen( titles ), &num_titles );
|
||||
TASSERT_EQi( num_titles, 4 );
|
||||
TASSERT_NEQp( tmessages, NULL );
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
TASSERT_EQi( tmessages[i].effect, 2 );
|
||||
TASSERT_EQi( tmessages[i].r1, i >= 2 ? 10 : 1 );
|
||||
TASSERT_EQi( tmessages[i].g1, i >= 2 ? 10 : 2 );
|
||||
TASSERT_EQi( tmessages[i].b1, i >= 2 ? 10 : 3 );
|
||||
TASSERT_EQi( tmessages[i].a1, 0 );
|
||||
TASSERT_EQi( tmessages[i].r2, 4 );
|
||||
TASSERT_EQi( tmessages[i].g2, 5 );
|
||||
TASSERT_EQi( tmessages[i].b2, 6 );
|
||||
TASSERT_EQi( tmessages[i].a2, 0 );
|
||||
TASSERT_EQi( tmessages[i].x, i >= 2 ? -1 : 7 );
|
||||
TASSERT_EQi( tmessages[i].y, i >= 2 ? -1 : 8 );
|
||||
TASSERT_EQi( tmessages[i].fadein, 0.1f );
|
||||
TASSERT_EQi( tmessages[i].fadeout, 0.5f );
|
||||
TASSERT_EQi( tmessages[i].holdtime, 321.f );
|
||||
TASSERT_EQi( tmessages[i].fxtime, 123.f );
|
||||
}
|
||||
|
||||
TASSERT_STR( tmessages[0].pName, "TITLE" );
|
||||
TASSERT_STR( tmessages[1].pName, "TITLE2" );
|
||||
TASSERT_STR( tmessages[2].pName, "UwU" );
|
||||
TASSERT_STR( tmessages[3].pName, "Technically titles can have spaces" );
|
||||
|
||||
TASSERT_STR( tmessages[0].pMessage, "Hello to anybody reading test data\nHope you have a good time" );
|
||||
TASSERT_STR( tmessages[1].pMessage, "Still reading that nonsense huh?" );
|
||||
TASSERT_STR( tmessages[2].pMessage, "OwO" );
|
||||
TASSERT_STR( tmessages[3].pMessage, "Oh yeah!" );
|
||||
|
||||
Mem_Free( tmessages );
|
||||
Mem_FreePool( &mempool );
|
||||
}
|
||||
|
||||
#endif // XASH_ENGINE_TESTS
|
||||
|
||||
@@ -29,6 +29,8 @@ extern struct tests_stats_s tests_stats;
|
||||
_TASSERT( ( val1 ) != ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%d\" != \"%d\"\n", __FILE__, __LINE__, (int)val1, (int)val2 ))
|
||||
#define TASSERT_EQp( val1, val2 ) \
|
||||
_TASSERT( ( val1 ) != ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%p\" != \"%p\"\n", __FILE__, __LINE__, val1, val2 ))
|
||||
#define TASSERT_NEQp( val1, val2 ) \
|
||||
_TASSERT( ( val1 ) == ( val2 ), Msg( S_ERROR "assert failed at %s:%i, \"%p\" == \"%p\"\n", __FILE__, __LINE__, val1, val2 ))
|
||||
#define TASSERT_STR( str1, str2 ) \
|
||||
_TASSERT( Q_strcmp(( str1 ), ( str2 )), Msg( S_ERROR "assert failed at %s:%i, \"%s\" != \"%s\"\n", __FILE__, __LINE__, ( str1 ), ( str2 )))
|
||||
|
||||
@@ -44,6 +46,7 @@ void Test_RunGamma( void );
|
||||
void Test_RunDelta( void );
|
||||
void Test_RunBuffer( void );
|
||||
void Test_RunMunge( void );
|
||||
void Test_RunTitles( void );
|
||||
|
||||
#define TEST_LIST_0 \
|
||||
Test_RunLibCommon(); \
|
||||
@@ -63,7 +66,8 @@ void Test_RunMunge( void );
|
||||
Test_RunImagelib();
|
||||
|
||||
#define TEST_LIST_1_CLIENT \
|
||||
Test_RunVOX();
|
||||
Test_RunVOX(); \
|
||||
Test_RunTitles();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user