#include "helpers.h"

#include <search/idl/meta.pb.h>

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

#include <util/system/maxlen.h>

using NUnitTest::RandomString;

class THelpersTest: public TTestBase {
private:
    UNIT_TEST_SUITE(THelpersTest)
        UNIT_TEST(TestExtractSearchResults0)
        UNIT_TEST(TestExtractSearchResults1)
        UNIT_TEST(TestExtractSearchResults4)
        UNIT_TEST(TestExtractSearchResultsKV)
        UNIT_TEST(TestGenerateReport0)
        UNIT_TEST(TestGenerateReport1)
        UNIT_TEST(TestGenerateReport4)
        UNIT_TEST(TestGenerateReportKV)
        UNIT_TEST(TestGetDaemonConfig)
        UNIT_TEST(TestGetSearchProxyConfig)
        UNIT_TEST(TestGetPatientSearchProxyConfig)
    UNIT_TEST_SUITE_END();

public:
    void TestExtractSearchResults0()
    {
        TSearchResults results(ExtractSearchResults(NMetaProtocol::TReport(), 200));
        UNIT_ASSERT_VALUES_EQUAL(results.size(), size_t(0));
        UNIT_ASSERT_VALUES_EQUAL(results.HttpStatus, unsigned(200));
    }

    void TestExtractSearchResults1()
    {
        NMetaProtocol::TReport report;
        NMetaProtocol::TGrouping* grouping = report.AddGrouping();
        NMetaProtocol::TGroup* group = grouping->AddGroup();
        NMetaProtocol::TDocument* document = group->AddDocument();
        document->SetRelevance(100500);
        document->MutableArchiveInfo()->SetUrl(RandomString(URL_MAX / 2));
        const TSearchResults& results = ExtractSearchResults(report, 301);
        UNIT_ASSERT_VALUES_EQUAL(results.size(), size_t(1));
        UNIT_ASSERT_VALUES_EQUAL(results.HttpStatus, unsigned(301));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Relevance, 100500);
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls.size(), size_t(1));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls[0], RandomString(URL_MAX / 2));
    }

    void TestExtractSearchResults4()
    {
        NMetaProtocol::TReport report;
        NMetaProtocol::TGrouping* grouping = report.AddGrouping();
        NMetaProtocol::TGroup* group = grouping->AddGroup();
        NMetaProtocol::TDocument* document = group->AddDocument();
        document->SetRelevance(9000);
        document->MutableArchiveInfo()->SetUrl(RandomString(URL_MAX / 2, 1));
        document = group->AddDocument();
        document->MutableArchiveInfo()->SetUrl(RandomString(URL_MAX / 2, 2));
        group = grouping->AddGroup();
        document = group->AddDocument();
        document->SetRelevance(100500);
        document->MutableArchiveInfo()->SetUrl(RandomString(URL_MAX / 2, 3));
        document = group->AddDocument();
        document->MutableArchiveInfo()->SetUrl(RandomString(URL_MAX / 2, 4));
        const TSearchResults& results = ExtractSearchResults(report, 404);
        UNIT_ASSERT_VALUES_EQUAL(results.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results.HttpStatus, unsigned(404));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Relevance, 9000);
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls[0],
            RandomString(URL_MAX / 2, 1));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls[1],
            RandomString(URL_MAX / 2, 2));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Relevance, 100500);
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls[0],
            RandomString(URL_MAX / 2, 3));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls[1],
            RandomString(URL_MAX / 2, 4));
    }

    void TestExtractSearchResultsKV()
    {
        NMetaProtocol::TReport report;
        NMetaProtocol::TGrouping* grouping = report.AddGrouping();
        NMetaProtocol::TGroup* group = grouping->AddGroup();
        NMetaProtocol::TDocument* document = group->AddDocument();
        document->SetRelevance(9000);
        document ->SetUrl(RandomString(URL_MAX / 2, 1));
        document = group->AddDocument();
        document ->SetUrl(RandomString(URL_MAX / 2, 2));
        group = grouping->AddGroup();
        document = group->AddDocument();
        document->SetRelevance(100500);
        document ->SetUrl(RandomString(URL_MAX / 2, 3));
        document = group->AddDocument();
        document->SetUrl(RandomString(URL_MAX / 2, 4));
        const TSearchResults& results = ExtractSearchResults(report, 404, true);
        UNIT_ASSERT_VALUES_EQUAL(results.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results.HttpStatus, unsigned(404));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Relevance, 9000);
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls[0],
            RandomString(URL_MAX / 2, 1));
        UNIT_ASSERT_VALUES_EQUAL(results[0].Urls[1],
            RandomString(URL_MAX / 2, 2));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Relevance, 100500);
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls.size(), size_t(2));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls[0],
            RandomString(URL_MAX / 2, 3));
        UNIT_ASSERT_VALUES_EQUAL(results[1].Urls[1],
            RandomString(URL_MAX / 2, 4));
    }

    void TestGenerateReport0()
    {
        UNIT_ASSERT_VALUES_EQUAL(
            GenerateReport(TSearchResults(200)).GetGrouping().size(), 0);
    }

    void TestGenerateReport1()
    {
        const TSearchResults data(200, TSearchResultsGroup(100500,
                TSearchResultsGroup::TUrls(1, RandomString(URL_MAX / 2, 5))));
        const NMetaProtocol::TReport& report = GenerateReport(data);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping().size(), 1);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup().size(), 1);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetRelevance(), i64(100500));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument().size(), 1);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetRelevance(), ui64(100500));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).HasArchiveInfo(), true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetArchiveInfo().GetUrl(),
            RandomString(URL_MAX / 2, 5));
    }

    void TestGenerateReport4()
    {
        TSearchResults data(300);
        data.push_back(TSearchResultsGroup(9000));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 6));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 7));
        data.push_back(TSearchResultsGroup(100500));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 8));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 9));
        const NMetaProtocol::TReport& report = GenerateReport(data);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping().size(), 1);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetRelevance(), i64(9000));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetRelevance(), ui64(9000));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).HasArchiveInfo(), true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetArchiveInfo().GetUrl(),
            RandomString(URL_MAX / 2, 6));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(1).GetRelevance(), ui64(9000));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(1).HasArchiveInfo(), true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(1).GetArchiveInfo().GetUrl(),
            RandomString(URL_MAX / 2, 7));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetRelevance(), i64(100500));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(0).GetRelevance(), ui64(100500));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(0).HasArchiveInfo(), true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(0).GetArchiveInfo().GetUrl(),
            RandomString(URL_MAX / 2, 8));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(1).GetRelevance(), ui64(100500));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(1).HasArchiveInfo(), true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(1).GetArchiveInfo().GetUrl(),
            RandomString(URL_MAX / 2, 9));
    }

    void TestGenerateReportKV()
    {
        TSearchResults data(300);
        data.push_back(TSearchResultsGroup(9000));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 6));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 7));
        data.push_back(TSearchResultsGroup(100500));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 8));
        data.back().Urls.push_back(RandomString(URL_MAX / 2, 9));
        const NMetaProtocol::TReport& report = GenerateReport(data, true);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping().size(), 1);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetRelevance(), ui64(9000));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(0).GetUrl(),
            RandomString(URL_MAX / 2, 6));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(0).
            GetDocument(1).GetUrl(),
            RandomString(URL_MAX / 2, 7));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument().size(), 2);
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(0).GetUrl(),
            RandomString(URL_MAX / 2, 8));
        UNIT_ASSERT_VALUES_EQUAL(report.GetGrouping(0).GetGroup(1).
            GetDocument(1).GetUrl(),
            RandomString(URL_MAX / 2, 9));
    }

    void TestGetDaemonConfig()
    {
        UNIT_ASSERT_STRINGS_EQUAL(GetDaemonConfig(),
            "<DaemonConfig>\n"
            "\tLogLevel: 0\n"
            "\tLoggerType: null\n"
            "</DaemonConfig>");
    }

    void TestGetSearchProxyConfig()
    {
        UNIT_ASSERT_VALUES_EQUAL(GetSearchProxyConfig(9000),
            "<SearchProxy>\n"
            "\tHost: localhost\n"
            "\tPort: 9000\n"
            "</SearchProxy>");
    }

    void TestGetPatientSearchProxyConfig()
    {
        UNIT_ASSERT_VALUES_EQUAL(GetPatientSearchProxyConfig(17000),
            "<SearchProxy>\n"
            "\tHost: localhost\n"
            "\tPort: 17000\n"
            "\tMaxConnections: 3000\n"
            "\tMaxQueueSize: 10000\n"
            "\tThreads: 64\n"
            "\t<SearchConfig>\n"
            "\t\tThreads: 64\n"
            "\t\tConnectTimeout: 10\n"
            "\t\tGlobalTimeout: 30000\n"
            "\t\t\n"
            "\t\t<SearchPageTemplate>\n"
            "\t\t\tMethod: builtin\n"
            "\t\t\tModule: searchproxy\n"
            "\t\t</SearchPageTemplate>\n"
            "\t\t<HttpStatuses>\n"
            "\t\t\tEmptySetStatus: 404\n"
            "\t\t\tIncompleteStatus: 502\n"
            "\t\t\tSyntaxErrorStatus: 400\n"
            "\t\t</HttpStatuses>\n"
            "\t</SearchConfig>\n"
            "</SearchProxy>");
    }
};

UNIT_TEST_SUITE_REGISTRATION(THelpersTest)

