192 lines
5 KiB
C
192 lines
5 KiB
C
|
#ifndef UT_NET_LAYER3
|
||
|
#define UT_NET_LAYER3
|
||
|
|
||
|
#include <nel/net/callback_client.h>
|
||
|
#include <nel/net/callback_server.h>
|
||
|
|
||
|
uint16 TestPort1 = 56000;
|
||
|
|
||
|
uint NbTestReceived = 0;
|
||
|
|
||
|
CMessage msgoutExpectingAnswer0, msgoutSimple0, msgoutSimple50;
|
||
|
|
||
|
// Data structure for messages
|
||
|
struct TData
|
||
|
{
|
||
|
string PayloadString;
|
||
|
bool ExpectingAnswer;
|
||
|
|
||
|
// Constructor
|
||
|
TData() : ExpectingAnswer(false) {}
|
||
|
|
||
|
// Serial
|
||
|
void serial( NLMISC::IStream& s )
|
||
|
{
|
||
|
s.serial( PayloadString );
|
||
|
s.serial( ExpectingAnswer );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// This callback must not take more than 10 ms
|
||
|
void cbTest( CMessage &msgin, TSockId from, CCallbackNetBase &netbase )
|
||
|
{
|
||
|
TTime before = CTime::getLocalTime();
|
||
|
|
||
|
// Read data from the message
|
||
|
TData data;
|
||
|
msgin.serial( data );
|
||
|
if ( data.PayloadString == "Payload" )
|
||
|
++NbTestReceived;
|
||
|
|
||
|
// Send the answer if required
|
||
|
if ( data.ExpectingAnswer )
|
||
|
netbase.send( msgoutSimple0, from );
|
||
|
|
||
|
// Check that the duration is compatible with our timeout tests
|
||
|
TTime maxDuration;
|
||
|
if ( msgin.getName() == "TEST_50" )
|
||
|
{
|
||
|
while ( CTime::getLocalTime() - before < 49 ); // wait
|
||
|
maxDuration = 70;
|
||
|
}
|
||
|
else
|
||
|
maxDuration = 10;
|
||
|
TTime actualDuration = CTime::getLocalTime() - before;
|
||
|
if ( actualDuration > maxDuration )
|
||
|
nlerror( "The callback cbTest takes too long (%u) for %s, please fix the test", (uint)actualDuration, msgin.getName().c_str() );
|
||
|
}
|
||
|
|
||
|
|
||
|
static TCallbackItem CallbackArray[] =
|
||
|
{
|
||
|
{ "TEST_0", cbTest },
|
||
|
{ "TEST_50", cbTest }
|
||
|
};
|
||
|
|
||
|
|
||
|
// Test suite for layer 3
|
||
|
class CUTNetLayer3: public Test::Suite
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
//
|
||
|
CUTNetLayer3 ()
|
||
|
{
|
||
|
_Server = NULL;
|
||
|
_Client = NULL;
|
||
|
TEST_ADD(CUTNetLayer3::sendReceiveUpdate);
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
~CUTNetLayer3 ()
|
||
|
{
|
||
|
if ( _Server )
|
||
|
delete _Server;
|
||
|
_Server = NULL;
|
||
|
if ( _Client )
|
||
|
delete _Client;
|
||
|
_Client = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
void sendReceiveUpdate()
|
||
|
{
|
||
|
// Prepare messages for tests
|
||
|
TData data;
|
||
|
data.PayloadString = "Payload";
|
||
|
data.ExpectingAnswer = true;
|
||
|
msgoutExpectingAnswer0.clear(); // optional
|
||
|
msgoutExpectingAnswer0.setType( "TEST_0" ); // could be passed to the constructor
|
||
|
msgoutExpectingAnswer0.serial( data );
|
||
|
data.ExpectingAnswer = false;
|
||
|
msgoutSimple0.clear(); // optional
|
||
|
msgoutSimple0.setType( "TEST_0" ); // could be passed to the constructor
|
||
|
msgoutSimple0.serial( data );
|
||
|
msgoutSimple50.clear(); // optional
|
||
|
msgoutSimple50.setType( "TEST_50" ); // could be passed to the constructor
|
||
|
msgoutSimple50.serial( data );
|
||
|
|
||
|
// Init connections
|
||
|
_Server = new CCallbackServer();
|
||
|
_Server->init( TestPort1 );
|
||
|
_Server->addCallbackArray( CallbackArray, sizeof(CallbackArray)/sizeof(TCallbackItem) );
|
||
|
_Client = new CCallbackClient();
|
||
|
_Client->connect( CInetAddress( "localhost", TestPort1 ) );
|
||
|
_Client->addCallbackArray( CallbackArray, sizeof(CallbackArray)/sizeof(TCallbackItem) );
|
||
|
|
||
|
// TEST: Simple message transmission
|
||
|
NbTestReceived = 0;
|
||
|
_Client->send( msgoutExpectingAnswer0 );
|
||
|
for ( uint i=0; i!=10; ++i ) // give some time to receive
|
||
|
{
|
||
|
_Client->update();
|
||
|
_Server->update(); // legacy version
|
||
|
nlSleep( 50 );
|
||
|
}
|
||
|
TEST_ASSERT( NbTestReceived == 2 ); // answer and reply
|
||
|
|
||
|
// TEST: ONE-SHOT update mode on the receiver
|
||
|
NbTestReceived = 0;
|
||
|
for ( uint i=0; i!=20; ++i ) // send 20 messages
|
||
|
_Client->send( msgoutSimple0 );
|
||
|
while ( NbTestReceived < 20 )
|
||
|
{
|
||
|
_Client->update2();
|
||
|
uint prevNbTestReceived = NbTestReceived;
|
||
|
_Server->update2( 0 ); // shortest time-out = ONE-SHOT mode
|
||
|
TEST_ASSERT( (NbTestReceived == prevNbTestReceived) ||
|
||
|
(NbTestReceived == prevNbTestReceived + 1) );
|
||
|
nlSleep( 10 );
|
||
|
}
|
||
|
|
||
|
// TEST: GREEDY update mode on the receiver
|
||
|
NbTestReceived = 0;
|
||
|
for ( uint i=0; i!=20; ++i ) // send 20 messages
|
||
|
_Client->send( msgoutSimple0 );
|
||
|
for ( uint i=0; i!=10; ++i ) // make sure all messages are flushed
|
||
|
{
|
||
|
_Client->update2();
|
||
|
nlSleep( 10 );
|
||
|
}
|
||
|
_Server->update2( -1 ); // receive all
|
||
|
TEST_ASSERT( NbTestReceived == 20 );
|
||
|
|
||
|
// TEST: CONSTRAINED update mode on the receiver
|
||
|
NbTestReceived = 0;
|
||
|
for ( uint i=0; i!=20; ++i ) // send 20 messages that will trigger a time-consuming callback
|
||
|
_Client->send( msgoutSimple50 );
|
||
|
for ( uint i=0; i!=10; ++i ) // make sure all messages are flushed
|
||
|
{
|
||
|
_Client->update2();
|
||
|
nlSleep( 10 );
|
||
|
}
|
||
|
while ( NbTestReceived < 20 )
|
||
|
{
|
||
|
uint prevNbTestReceived = NbTestReceived;
|
||
|
_Server->update2( 80 ); // no more time than two callback executions
|
||
|
TEST_ASSERT( NbTestReceived <= prevNbTestReceived + 2 );
|
||
|
}
|
||
|
|
||
|
// TEST: CONSTRAINED with minTime update mode on the receiver
|
||
|
NbTestReceived = 0;
|
||
|
while ( NbTestReceived < 20 )
|
||
|
{
|
||
|
_Client->send( msgoutSimple0 );
|
||
|
_Client->send( msgoutSimple0 ); // send 2 messages at a time
|
||
|
_Client->update2();
|
||
|
TTime before = CTime::getLocalTime();
|
||
|
_Server->update2( -1, 30 );
|
||
|
TTime duration = CTime::getLocalTime() - before;
|
||
|
TEST_ASSERT( duration >= 30 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
CCallbackServer *_Server;
|
||
|
CCallbackClient *_Client;
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif
|