// Copyright (C) 2006 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <cstdlib> #include <ctime> #include <dlib/sockets.h> #include <dlib/server.h> #include <dlib/misc_api.h> #include "tester.h" namespace { using namespace test; using namespace dlib; using namespace std; dlib::mutex gm; dlib::signaler gs(gm); const char magic_num = 42; const int min_bytes_sent = 10000; int assigned_port; logger dlog("test.sockets"); // ---------------------------------------------------------------------------------------- class serv : public server::kernel_1a_c { public: serv ( ) : error_occurred (false), got_connections(false) {} void on_listening_port_assigned ( ) { auto_mutex M(gm); assigned_port = get_listening_port(); gs.broadcast(); } void on_connect ( connection& con ) { dlog << LINFO << "in serv::on_connect(): got new connection"; int status; int count = 0; char buf[100]; while ((status = con.read(buf,sizeof(buf))) > 0) { for (int i = 0; i < status; ++i) { if (buf[i] != magic_num) { tag = 4.0; error_occurred = true; } } count += status; } if (count != min_bytes_sent) { tag = 5.0; error_occurred = true; } got_connections = true; dlog << LINFO << "in serv::on_connect(): on_connect ending"; } bool error_occurred; bool got_connections; double tag; }; // ---------------------------------------------------------------------------------------- class thread_container : public multithreaded_object { public: serv& srv; thread_container ( serv& srv_ ) : srv(srv_) { for (int i = 0; i < 10; ++i) register_thread(*this, &thread_container::thread_proc); // start up the threads start(); } ~thread_container () { // wait for all threads to terminate wait(); } void thread_proc ( ) { try { dlog << LTRACE << "enter thread"; { auto_mutex M(gm); while (assigned_port == 0) gs.wait(); } int status; scoped_ptr<connection> con; string hostname; string ip; status = get_local_hostname(hostname); if (status) { srv.tag = 1.0; srv.error_occurred = true; srv.clear(); dlog << LERROR << "leaving thread, line: " << __LINE__; dlog << LERROR << "get_local_hostname() failed"; return; } status = hostname_to_ip(hostname,ip); if (status) { srv.tag = 2.0; srv.error_occurred = true; srv.clear(); dlog << LERROR << "leaving thread, line: " << __LINE__; dlog << LERROR << "hostname_to_ip() failed"; return; } dlog << LTRACE << "try to connect to the server at port " << srv.get_listening_port(); status = create_connection(con,srv.get_listening_port(),ip); if (status) { srv.tag = 3.0; srv.error_occurred = true; srv.clear(); dlog << LERROR << "leaving thread, line: " << __LINE__; dlog << LERROR << "create_connection() failed"; return; } dlog << LTRACE << "sending magic_num to server"; int i; for (i = 0; i < min_bytes_sent; ++i) { con->write(&magic_num,1); } dlog << LTRACE << "shutting down connection to server"; close_gracefully(con); dlog << LTRACE << "finished calling close_gracefully() on the connection"; } catch (exception& e) { srv.error_occurred = true; dlog << LERROR << "exception thrown in thread_proc(): " << e.what(); cout << "exception thrown in thread_proc(): " << e.what(); } dlog << LTRACE << "exit thread"; } }; void run_server(serv* srv) { dlog << LTRACE << "calling srv.start()"; srv->start(); dlog << LTRACE << "srv.start() just ended."; } void sockets_test ( ) /*! requires - sockets is an implementation of sockets/sockets_kernel_abstract.h is instantiated with int ensures - runs tests on sockets for compliance with the specs !*/ { dlog << LTRACE << "starting test"; serv srv; assigned_port = 0; dlog << LTRACE << "spawning threads"; thread_container stuff(srv); thread_function thread2(run_server, &srv); // wait until all the sending threads have ended stuff.wait(); if (srv.error_occurred) { dlog << LDEBUG << "tag: " << srv.tag; } srv.clear(); dlog << LTRACE << "ending successful test"; DLIB_TEST( !srv.error_occurred); DLIB_TEST( srv.got_connections); } // ---------------------------------------------------------------------------------------- class sockets_tester : public tester { public: sockets_tester ( ) : tester ("test_sockets", "Runs tests on the sockets component.") {} void perform_test ( ) { sockets_test(); } } a; }