#include <balancer/kernel/coro/poller_event.h>
#include <balancer/kernel/testing/cont_executor.h>

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

using namespace NSrvKernel;

Y_UNIT_TEST_SUITE(TPollerEventTest) {
    Y_UNIT_TEST(Pipe) {
        NTesting::TTestContExecutor executor;

        TPipe r;
        TPipe w;
        TPipe::Pipe(r, w);

        bool readerFinished = false;
        bool writerFinished = false;

        auto reader = [&](TCont* cont) {
            TPollerEvent pipeEvent(*cont->Executor(), r.GetHandle(), CONT_POLL_READ);

            for (size_t i = 0; i < 10; ++i) {
                const int status = pipeEvent.Wait(cont, TDuration::Seconds(5).ToDeadLine());
                UNIT_ASSERT_VALUES_EQUAL(status, 0);

                ui64 res = 42;
                r.Read((void*)&res, sizeof res);
                UNIT_ASSERT_VALUES_EQUAL(i, res);
            }

            const TInstant t = Now();
            const int status = pipeEvent.Wait(cont, TDuration::Seconds(1).ToDeadLine());
            UNIT_ASSERT_VALUES_EQUAL(status, ETIMEDOUT);
            UNIT_ASSERT(Now() - t >= TDuration::Seconds(1));

            readerFinished = true;
        };

        auto writer = [&](TCont* cont) {
            for (ui64 i = 0; i < 10; ++i) {
                w.Write(&i, sizeof i);
                cont->SleepT(TDuration::MilliSeconds(1));
            }
            writerFinished = true;
        };

        executor.Create(reader, "reader");
        executor.Create(writer, "writer");
        executor.Execute();

        UNIT_ASSERT(readerFinished);
        UNIT_ASSERT(writerFinished);
    }
}
