205 lines
6.3 KiB
C++
205 lines
6.3 KiB
C++
// Copyright (C) 2008 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
#include "tester.h"
|
|
#include <dlib/sockets.h>
|
|
#include <dlib/threads.h>
|
|
#include <dlib/array.h>
|
|
|
|
// This is called an unnamed-namespace and it has the effect of making everything
|
|
// inside this file "private" so that everything you declare will have static linkage.
|
|
// Thus we won't have any multiply defined symbol errors coming out of the linker when
|
|
// we try to compile the test suite.
|
|
namespace
|
|
{
|
|
using namespace test;
|
|
using namespace dlib;
|
|
using namespace std;
|
|
// Declare the logger we will use in this test. The name of the logger
|
|
// should start with "test."
|
|
dlib::logger dlog("test.sockets2");
|
|
|
|
|
|
class sockets2_tester : public tester, private multithreaded_object
|
|
{
|
|
/*!
|
|
WHAT THIS OBJECT REPRESENTS
|
|
This object represents a unit test. When it is constructed
|
|
it adds itself into the testing framework.
|
|
!*/
|
|
|
|
short port_num;
|
|
string data_to_send;
|
|
|
|
bool test_failed;
|
|
|
|
void write_thread (
|
|
)
|
|
{
|
|
try
|
|
{
|
|
std::unique_ptr<connection> con(connect("127.0.0.1", port_num));
|
|
|
|
// Send a copy of the data down the connection so we can test our the read() function
|
|
// that uses timeouts in the main thread.
|
|
if (con->write(data_to_send.data(), data_to_send.size()) != (int)data_to_send.size())
|
|
{
|
|
test_failed = true;
|
|
dlog << LERROR << "failed to send all the data down the connection";
|
|
}
|
|
|
|
close_gracefully(con,300000);
|
|
}
|
|
catch (exception& e)
|
|
{
|
|
test_failed = true;
|
|
dlog << LERROR << e.what();
|
|
}
|
|
}
|
|
|
|
void no_write_thread (
|
|
)
|
|
{
|
|
try
|
|
{
|
|
std::unique_ptr<connection> con(connect("127.0.0.1", port_num));
|
|
|
|
// just do nothing until the connection closes
|
|
char ch;
|
|
con->read(&ch, 1);
|
|
dlog << LDEBUG << "silent connection finally closing";
|
|
}
|
|
catch (exception& e)
|
|
{
|
|
test_failed = true;
|
|
dlog << LERROR << e.what();
|
|
}
|
|
}
|
|
|
|
public:
|
|
sockets2_tester (
|
|
) :
|
|
tester (
|
|
"test_sockets2", // the command line argument name for this test
|
|
"Run sockets2 tests.", // the command line argument description
|
|
0 // the number of command line arguments for this test
|
|
)
|
|
{
|
|
register_thread(*this, &sockets2_tester::write_thread);
|
|
register_thread(*this, &sockets2_tester::write_thread);
|
|
register_thread(*this, &sockets2_tester::write_thread);
|
|
register_thread(*this, &sockets2_tester::write_thread);
|
|
register_thread(*this, &sockets2_tester::write_thread);
|
|
register_thread(*this, &sockets2_tester::no_write_thread);
|
|
}
|
|
|
|
void perform_test (
|
|
)
|
|
{
|
|
run_tests(0);
|
|
run_tests(40);
|
|
}
|
|
|
|
void run_tests (
|
|
unsigned long timeout_to_use
|
|
)
|
|
{
|
|
// make sure there aren't any threads running
|
|
wait();
|
|
|
|
port_num = 5000;
|
|
test_failed = false;
|
|
|
|
print_spinner();
|
|
data_to_send = "oi 2m3ormao2m fo2im3fo23mi o2mi3 foa2m3fao23ifm2o3fmia23oima23iom3giugbiua";
|
|
// make the block of data much larger
|
|
for (int i = 0; i < 11; ++i)
|
|
data_to_send = data_to_send + data_to_send;
|
|
|
|
dlog << LINFO << "data block size: " << data_to_send.size();
|
|
|
|
|
|
std::unique_ptr<listener> list;
|
|
DLIB_TEST(create_listener(list, port_num, "127.0.0.1") == 0);
|
|
DLIB_TEST(bool(list));
|
|
|
|
// kick off the sending threads
|
|
start();
|
|
|
|
|
|
dlib::array<std::unique_ptr<connection> > cons;
|
|
std::vector<long> bytes_received(6,0);
|
|
std::unique_ptr<connection> con_temp;
|
|
|
|
// accept the 6 connections we should get
|
|
for (int i = 0; i < 6; ++i)
|
|
{
|
|
DLIB_TEST(list->accept(con_temp) == 0);
|
|
cons.push_back(con_temp);
|
|
print_spinner();
|
|
}
|
|
|
|
int finished_cons = 0;
|
|
|
|
// now receive all the bytes from the sending threads
|
|
while (finished_cons < 5)
|
|
{
|
|
for (unsigned long i = 0; i < cons.size(); ++i)
|
|
{
|
|
if (cons[i])
|
|
{
|
|
const int buf_size = 3000;
|
|
char buf[buf_size];
|
|
|
|
int status = cons[i]->read(buf, buf_size, timeout_to_use);
|
|
|
|
if (status > 0)
|
|
{
|
|
DLIB_TEST(equal(buf, buf+status, data_to_send.begin()+bytes_received[i]));
|
|
bytes_received[i] += status;
|
|
}
|
|
else if (status == 0)
|
|
{
|
|
// the connection is closed to kill it
|
|
cons[i].reset();
|
|
++finished_cons;
|
|
}
|
|
}
|
|
}
|
|
print_spinner();
|
|
}
|
|
|
|
for (unsigned long i = 0; i < bytes_received.size(); ++i)
|
|
{
|
|
DLIB_TEST(bytes_received[i] == (long)data_to_send.size() || cons[i]);
|
|
}
|
|
|
|
|
|
dlog << LINFO << "All data received correctly";
|
|
|
|
cons.clear();
|
|
|
|
|
|
print_spinner();
|
|
|
|
DLIB_TEST(test_failed == false);
|
|
|
|
|
|
// wait for all the sending threads to terminate
|
|
wait();
|
|
}
|
|
};
|
|
|
|
// Create an instance of this object. Doing this causes this test
|
|
// to be automatically inserted into the testing framework whenever this cpp file
|
|
// is linked into the project. Note that since we are inside an unnamed-namespace
|
|
// we won't get any linker errors about the symbol a being defined multiple times.
|
|
sockets2_tester a;
|
|
|
|
}
|
|
|
|
|