#include "server.h"

#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>

namespace {
    class TEchoReplier : public TRequestReplier {
        bool DoReply(const TReplyParams& params) final {
            params.Output << "HTTP/1.1 200 Ok\r\n\r\n";
            params.Input.ReadAll(params.Output);
            params.Output.Finish();
            return true;
        }
    };

    class TEchoServer : public TSearchServerBase {
        using TSearchServerBase::TSearchServerBase;
        TClientRequest* CreateClient() final {
            return new TEchoReplier();
        }
    };

    TString SendRequest(ui16 port, TStringBuf text) {
        TSocket s{TNetworkAddress("localhost", port)};
        TSocketOutput os(s);
        THttpOutput hos(&os);
        hos << "POST / HTTP/1.1\r\nHost: localhost:" << port << "\r\n\r\n" << text;
        hos.Finish();
        TSocketInput is(s);
        return THttpInput(&is).ReadAll();
    }

    void SendAndCheckEchoRequest(ui16 port, TStringBuf text) {
        UNIT_ASSERT_STRINGS_EQUAL(SendRequest(port, text), text);
    }
}

Y_UNIT_TEST_SUITE(TestSearchServer) {
    Y_UNIT_TEST(TestEchoServer) {
        THttpServerOptions opts;
        TPortManager pm;
        ui16 port = pm.GetPort();
        TEchoServer server(THttpServer::TOptions{port});
        server.Start();
        SendAndCheckEchoRequest(port, "");
        SendAndCheckEchoRequest(port, "123");
        server.Stop();
    }
    Y_UNIT_TEST(TestEchoMultiServer) {
        THttpServerOptions opts;
        TPortManager pm;
        ui16 port = pm.GetPort();
        TEchoServer server(THttpServer::TOptions(port).EnableReusePort(true), 10);
        server.Start();
        for (ui32 i = 0; i < 1000; ++i) {
            SendAndCheckEchoRequest(port, ::ToString(i));
        }
    }
    Y_UNIT_TEST(TestEchoMultiServerShutdown) {
        THttpServerOptions opts;
        TPortManager pm;
        ui16 port = pm.GetPort();
        TEchoServer server(THttpServer::TOptions(port).EnableReusePort(true), 10);
        server.Start();
        for (ui32 i = 0; i < 1000; ++i) {
            SendAndCheckEchoRequest(port, ::ToString(i));
        }
        server.ShutdownAndWait();
    }
}
