#include #include "actor.h" #include "queue_in_actor.h" #include #include #include using namespace NActor; template struct TTestActorBase: public TAtomicRefCount, public TActor { TTestSync Started; TTestSync Acted; TTestActorBase(TExecutor* executor) : TActor(executor) { } void Act(TDefaultTag) { Started.Inc(); static_cast(this)->Act2(); Acted.Inc(); } }; struct TNopActor: public TTestActorBase { TObjectCounter AllocCounter; TNopActor(TExecutor* executor) : TTestActorBase(executor) { } void Act2() { } }; struct TWaitForSignalActor: public TTestActorBase { TWaitForSignalActor(TExecutor* executor) : TTestActorBase(executor) { } TSystemEvent WaitFor; void Act2() { WaitFor.Wait(); } }; struct TDecrementAndSendActor: public TTestActorBase, public TQueueInActor { TSystemEvent Done; TDecrementAndSendActor* Next; TDecrementAndSendActor(TExecutor* executor) : TTestActorBase(executor) , Next(nullptr) { } void ProcessItem(TDefaultTag, TDefaultTag, int n) { if (n == 0) { Done.Signal(); } else { Next->EnqueueAndSchedule(n - 1); } } void Act(TDefaultTag) { DequeueAll(); } }; struct TObjectCountChecker { TObjectCountChecker() { CheckCounts(); } ~TObjectCountChecker() { CheckCounts(); } void CheckCounts() { UNIT_ASSERT_VALUES_EQUAL(TAtomicBase(0), TObjectCounter::ObjectCount()); UNIT_ASSERT_VALUES_EQUAL(TAtomicBase(0), TObjectCounter::ObjectCount()); UNIT_ASSERT_VALUES_EQUAL(TAtomicBase(0), TObjectCounter::ObjectCount()); } }; Y_UNIT_TEST_SUITE(TActor) { Y_UNIT_TEST(Simple) { TObjectCountChecker objectCountChecker; TExecutor executor(4); TIntrusivePtr actor(new TNopActor(&executor)); actor->Schedule(); actor->Acted.WaitFor(1u); } Y_UNIT_TEST(ScheduleAfterStart) { TObjectCountChecker objectCountChecker; TExecutor executor(4); TIntrusivePtr actor(new TWaitForSignalActor(&executor)); actor->Schedule(); actor->Started.WaitFor(1); actor->Schedule(); actor->WaitFor.Signal(); // make sure Act is called second time actor->Acted.WaitFor(2u); } void ComplexImpl(int queueSize, int actorCount) { TObjectCountChecker objectCountChecker; TExecutor executor(queueSize); TVector> actors; for (int i = 0; i < actorCount; ++i) { actors.push_back(new TDecrementAndSendActor(&executor)); } for (int i = 0; i < actorCount; ++i) { actors.at(i)->Next = &*actors.at((i + 1) % actorCount); } for (int i = 0; i < actorCount; ++i) { actors.at(i)->EnqueueAndSchedule(10000); } for (int i = 0; i < actorCount; ++i) { actors.at(i)->Done.WaitI(); } } Y_UNIT_TEST(ComplexContention) { ComplexImpl(4, 6); } Y_UNIT_TEST(ComplexNoContention) { ComplexImpl(6, 4); } }