blob: b76ab55bfa2be67efec3b4b0018c3fc0a1a891dd (
plain) (
tree)
|
|
#include <library/cpp/testing/unittest/registar.h>
#include "actor.h"
#include "queue_in_actor.h"
#include <library/cpp/messagebus/misc/test_sync.h>
#include <util/generic/object_counter.h>
#include <util/system/event.h>
using namespace NActor;
template <typename TThis>
struct TTestActorBase: public TAtomicRefCount<TThis>, public TActor<TThis> {
TTestSync Started;
TTestSync Acted;
TTestActorBase(TExecutor* executor)
: TActor<TThis>(executor)
{
}
void Act(TDefaultTag) {
Started.Inc();
static_cast<TThis*>(this)->Act2();
Acted.Inc();
}
};
struct TNopActor: public TTestActorBase<TNopActor> {
TObjectCounter<TNopActor> AllocCounter;
TNopActor(TExecutor* executor)
: TTestActorBase<TNopActor>(executor)
{
}
void Act2() {
}
};
struct TWaitForSignalActor: public TTestActorBase<TWaitForSignalActor> {
TWaitForSignalActor(TExecutor* executor)
: TTestActorBase<TWaitForSignalActor>(executor)
{
}
TSystemEvent WaitFor;
void Act2() {
WaitFor.Wait();
}
};
struct TDecrementAndSendActor: public TTestActorBase<TDecrementAndSendActor>, public TQueueInActor<TDecrementAndSendActor, int> {
TSystemEvent Done;
TDecrementAndSendActor* Next;
TDecrementAndSendActor(TExecutor* executor)
: TTestActorBase<TDecrementAndSendActor>(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<TNopActor>::ObjectCount());
UNIT_ASSERT_VALUES_EQUAL(TAtomicBase(0), TObjectCounter<TWaitForSignalActor>::ObjectCount());
UNIT_ASSERT_VALUES_EQUAL(TAtomicBase(0), TObjectCounter<TDecrementAndSendActor>::ObjectCount());
}
};
Y_UNIT_TEST_SUITE(TActor) {
Y_UNIT_TEST(Simple) {
TObjectCountChecker objectCountChecker;
TExecutor executor(4);
TIntrusivePtr<TNopActor> actor(new TNopActor(&executor));
actor->Schedule();
actor->Acted.WaitFor(1u);
}
Y_UNIT_TEST(ScheduleAfterStart) {
TObjectCountChecker objectCountChecker;
TExecutor executor(4);
TIntrusivePtr<TWaitForSignalActor> 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<TIntrusivePtr<TDecrementAndSendActor>> 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);
}
}
|