Commit ff723d30 authored by John Selbie's avatar John Selbie

latest changes

parent 26b1e70d
include ../common.inc
PROJECT_TARGET := stuntestcode
PROJECT_OBJS := testbuilder.o testclientlogic.o testcmdline.o testcode.o testdatastream.o testfasthash.o testintegrity.o testmessagehandler.o testreader.o testrecvfromex.o
PROJECT_OBJS := testbuilder.o testclientlogic.o testcmdline.o testcode.o testdatastream.o testfasthash.o testintegrity.o testmessagehandler.o testpolling.o testreader.o testrecvfromex.o
INCLUDES := $(BOOST_INCLUDE) $(OPENSSL_INCLUDE) -I../common -I../stuncore -I../networkutils
LIB_PATH := -L../networkutils -L../stuncore -L../common
......
z=0
while [ 1 ]
do
nc $1 $2 < packet.bin > /dev/null
let z=$z+1
echo $z
done
z=0
echo "start"
while [ 1 ]
do
../stunclient localhost 3478 > /dev/null
let z=$z+1
echo $z
done
#include "commonincludes.h"
#include "unittest.h"
#include "polling.h"
#include "testpolling.h"
CTestPolling::CTestPolling()
{
;
}
CTestPolling::~CTestPolling()
{
TestUnInit();
}
HRESULT CTestPolling::Run()
{
HRESULT hr = S_OK;
#ifdef HAS_EPOLL
_polltype = IPOLLING_TYPE_EPOLL;
ChkA(Test1());
ChkA(Test2());
#endif
_polltype = IPOLLING_TYPE_POLL;
ChkA(Test1());
ChkA(Test2());
Cleanup:
return hr;
}
void CTestPolling::TestUnInit()
{
size_t size = _pipes.size();
_spPolling.ReleaseAndClear();
for (size_t index = 0; index < size; index++)
{
close(_pipes[index].readpipe);
close(_pipes[index].writepipe);
}
_pipes.clear();
}
HRESULT CTestPolling::SetNonBlocking(int fd)
{
HRESULT hr = S_OK;
int result;
int flags;
flags = ::fcntl(fd, F_GETFL, 0);
ChkIfA(flags == -1, ERRNOHR);
flags |= O_NONBLOCK;
result = fcntl(fd , F_SETFL , flags);
ChkIfA(result == -1, ERRNOHR);
Cleanup:
return hr;
}
HRESULT CTestPolling::CreateAndAddPipe()
{
HRESULT hr = S_OK;
PipePair pp = {};
int ret = -1;
int fds[2];
ret = ::pipe(fds);
ChkIfA(ret == -1, ERRNOHR);
pp.readpipe = fds[0];
pp.writepipe = fds[1];
pp.fDataPending = false;
ChkA(SetNonBlocking(pp.readpipe));
ChkA(SetNonBlocking(pp.writepipe));
_pipes.push_back(pp);
ChkA(_spPolling->Add(fds[0], IPOLLING_READ));
Cleanup:
return hr;
}
HRESULT CTestPolling::TestInit(size_t sizePolling, size_t sizePipeArray)
{
HRESULT hr = S_OK;
TestUnInit();
ChkA(CreatePollingInstance(_polltype, sizePolling, _spPolling.GetPointerPointer()));
for (size_t index = 0; index < sizePipeArray; index++)
{
ChkA(CreateAndAddPipe());
}
Cleanup:
return hr;
}
HRESULT CTestPolling::WritePipe(PipePair* pPair)
{
HRESULT hr = S_OK;
char ch = 'x';
int ret = -1;
ret = write(pPair->writepipe, &ch, 1);
ChkIfA(ret < 0, ERRNOHR);
ChkIfA(ret == 0, E_UNEXPECTED);
pPair->fDataPending = true;
Cleanup:
return hr;
}
HRESULT CTestPolling::ConsumeEvent(int* pFD, int* pCount)
{
HRESULT hr = S_OK;
HRESULT hrResult = S_OK;
PollEvent event;
char ch;
int result;
int count = 0;
int fd = -1;
int pipesindex = -1;
hrResult = _spPolling->WaitForNextEvent(&event, 0);
ChkA(hrResult);
ChkIfA(hrResult == S_FALSE, S_FALSE);
fd = event.fd;
while (true)
{
result = ::read(fd, &ch, 1);
if (result <= 0)
{
break;
}
count++;
}
pipesindex = FindPipePairIndex(fd);
ChkIfA(pipesindex == -1, E_UNEXPECTED);
ChkIfA(count == 0, E_UNEXPECTED);
ChkIfA(_pipes[pipesindex].fDataPending == false, E_UNEXPECTED);
_pipes[pipesindex].fDataPending = false;
Cleanup:
if (pFD)
{
*pFD = fd;
}
if (pCount)
{
*pCount = count;
}
return hr;
}
int CTestPolling::FindPipePairIndex(int fd)
{
size_t size = _pipes.size();
for (size_t index = 0; index < size; index++)
{
if ((_pipes[index].readpipe == fd) || (_pipes[index].writepipe == fd))
{
return index;
}
}
return -1;
}
size_t CTestPolling::GetPendingCount()
{
size_t size = _pipes.size();
size_t count = 0;
for (size_t index = 0; index < size; index++)
{
if (_pipes[index].fDataPending)
{
count++;
}
}
return count;
}
HRESULT CTestPolling::RemovePipe(int pipeindex)
{
HRESULT hr = S_OK;
size_t size = _pipes.size();
ChkIfA(pipeindex < 0, E_FAIL);
ChkIfA(pipeindex >= (int)size, E_FAIL);
ChkA(_spPolling->Remove(_pipes[pipeindex].readpipe));
_pipes.erase(_pipes.begin()+pipeindex);
Cleanup:
return hr;
}
// simplest of all tests. Just set a file descriptor and see that it's available
// repeat many times
HRESULT CTestPolling::Test1()
{
HRESULT hr = S_OK;
HRESULT hrResult;
size_t size;
PollEvent event;
int fd;
int count = 0;
srand(100);
ChkA(TestInit(10, 10));
size = _pipes.size();
hrResult = _spPolling->WaitForNextEvent(&event, 0);
ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
// one event at a time model
for (int index = 0; index < 100; index++)
{
size_t item = rand() % size;
ChkA(WritePipe(&_pipes[item]));
ConsumeEvent(&fd, &count);
ChkIfA(fd != _pipes[item].readpipe, E_UNEXPECTED);
ChkIfA(count != 1, E_UNEXPECTED);
}
hrResult = _spPolling->WaitForNextEvent(&event, 0);
ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
Cleanup:
return hr;
}
// create a polling set
HRESULT CTestPolling::Test2()
{
// simulate the following events in random order:
// socket added (did it succeed as expected)
// incoming data (write to a random pipe)
// WaitForNextEvent called (did it return an expected result/socket)
// Remove socket last notified about
HRESULT hr = S_OK;
HRESULT hrResult;
PollEvent event;
const size_t c_maxSockets = 10;
srand(100);
ChkA(TestInit(c_maxSockets, 0));
hrResult = _spPolling->WaitForNextEvent(&event, 0);
ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
for (size_t index = 0; index < 1000; index++)
{
int randresult = ::rand() % 4;
switch (randresult)
{
case 0:
{
// simulate a new socket being added
if (_pipes.size() >= c_maxSockets)
{
continue;
}
ChkA(CreateAndAddPipe());
break;
}
case 1:
{
// simulate incoming data
size_t size = _pipes.size();
size_t itemindex;
if (size == 0)
{
continue;
}
itemindex = rand() % size;
ChkA(WritePipe(&_pipes[itemindex]));
break;
}
case 2:
case 3:
{
int fd;
size_t pending = GetPendingCount();
if (pending == 0)
{
continue;
}
ChkA(ConsumeEvent(&fd, NULL));
if (randresult == 3)
{
// simulate removing this pipe from the set
ChkA(RemovePipe(FindPipePairIndex(fd)));
}
break;
} // case
} // switch
} // for
Cleanup:
return hr;
}
#ifndef TEST_POLLING_H
#define TEST_POLLING_H
struct PipePair
{
int readpipe;
int writepipe;
bool fDataPending;
};
class CTestPolling : public IUnitTest
{
public:
CRefCountedPtr<IPolling> _spPolling;
std::vector<PipePair> _pipes;
uint32_t _polltype;
void TestUnInit();
HRESULT TestInit(size_t sizePolling, size_t sizePipeArray); // creates pipes and polling mechanism;
HRESULT CreateAndAddPipe();
HRESULT WritePipe(PipePair* pPipePair);
HRESULT SetNonBlocking(int fd);
HRESULT ConsumeEvent(int* pFD, int* pCount); // returns file descriptor of what was last handled
int FindPipePairIndex(int fd);
size_t GetPendingCount();
HRESULT RemovePipe(int pipeindex);
HRESULT Test1();
HRESULT Test2();
HRESULT Run();
CTestPolling();
~CTestPolling();
UT_DECLARE_TEST_NAME("CTestPolling");
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment