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

#include <wmconsole/version3/protos/queries2.pb.h>
#include <wmconsole/version3/protos/querygroups.pb.h>

#include "../composite_filter.cpp"

using namespace NWebmaster;
using namespace NWebmaster::proto::queries2;
using namespace NWebmaster::proto::querygroups;

Y_UNIT_TEST_SUITE(TSearchQueriesMRTest1) {
    Y_UNIT_TEST(CompositeFilter_TData_Test01) {
        QueryMessage msg;
        TData data(msg);

        //UNIT_ASSERT_EQUAL(data.GetQuery(), "");
        //UNIT_ASSERT_EQUAL(data.GetUrl(), "");
        UNIT_ASSERT_EQUAL(data.GetClicks(), 0);
        UNIT_ASSERT_EQUAL(data.GetShows(), 0);
        UNIT_ASSERT_EQUAL(data.GetCTR(), 0);
        UNIT_ASSERT_EQUAL(data.GetAvgClickPosition(), Max<float>());
        UNIT_ASSERT_EQUAL(data.GetAvgShowPosition(), Max<float>());
        UNIT_ASSERT_EQUAL(data.GetClicks(0, 1), 0);
        UNIT_ASSERT_EQUAL(data.GetShows(0, 1), 0);
        UNIT_ASSERT_EQUAL(data.GetCTR(0, 1), 0);
        UNIT_ASSERT_EQUAL(data.GetAvgClickPosition(0, 1), Max<float>());
        UNIT_ASSERT_EQUAL(data.GetAvgShowPosition(0, 1), Max<float>());
    }

    void AddPositionInfo(QueryRegionInfo *qri, int position, int shows, int clicks) {
        QueryPositionInfo *qpi = qri->add_position_info();
        qpi->set_position(position);
        qpi->set_shows_count(shows);
        qpi->set_clicks_count(clicks);
    }

    void FillQuery(QueryMessage &msg) {
        msg.set_corrected_query("test_query");
        msg.set_url("test_url");

        QueryRegionInfo *qri = nullptr;

        qri = msg.add_reports_by_region();
        AddPositionInfo(qri, 1, 2, 1);
        AddPositionInfo(qri, 2, 3, 2);
        AddPositionInfo(qri, 3, 5, 3);

        qri = msg.add_reports_by_region();
        AddPositionInfo(qri, 1, 2, 1);
        AddPositionInfo(qri, 2, 3, 2);
        AddPositionInfo(qri, 3, 5, 3);
    }

    float GetAvgClickPosition(const TData &data) {
        return (1.f * 1.f + 2.f * 2.f + 3.f * 3.f + 1.f * 1.f + 2.f * 2.f + 3.f * 3.f) / data.GetClicks();
    }

    float GetAvgShowPosition(const TData &data) {
        return (1.f * 2.f + 2.f * 3.f + 3.f * 5.f + 1.f * 2.f + 2.f * 3.f + 3.f * 5.f) / data.GetShows();
    }

    float GetAvgClickPosition_1_2(const TData &data) {
        return (1.f * 1.f + 1.f * 1.f) / data.GetClicks(1, 2);
    }

    float GetAvgShowPosition_1_2(const TData &data) {
        return (1.f * 2.f + 1.f * 2.f) / data.GetShows(1, 2);
    }

    float GetAvgClickPosition_2_4(const TData &data) {
        return (2.f * 2.f + 3.f * 3.f + 2.f * 2.f + 3.f * 3.f) / data.GetClicks(2, 4);
    }

    float GetAvgShowPosition_2_4(const TData &data) {
        return (2.f * 3.f + 3.f * 5.f + 2.f * 3.f + 3.f * 5.f) / data.GetShows(2, 4);
    }

    Y_UNIT_TEST(CompositeFilter_TData_Test02) {
        QueryMessage msg;

        FillQuery(msg);

        TData data(msg);

        UNIT_ASSERT_EQUAL(data.GetQuery(), "test_query");
        UNIT_ASSERT_EQUAL(data.GetUrl(), "test_url");

        UNIT_ASSERT_EQUAL(data.GetShows(), 20.f);
        UNIT_ASSERT_EQUAL(data.GetClicks(), 12.f);
        UNIT_ASSERT_EQUAL(data.GetCTR(), data.GetClicks() / data.GetShows());
        UNIT_ASSERT_EQUAL(data.GetAvgClickPosition(), GetAvgClickPosition(data));
        UNIT_ASSERT_EQUAL(data.GetAvgShowPosition(), GetAvgShowPosition(data));

        int a = 1, b = 2;
        UNIT_ASSERT_EQUAL(data.GetShows(a, b), 4.f);
        UNIT_ASSERT_EQUAL(data.GetClicks(a, b), 2.f);
        UNIT_ASSERT_EQUAL(data.GetCTR(a, b), data.GetClicks(a, b) / data.GetShows(a, b));
        UNIT_ASSERT_EQUAL(data.GetAvgClickPosition(a, b), GetAvgClickPosition_1_2(data));
        UNIT_ASSERT_EQUAL(data.GetAvgShowPosition(a, b), GetAvgShowPosition_1_2(data));

        a = 2; b = 4;
        UNIT_ASSERT_EQUAL(data.GetShows(a, b), 16.f);
        UNIT_ASSERT_EQUAL(data.GetClicks(a, b), 10.f);
        UNIT_ASSERT_EQUAL(data.GetCTR(a, b), data.GetClicks(a, b) / data.GetShows(a, b));
        UNIT_ASSERT_EQUAL(data.GetAvgClickPosition(a, b), GetAvgClickPosition_2_4(data));
        UNIT_ASSERT_EQUAL(data.GetAvgShowPosition(a, b), GetAvgShowPosition_2_4(data));
    }

    #define ACCEPTED(p) UNIT_ASSERT_EQUAL(p, true)
    #define REJECTED(p) UNIT_ASSERT_EQUAL(p, false)
    #define CONSTRAINT_ACCEPTED(filter, data) ACCEPTED(BuildConstraint(filter)->Accepted(data))
    #define CONSTRAINT_REJECTED(filter, data) REJECTED(BuildConstraint(filter)->Accepted(data))

    Y_UNIT_TEST(CompositeFilter_TConstraint_Test01) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);
        QueryFilter filter;

        filter.set_type(MATCHES_REGEXP); {
            filter.set_indicator(QUERY); {
                filter.set_filter_text("test_query"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_query"); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(URL); {
                filter.set_filter_text("test_url"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_url"); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(21); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(20); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(13); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(12); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR();
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(20); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(19); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(12); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(11); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR();
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }


        filter.set_type(GREATER_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(19); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(20); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(11); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(12); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR();
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(GREATER_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(20); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(21); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(12); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(13); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR();
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }
    }

    Y_UNIT_TEST(CompositeFilter_TConstraintBounded_Test01) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);
        QueryFilter filter;

        filter.set_indicator_from_position(1);
        filter.set_indicator_until_position(2);

        filter.set_type(MATCHES_REGEXP); {
            filter.set_indicator(QUERY); {
                filter.set_filter_text("test_query"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_query"); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(URL); {
                filter.set_filter_text("test_url"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_url"); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(5); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(4); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(3); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(2); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(1, 2);
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_1_2(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_1_2(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_1_2(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_1_2(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(4); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(3); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(2); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(1); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(1, 2);
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_1_2(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_1_2(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_1_2(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_1_2(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(GREATER_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(3); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(4); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(1); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(2); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(1, 2);
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_1_2(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_1_2(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_1_2(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_1_2(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(GREATER_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(4); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(5); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(2); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(3); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(1, 2);
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_1_2(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_1_2(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_1_2(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_1_2(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }
    }

    Y_UNIT_TEST(CompositeFilter_TConstraintBounded_Test02) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);
        QueryFilter filter;

        filter.set_indicator_from_position(2);
        filter.set_indicator_until_position(4);

        filter.set_type(MATCHES_REGEXP); {
            filter.set_indicator(QUERY); {
                filter.set_filter_text("test_query"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_query"); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(URL); {
                filter.set_filter_text("test_url"); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_text("wrong_url"); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(17); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(16); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(11); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(10); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(2, 4);
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_2_4(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_2_4(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_2_4(data) + 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_2_4(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(LESS_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(16); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(15); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(10); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(9); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(2, 4);
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_2_4(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_2_4(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_2_4(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_2_4(data) - 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(GREATER_THAN); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(15); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(16); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(9); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(10); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(2, 4);
                filter.set_filter_value(ctr - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_2_4(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_2_4(data)); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_2_4(data) - 1.f); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_2_4(data)); CONSTRAINT_REJECTED(filter, data);
            }
        }

        filter.set_type(GREATER_OR_EQUAL); {
            filter.set_indicator(SHOWS_COUNT); {
                filter.set_filter_value(16); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(17); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CLICKS_COUNT); {
                filter.set_filter_value(10); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(11); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(CTR); {
                float ctr = data.GetCTR(2, 4);
                filter.set_filter_value(ctr); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(ctr + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_SHOW_POSITION); {
                filter.set_filter_value(GetAvgShowPosition_2_4(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgShowPosition_2_4(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }

            filter.set_indicator(AVERAGE_CLICK_POSITION); {
                filter.set_filter_value(GetAvgClickPosition_2_4(data)); CONSTRAINT_ACCEPTED(filter, data);
                filter.set_filter_value(GetAvgClickPosition_2_4(data) + 1.f); CONSTRAINT_REJECTED(filter, data);
            }
        }
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test01) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;

        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.set_type(OR);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.set_type(NOT);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.set_type(AND);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.set_type(FILTER);
        expression.mutable_filter()->set_type(MATCHES_REGEXP);
        expression.mutable_filter()->set_indicator(QUERY);
        expression.mutable_filter()->set_filter_text("test_query");

        TFilter::Ptr filter = BuildTextFilter(expression);

        UNIT_ASSERT_EQUAL(filter->HasTextConstraints(), true);
        UNIT_ASSERT_EQUAL(filter->HasFloatConstraints(), false);
        UNIT_ASSERT_EQUAL(filter->Accepted(data), true);
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test02) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;

        expression.set_type(FILTER);
        expression.mutable_filter()->set_type(LESS_THAN);
        expression.mutable_filter()->set_indicator(SHOWS_COUNT);
        expression.mutable_filter()->set_filter_value(20.f);

        {
            TFilter::Ptr filter = BuildFloatFilter(expression);
            UNIT_ASSERT_EQUAL(filter->HasTextConstraints(), false);
            UNIT_ASSERT_EQUAL(filter->HasFloatConstraints(), true);
            UNIT_ASSERT_EQUAL(filter->Accepted(data), false);
        }

        FilterExpression *child1 = expression.add_filter_expressions(); //child filter must be ignored
        child1->mutable_filter()->set_type(MATCHES_REGEXP);
        child1->mutable_filter()->set_indicator(QUERY);
        child1->mutable_filter()->set_filter_text("wrong_query");
        expression.mutable_filter()->set_filter_value(21.f);
        UNIT_ASSERT_EQUAL(BuildFloatFilter(expression)->Accepted(data), true);

        expression.clear_filter(); //empty root constraint
        expression.set_type(NOT);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), true);

        child1->mutable_filter()->set_filter_text("test_query");
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.set_type(AND);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), true);
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test03) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;
        expression.set_type(FILTER);

        expression.mutable_filter()->set_type(GREATER_THAN);
        expression.mutable_filter()->set_indicator(CLICKS_COUNT);
        expression.mutable_filter()->set_filter_value(9.f);
        expression.mutable_filter()->set_indicator_from_position(2);
        expression.mutable_filter()->set_indicator_until_position(4);

        FilterExpression *child1 = expression.add_filter_expressions();
        child1->mutable_filter()->set_type(MATCHES_REGEXP);
        child1->mutable_filter()->set_indicator(QUERY);
        child1->mutable_filter()->set_filter_text("test_query");

        FilterExpression *child2 = expression.add_filter_expressions();
        child2->mutable_filter()->set_type(LESS_THAN);
        child2->mutable_filter()->set_indicator(CLICKS_COUNT);
        child2->mutable_filter()->set_filter_value(11.f);
        child2->mutable_filter()->set_indicator_from_position(2);
        child2->mutable_filter()->set_indicator_until_position(4);

        {
            TFilter::Ptr filter = BuildFullFilter(expression);
            UNIT_ASSERT_EQUAL(filter->HasTextConstraints(), true);
            UNIT_ASSERT_EQUAL(filter->HasFloatConstraints(), true);
            UNIT_ASSERT_EQUAL(filter->Accepted(data), true);
        }

        child1->mutable_filter()->set_filter_text("wrong_query");
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test04) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;
        expression.set_type(NOT);

        expression.mutable_filter()->set_type(GREATER_THAN);
        expression.mutable_filter()->set_indicator(CLICKS_COUNT);
        expression.mutable_filter()->set_filter_value(12.f);

        FilterExpression *child1 = expression.add_filter_expressions();
        child1->mutable_filter()->set_type(MATCHES_REGEXP);
        child1->mutable_filter()->set_indicator(QUERY);
        child1->mutable_filter()->set_filter_text("wrong_query");

        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), true);

        expression.set_type(OR);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), false);

        expression.mutable_filter()->set_filter_value(11.f);
        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), true);
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test05) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;

        expression.set_type(AND);
        expression.mutable_filter()->set_type(MATCHES_REGEXP);
        expression.mutable_filter()->set_indicator(QUERY);
        expression.mutable_filter()->set_filter_text("test_query");

        FilterExpression *child1 = expression.add_filter_expressions();
        child1->set_type(AND);
        child1->mutable_filter()->set_type(MATCHES_REGEXP);
        child1->mutable_filter()->set_indicator(URL);
        child1->mutable_filter()->set_filter_text("test_url");

        FilterExpression *child2 = expression.add_filter_expressions();
        child2->set_type(NOT);
        child2->mutable_filter()->set_type(MATCHES_REGEXP);
        child2->mutable_filter()->set_indicator(QUERY);
        child2->mutable_filter()->set_filter_text("wrong_query");

        FilterExpression *child2_child1 = child2->add_filter_expressions();
        child2_child1->set_type(AND);
        child2_child1->mutable_filter()->set_type(MATCHES_REGEXP);
        child2_child1->mutable_filter()->set_indicator(QUERY);
        child2_child1->mutable_filter()->set_filter_text("wrong_query");

        UNIT_ASSERT_EQUAL(BuildFullFilter(expression)->Accepted(data), true);
    }

    Y_UNIT_TEST(CompositeFilter_TFilter_Test06) {
        QueryMessage query;
        FillQuery(query);
        TData data(query);

        FilterExpression expression;

        expression.set_type(NOT);
        expression.mutable_filter()->set_type(GREATER_THAN);
        expression.mutable_filter()->set_indicator(CLICKS_COUNT);
        expression.mutable_filter()->set_filter_value(12.f);

        UNIT_ASSERT_EQUAL(BuildTextFilter(expression)->Accepted(data), false);
    }
}
