123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- // SPDX-License-Identifier: MIT
- // SPDX-FileCopyrightText: 2022 Ivan Baidakou
- #if defined(__ANDROID__)
- #undef __ANDROID__
- #endif
- #include "catch.hpp"
- #include "rotor-light/context.hpp"
- #include "rotor-light/planner.hpp"
- #include "rotor-light/queue.hpp"
- #include "rotor-light/supervisor.hpp"
- using namespace rotor_light;
- using MessageStorage =
- traits::MessageStorage<message::ChangeState, message::ChangeStateAck>;
- using AppQueue = Queue<MessageStorage, 5>;
- using AppPlanner = Planner<1>;
- TEST_CASE("start & finish empty supervisor", "[sup]") {
- using AppSupervisor = Supervisor<3>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- CHECK(sup.get_state() == State::off);
- sup.bind(context);
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::operational);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- }
- TEST_CASE("supervisor & succesfull actor", "[sup]") {
- using DummyActor = Actor<1>;
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- CHECK(sup.get_state() == State::off);
- sup.bind(context);
- CHECK(sup.get_id() == 1 << 0);
- auto act = sup.get_child<0>();
- CHECK(act->get_state() == State::off);
- CHECK(act->get_id() == 1 << 1);
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::operational);
- CHECK(act->get_state() == State::operational);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = restart (init)", "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() {
- inits = 0;
- fail_policy = FailPolicy::restart;
- }
- void advance_init() override {
- send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
- State::initialized, false);
- if (++inits >= 2) {
- fail_policy = FailPolicy::ignore;
- }
- }
- size_t inits;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- CHECK(sup.get_state() == State::off);
- CHECK(sup.get_id() == 1 << 0);
- auto act = sup.get_child<0>();
- CHECK(act->get_state() == State::off);
- CHECK(act->get_id() == 1 << 1);
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::initializing);
- CHECK(act->get_state() == State::off);
- CHECK(act->inits == 2);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = restart, do counts",
- "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() {
- inits = 0;
- fail_policy = FailPolicy::restart;
- }
- void advance_init() override { ++inits; }
- size_t inits;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::initializing);
- CHECK(act->get_state() == State::initializing);
- CHECK(act->inits == 1);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- CHECK(act->inits == 1);
- }
- TEST_CASE("supervisor & failing actor, fail policy = init (operational)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- using Parent = Actor<1>;
- DummyActor() {
- starts = 0;
- fail_policy = FailPolicy::restart;
- }
- void advance_start() override {
- Parent::advance_start();
- stop();
- ++starts;
- }
- size_t starts;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::operational);
- CHECK(act->get_state() == State::off);
- CHECK(act->starts == 1);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = force_restart (init)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() {
- inits = 0;
- fail_policy = FailPolicy::force_restart;
- }
- void advance_init() override {
- send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
- State::initialized, false);
- if (++inits >= 2) {
- fail_policy = FailPolicy::ignore;
- }
- }
- size_t inits;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::initializing);
- CHECK(act->get_state() == State::off);
- CHECK(act->inits == 2);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = force_restart (start)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- using Parent = Actor<1>;
- DummyActor() {
- starts = 0;
- fail_policy = FailPolicy::force_restart;
- }
- void advance_start() override {
- Parent::advance_start();
- if (++starts >= 2) {
- fail_policy = FailPolicy::ignore;
- }
- stop();
- }
- size_t starts;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- CHECK(sup.get_state() == State::off);
- CHECK(sup.get_id() == 1 << 0);
- auto act = sup.get_child<0>();
- CHECK(act->get_state() == State::off);
- CHECK(act->get_id() == 1 << 1);
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::operational);
- CHECK(act->get_state() == State::off);
- CHECK(act->starts == 2);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = escalate (init)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() {
- inits = 0;
- fail_policy = FailPolicy::escalate;
- }
- void advance_init() override {
- send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
- State::initialized, false);
- ++inits;
- }
- size_t inits;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- CHECK(sup.get_state() == State::off);
- CHECK(sup.get_id() == 1 << 0);
- auto act = sup.get_child<0>();
- CHECK(act->get_state() == State::off);
- CHECK(act->get_id() == 1 << 1);
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- CHECK(act->inits == 1);
- }
- TEST_CASE("supervisor & failing actor, fail policy = escalate (operational)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- using Parent = Actor<1>;
- DummyActor() {
- starts = 0;
- fail_policy = FailPolicy::escalate;
- }
- void advance_start() override {
- Parent::advance_start();
- stop();
- ++starts;
- }
- size_t starts;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::operational);
- CHECK(act->get_state() == State::off);
- CHECK(act->starts == 1);
- sup.stop();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
- TEST_CASE("supervisor & failing actor, fail policy = force_escalate (init)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() {
- inits = 0;
- fail_policy = FailPolicy::force_escalate;
- }
- void advance_init() override {
- send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
- State::initialized, false);
- ++inits;
- }
- size_t inits;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- CHECK(act->inits == 1);
- }
- TEST_CASE(
- "supervisor & failing actor, fail policy = force_escalate (operational)",
- "[sup]") {
- struct DummyActor : Actor<1> {
- using Parent = Actor<1>;
- DummyActor() {
- starts = 0;
- fail_policy = FailPolicy::force_escalate;
- }
- void advance_start() override {
- Parent::advance_start();
- stop();
- ++starts;
- }
- size_t starts;
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- CHECK(act->starts == 1);
- }
- TEST_CASE("supervisor double stop", "[sup]") {
- struct DummyActor : Actor<1> {
- DummyActor() { fail_policy = FailPolicy::escalate; }
- void advance_init() override {
- send<ctx::thread, message::ChangeStateAck>(0, supervisor->get_id(), id,
- State::initialized, false);
- supervisor->stop();
- supervisor->stop();
- }
- };
- using AppSupervisor = Supervisor<3, DummyActor>;
- AppPlanner planner;
- AppQueue queue;
- AppSupervisor sup;
- Context context{&queue, &planner, nullptr};
- sup.bind(context);
- auto act = sup.get_child<0>();
- sup.start();
- sup.process();
- CHECK(sup.get_state() == State::off);
- CHECK(act->get_state() == State::off);
- }
|