<commit_before>#include "tinfra/io/stream.h"
#include "tinfra/io/socket.h"
#include "tinfra/thread.h"
#include "tinfra/string.h"
#include "tinfra/server.h"
#include <ostream>
#include <istream>
#include <iostream>
#include <sstream>
#include <string>

#include <unittest++/UnitTest++.h>
#include "tinfra/test.h"

class Client: public tinfra::Runnable {
    std::auto_ptr<tinfra::io::stream> client;
    tinfra::net::Server& server;
public:
    Client(std::auto_ptr<tinfra::io::stream> _client, tinfra::net::Server& _server)
        : client(_client), server(_server) {}
        
    virtual void run()
    {
        
        bool connected = true;
        std::string response;
        //response = "hello!";
        //client->write(response.c_str(), response.size());
        //client->write("\r\n",2);
        while( connected ) {            
            {
                tinfra::io::zstreambuf buf(client.get());
                std::istream in(&buf);
                std::string cmd;
                std::getline(in, cmd);
                tinfra::strip_inplace(cmd);
                //std::cerr << "S<" << cmd << std::endl;
                if( cmd == "stop") {
                    server.stop();
                    connected = false;
                    response = "quitting";
                } else if( cmd == "close" ) {
                    connected = false;
                    response = "bye";
                } else {
                    response = cmd;
                }
            }
            {   
                //std::cerr << "S>" << response << std::endl;
                client->write(response.c_str(), response.size());
                client->write("\r\n",2);
            }
        }
        delete this;
    }
};

class TestServer: public tinfra::net::Server, public tinfra::Runnable {
public:
    virtual void onAccept(std::auto_ptr<tinfra::io::stream> client, std::string const&) {
        Runnable* worker = new Client(client, *this);        
        //tinfra::Thread::start_detached(*worker);
        worker->run();
    }
    
    virtual void run()
    {
        tinfra::net::Server::run();
    }
};

std::string invoke(std::istream& in, std::ostream& out, std::string const& msg)
{
    out << msg << std::endl;
    out.flush();
    //std::cerr << "C>'" << tinfra::escape_c(msg) << "'" << std::endl;
    std::string tmp;
    std::getline(in, tmp);
    tinfra::strip_inplace(tmp);
    //std::cerr << "C<'" << tinfra::escape_c(tmp) << "'" << std::endl;
    return tmp;
}
SUITE(tinfra_server)
{
    TEST(test_server_generic)
    {
        TestServer server;
        server.bind("localhost", 10900);
        tinfra::ThreadSet ts;
        tinfra::Thread server_thread = ts.start(server);    
        {        
            std::auto_ptr<tinfra::io::stream> client(tinfra::io::socket::open_client_socket("localhost",10900));
            
            tinfra::io::zstreambuf ibuf(client.get());
            tinfra::io::zstreambuf obuf(client.get());
            
            std::istream in(&ibuf);
            std::ostream out(&obuf);
            
            CHECK_EQUAL( "zbyszek", invoke(in,out, "zbyszek"));
            CHECK_EQUAL( "A", invoke(in,out, "A"));
            CHECK_EQUAL( "", invoke(in,out, ""));
            CHECK_EQUAL( "quitting", invoke(in,out, "stop"));<commit_msg>test_server: described failing test case as TODO with explanation<commit_after>#include "tinfra/io/stream.h"
#include "tinfra/io/socket.h"
#include "tinfra/thread.h"
#include "tinfra/string.h"
#include "tinfra/server.h"
#include <ostream>
#include <istream>
#include <iostream>
#include <sstream>
#include <string>

#include <unittest++/UnitTest++.h>
#include "tinfra/test.h"

class Client: public tinfra::Runnable {
    std::auto_ptr<tinfra::io::stream> client;
    tinfra::net::Server& server;
public:
    Client(std::auto_ptr<tinfra::io::stream> _client, tinfra::net::Server& _server)
        : client(_client), server(_server) {}
        
    virtual void run()
    {
        
        bool connected = true;
        std::string response;
        //response = "hello!";
        //client->write(response.c_str(), response.size());
        //client->write("\r\n",2);
        while( connected ) {            
            {
                tinfra::io::zstreambuf buf(client.get());
                std::istream in(&buf);
                std::string cmd;
                std::getline(in, cmd);
                tinfra::strip_inplace(cmd);
                //std::cerr << "S<" << cmd << std::endl;
                if( cmd == "stop") {
                    server.stop();
                    connected = false;
                    response = "quitting";
                } else if( cmd == "close" ) {
                    connected = false;
                    response = "bye";
                } else {
                    response = cmd;
                }
            }
            {   
                //std::cerr << "S>" << response << std::endl;
                client->write(response.c_str(), response.size());
                client->write("\r\n",2);
            }
        }
        delete this;
    }
};

class TestServer: public tinfra::net::Server, public tinfra::Runnable {
public:
    virtual void onAccept(std::auto_ptr<tinfra::io::stream> client, std::string const&) {
        Runnable* worker = new Client(client, *this);        
        //tinfra::Thread::start_detached(*worker);
        worker->run();
    }
    
    virtual void run()
    {
        tinfra::net::Server::run();
    }
};

std::string invoke(std::istream& in, std::ostream& out, std::string const& msg)
{
    out << msg << std::endl;
    out.flush();
    //std::cerr << "C>'" << tinfra::escape_c(msg) << "'" << std::endl;
    std::string tmp;
    std::getline(in, tmp);
    tinfra::strip_inplace(tmp);
    //std::cerr << "C<'" << tinfra::escape_c(tmp) << "'" << std::endl;
    return tmp;
}
SUITE(tinfra_server)
{
    TEST(test_server_generic)
    {
        TestServer server;
        server.bind("localhost", 10900);
        tinfra::ThreadSet ts;
        tinfra::Thread server_thread = ts.start(server);    
        {        
            std::auto_ptr<tinfra::io::stream> client(tinfra::io::socket::open_client_socket("localhost",10900));
            
            tinfra::io::zstreambuf ibuf(client.get());
            tinfra::io::zstreambuf obuf(client.get());
            
            std::istream in(&ibuf);
            std::ostream out(&obuf);
	    
            // TODO: this test fails with "zyszek" sometimes
	    //       because zstreambuf is broken
	    //       in following read sequence: 
	    //  sendto(4, "zbyszek", 7, 0, NULL, 0)     = 7
	    //  sendto(4, "\n", 1, 0, NULL, 0)          = 1
	    //  recvfrom(4, "z", 1, 0, NULL, NULL)      = 1
	    //  recvfrom(4, "byszek", 32768, 0, NULL, NULL) = 6
	    //  recvfrom(4, "\r\n", 32768, 0, NULL, NULL) = 2
	    //
	    // and thus std::getline( returns "zyszek\r\n")
		
            CHECK_EQUAL( "zbyszek", invoke(in,out, "zbyszek"));
	    
            CHECK_EQUAL( "A", invoke(in,out, "A"));
            CHECK_EQUAL( "", invoke(in,out, ""));
            CHECK_EQUAL( "quitting", invoke(in,out, "stop"));
{'fraction_non_alphanumeric': 0.16888019013001537, 'fraction_numerical': 0.007549280022368237, 'mean_word_length': 1.964774140074596, 'pattern_counts': {'":': 0, '<': 91, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6576028', 'n_tokens_mistral': 2355, 'n_tokens_neox': 2204, 'n_words': 424}