From dd02c01c36d82cf8cfade41df0bf54a100aea01d Mon Sep 17 00:00:00 2001 From: Alexey Rybalchenko Date: Fri, 8 Mar 2019 15:26:21 +0100 Subject: [PATCH] Extend tests of error cases - test raising SIGINT in every state - test going to Error state from every state - add new states (bind/connect) to exception tests --- fairmq/StateMachine.cxx | 10 ++ fairmq/StateMachine.h | 2 + fairmq/plugins/Control.cxx | 86 +++++++--------- test/CMakeLists.txt | 2 + test/device/_error_state.cxx | 149 +++++++++++++++++++++++++++ test/device/_exceptions.cxx | 24 +++++ test/device/_signals.cxx | 149 +++++++++++++++++++++++++++ test/helper/devices/TestErrorState.h | 111 ++++++++++++++++++++ test/helper/devices/TestExceptions.h | 14 +++ test/helper/devices/TestSignals.h | 112 ++++++++++++++++++++ test/helper/runTestDevice.cxx | 62 ++++------- 11 files changed, 634 insertions(+), 87 deletions(-) create mode 100644 test/device/_error_state.cxx create mode 100644 test/device/_signals.cxx create mode 100644 test/helper/devices/TestErrorState.h create mode 100644 test/helper/devices/TestSignals.h diff --git a/fairmq/StateMachine.cxx b/fairmq/StateMachine.cxx index 7e446d33..850d0547 100644 --- a/fairmq/StateMachine.cxx +++ b/fairmq/StateMachine.cxx @@ -28,6 +28,7 @@ #include #include #include +#include using namespace std; using namespace boost::msm; @@ -299,6 +300,10 @@ struct Machine_ : public state_machine_def fWorkDoneCV.notify_one(); } } + + if (fState == State::Error) { + throw StateMachine::ErrorStateException("Device transitioned to error state"); + } } // replaces the default no-transition response. @@ -463,7 +468,11 @@ void StateMachine::ProcessWork() try { fsm->CallStateChangeCallbacks(State::Idle); fsm->ProcessWork(); + } catch(ErrorStateException& ese) { + LOG(trace) << "ErrorStateException caught in ProcessWork(), rethrowing"; + throw; } catch(...) { + LOG(debug) << "Exception caught in ProcessWork(), going to Error state and rethrowing"; { lock_guard lock(fsm->fStateMtx); fsm->fState = State::Error; @@ -480,3 +489,4 @@ string StateMachine::GetStateName(const State state) { return stateNames.at(stat string StateMachine::GetTransitionName(const Transition transition) { return transitionNames.at(static_cast(transition)); } State StateMachine::GetState(const string& state) { return stateNumbers.at(state); } Transition StateMachine::GetTransition(const string& transition) { return transitionNumbers.at(transition); } + diff --git a/fairmq/StateMachine.h b/fairmq/StateMachine.h index 414b9495..faaf6cfc 100644 --- a/fairmq/StateMachine.h +++ b/fairmq/StateMachine.h @@ -94,6 +94,8 @@ class StateMachine static State GetState(const std::string& state); static Transition GetTransition(const std::string& transition); + struct ErrorStateException : std::runtime_error { using std::runtime_error::runtime_error; }; + private: std::shared_ptr fFsm; }; diff --git a/fairmq/plugins/Control.cxx b/fairmq/plugins/Control.cxx index c36f862d..c313668f 100644 --- a/fairmq/plugins/Control.cxx +++ b/fairmq/plugins/Control.cxx @@ -29,8 +29,7 @@ namespace ++gSignalCount; gLastSignal = signal; - if (gSignalCount > 1) - { + if (gSignalCount > 1) { std::abort(); } } @@ -57,11 +56,18 @@ Control::Control(const string& name, const Plugin::Version version, const string { SubscribeToDeviceStateChange([&](DeviceState newState) { LOG(trace) << "control plugin notified on new state: " << newState; + { lock_guard lock{fEventsMutex}; fEvents.push(newState); } fNewEvent.notify_one(); + + if (newState == DeviceState::Error) { + fPluginShutdownRequested = true; + fDeviceShutdownRequested = true; + // throw DeviceErrorState("Controlled device transitioned to error state."); + } }); try { @@ -110,6 +116,25 @@ auto Control::RunStartupSequence() -> void while (WaitForNextState() != DeviceState::Running) {} } +auto Control::WaitForNextState() -> DeviceState +{ + unique_lock lock{fEventsMutex}; + while (fEvents.empty()) { + fNewEvent.wait_for(lock, chrono::milliseconds(50)); + } + + auto result = fEvents.front(); + + if (result == DeviceState::Error) { + ReleaseDeviceControl(); + throw DeviceErrorState("Controlled device transitioned to error state."); + } + + fEvents.pop(); + + return result; +} + auto ControlPluginProgramOptions() -> Plugin::ProgOptions { namespace po = boost::program_options; @@ -248,6 +273,7 @@ try { } if (GetCurrentDeviceState() == DeviceState::Error) { + ReleaseDeviceControl(); throw DeviceErrorState("Controlled device transitioned to error state."); } @@ -363,64 +389,38 @@ void Control::PrintStateMachine() cout << ss.str() << flush; } -auto Control::WaitForNextState() -> DeviceState -{ - unique_lock lock{fEventsMutex}; - while (fEvents.empty()) { - fNewEvent.wait_for(lock, chrono::milliseconds(50)); - } - - auto result = fEvents.front(); - - if (result == DeviceState::Error) { - throw DeviceErrorState("Controlled device transitioned to error state."); - } - - fEvents.pop(); - - return result; -} - auto Control::StaticMode() -> void -try -{ +try { RunStartupSequence(); { // Wait for next state, which is DeviceState::Ready, // or for device shutdown request (Ctrl-C) unique_lock lock{fEventsMutex}; - while (fEvents.empty() && !fDeviceShutdownRequested) - { + while (fEvents.empty() && !fDeviceShutdownRequested) { fNewEvent.wait_for(lock, chrono::milliseconds(50)); } - if (fEvents.front() == DeviceState::Error) - { + if (fEvents.front() == DeviceState::Error) { + ReleaseDeviceControl(); throw DeviceErrorState("Controlled device transitioned to error state."); } } RunShutdownSequence(); -} -catch (PluginServices::DeviceControlError& e) -{ +} catch (PluginServices::DeviceControlError& e) { // If we are here, it means another plugin has taken control. That's fine, just print the exception message and do nothing else. LOG(debug) << e.what(); -} -catch (DeviceErrorState&) -{ +} catch (DeviceErrorState&) { } auto Control::SignalHandler() -> void { - while (gSignalCount == 0 && !fPluginShutdownRequested) - { + while (gSignalCount == 0 && !fPluginShutdownRequested) { this_thread::sleep_for(chrono::milliseconds(100)); } - if (!fPluginShutdownRequested) - { + if (!fPluginShutdownRequested) { LOG(info) << "Received device shutdown request (signal " << gLastSignal << ")."; LOG(info) << "Waiting for graceful device shutdown. Hit Ctrl-C again to abort immediately."; @@ -431,20 +431,14 @@ auto Control::SignalHandler() -> void if (fControllerThread.joinable()) fControllerThread.join(); } - if (!fDeviceHasShutdown) - { + if (!fDeviceHasShutdown) { // Take over control and attempt graceful shutdown StealDeviceControl(); - try - { + try { RunShutdownSequence(); - } - catch (PluginServices::DeviceControlError& e) - { + } catch (PluginServices::DeviceControlError& e) { LOG(info) << "Graceful device shutdown failed: " << e.what() << " If hanging, hit Ctrl-C again to abort immediately."; - } - catch (...) - { + } catch (...) { LOG(info) << "Graceful device shutdown failed. If hanging, hit Ctrl-C again to abort immediately."; } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f00d894f..f49f88dc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,8 @@ add_testsuite(Device device/_config.cxx device/_waitfor.cxx device/_exceptions.cxx + device/_error_state.cxx + device/_signals.cxx LINKS FairMQ DEPENDS testhelper_runTestDevice diff --git a/test/device/_error_state.cxx b/test/device/_error_state.cxx new file mode 100644 index 00000000..68699b7d --- /dev/null +++ b/test/device/_error_state.cxx @@ -0,0 +1,149 @@ +/******************************************************************************** + * Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#include "runner.h" + +#include +#include +#include + +#include +#include +#include + +namespace +{ + +using namespace std; +using namespace fair::mq::test; +using namespace fair::mq::tools; + +void RunErrorStateIn(const std::string& state, const std::string& input = "") +{ + size_t session{fair::mq::tools::UuidHash()}; + + execute_result result{"", 100}; + thread device_thread([&]() { + stringstream cmd; + cmd << runTestDevice + << " --id error_state_" << state << "_" + << " --control " << ((input == "") ? "static" : "interactive") + << " --session " << session + << " --color false"; + result = execute(cmd.str(), "[ErrorFound IN " + state + "]", input); + }); + + device_thread.join(); + + ASSERT_NE(std::string::npos, result.console_out.find("going to change to Error state from " + state + "()")); + + exit(result.exit_code); +} + +TEST(ErrorState, static_InInit) +{ + EXPECT_EXIT(RunErrorStateIn("Init"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InBind) +{ + EXPECT_EXIT(RunErrorStateIn("Bind"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InConnect) +{ + EXPECT_EXIT(RunErrorStateIn("Connect"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InInitTask) +{ + EXPECT_EXIT(RunErrorStateIn("InitTask"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InPreRun) +{ + EXPECT_EXIT(RunErrorStateIn("PreRun"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InRun) +{ + EXPECT_EXIT(RunErrorStateIn("Run"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InPostRun) +{ + EXPECT_EXIT(RunErrorStateIn("PostRun"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InResetTask) +{ + EXPECT_EXIT(RunErrorStateIn("ResetTask"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, static_InReset) +{ + EXPECT_EXIT(RunErrorStateIn("Reset"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InInit) +{ + EXPECT_EXIT(RunErrorStateIn("Init", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InBind) +{ + EXPECT_EXIT(RunErrorStateIn("Bind", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InConnect) +{ + EXPECT_EXIT(RunErrorStateIn("Connect", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InInitTask) +{ + EXPECT_EXIT(RunErrorStateIn("InitTask", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InPreRun) +{ + EXPECT_EXIT(RunErrorStateIn("PreRun", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InRun) +{ + EXPECT_EXIT(RunErrorStateIn("Run", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InPostRun) +{ + EXPECT_EXIT(RunErrorStateIn("PostRun", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InResetTask) +{ + EXPECT_EXIT(RunErrorStateIn("ResetTask", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_InReset) +{ + EXPECT_EXIT(RunErrorStateIn("Reset", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InInit) +{ + EXPECT_EXIT(RunErrorStateIn("Init", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InBind) +{ + EXPECT_EXIT(RunErrorStateIn("Bind", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InConnect) +{ + EXPECT_EXIT(RunErrorStateIn("Connect", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InInitTask) +{ + EXPECT_EXIT(RunErrorStateIn("InitTask", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InPreRun) +{ + EXPECT_EXIT(RunErrorStateIn("PreRun", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InRun) +{ + EXPECT_EXIT(RunErrorStateIn("Run", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(ErrorState, interactive_invalid_InPostRun) +{ + EXPECT_EXIT(RunErrorStateIn("PostRun", "_"), ::testing::ExitedWithCode(1), ""); +} + +} // namespace diff --git a/test/device/_exceptions.cxx b/test/device/_exceptions.cxx index 2120bb62..e362c625 100644 --- a/test/device/_exceptions.cxx +++ b/test/device/_exceptions.cxx @@ -49,6 +49,14 @@ TEST(Exceptions, static_InInit) { EXPECT_EXIT(RunExceptionIn("Init"), ::testing::ExitedWithCode(1), ""); } +TEST(Exceptions, static_InBind) +{ + EXPECT_EXIT(RunExceptionIn("Bind"), ::testing::ExitedWithCode(1), ""); +} +TEST(Exceptions, static_InConnect) +{ + EXPECT_EXIT(RunExceptionIn("Connect"), ::testing::ExitedWithCode(1), ""); +} TEST(Exceptions, static_InInitTask) { EXPECT_EXIT(RunExceptionIn("InitTask"), ::testing::ExitedWithCode(1), ""); @@ -77,6 +85,14 @@ TEST(Exceptions, interactive_InInit) { EXPECT_EXIT(RunExceptionIn("Init", "q"), ::testing::ExitedWithCode(1), ""); } +TEST(Exceptions, interactive_InBind) +{ + EXPECT_EXIT(RunExceptionIn("Bind", "q"), ::testing::ExitedWithCode(1), ""); +} +TEST(Exceptions, interactive_InConnect) +{ + EXPECT_EXIT(RunExceptionIn("Connect", "q"), ::testing::ExitedWithCode(1), ""); +} TEST(Exceptions, interactive_InInitTask) { EXPECT_EXIT(RunExceptionIn("InitTask", "q"), ::testing::ExitedWithCode(1), ""); @@ -105,6 +121,14 @@ TEST(Exceptions, interactive_invalid_InInit) { EXPECT_EXIT(RunExceptionIn("Init", "_"), ::testing::ExitedWithCode(1), ""); } +TEST(Exceptions, interactive_invalid_InBind) +{ + EXPECT_EXIT(RunExceptionIn("Bind", "_"), ::testing::ExitedWithCode(1), ""); +} +TEST(Exceptions, interactive_invalid_InConnect) +{ + EXPECT_EXIT(RunExceptionIn("Connect", "_"), ::testing::ExitedWithCode(1), ""); +} TEST(Exceptions, interactive_invalid_InInitTask) { EXPECT_EXIT(RunExceptionIn("InitTask", "_"), ::testing::ExitedWithCode(1), ""); diff --git a/test/device/_signals.cxx b/test/device/_signals.cxx new file mode 100644 index 00000000..720fe9f2 --- /dev/null +++ b/test/device/_signals.cxx @@ -0,0 +1,149 @@ +/******************************************************************************** + * Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#include "runner.h" + +#include +#include +#include + +#include +#include +#include + +namespace +{ + +using namespace std; +using namespace fair::mq::test; +using namespace fair::mq::tools; + +void RunSignalIn(const std::string& state, const std::string& input = "") +{ + size_t session{fair::mq::tools::UuidHash()}; + + execute_result result{"", 100}; + thread device_thread([&]() { + stringstream cmd; + cmd << runTestDevice + << " --id signals_" << state << "_" + << " --control " << ((input == "") ? "static" : "interactive") + << " --session " << session + << " --color false"; + result = execute(cmd.str(), "[SIGINT IN " + state + "]", input); + }); + + device_thread.join(); + + ASSERT_NE(std::string::npos, result.console_out.find("raising SIGINT from " + state + "()")); + + exit(result.exit_code); +} + +TEST(Signal_SIGINT, static_InInit) +{ + EXPECT_EXIT(RunSignalIn("Init"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InBind) +{ + EXPECT_EXIT(RunSignalIn("Bind"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InConnect) +{ + EXPECT_EXIT(RunSignalIn("Connect"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InInitTask) +{ + EXPECT_EXIT(RunSignalIn("InitTask"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InPreRun) +{ + EXPECT_EXIT(RunSignalIn("PreRun"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InRun) +{ + EXPECT_EXIT(RunSignalIn("Run"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InPostRun) +{ + EXPECT_EXIT(RunSignalIn("PostRun"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InResetTask) +{ + EXPECT_EXIT(RunSignalIn("ResetTask"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, static_InReset) +{ + EXPECT_EXIT(RunSignalIn("Reset"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InInit) +{ + EXPECT_EXIT(RunSignalIn("Init", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InBind) +{ + EXPECT_EXIT(RunSignalIn("Bind", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InConnect) +{ + EXPECT_EXIT(RunSignalIn("Connect", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InInitTask) +{ + EXPECT_EXIT(RunSignalIn("InitTask", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InPreRun) +{ + EXPECT_EXIT(RunSignalIn("PreRun", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InRun) +{ + EXPECT_EXIT(RunSignalIn("Run", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InPostRun) +{ + EXPECT_EXIT(RunSignalIn("PostRun", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InResetTask) +{ + EXPECT_EXIT(RunSignalIn("ResetTask", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_InReset) +{ + EXPECT_EXIT(RunSignalIn("Reset", "q"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InInit) +{ + EXPECT_EXIT(RunSignalIn("Init", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InBind) +{ + EXPECT_EXIT(RunSignalIn("Bind", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InConnect) +{ + EXPECT_EXIT(RunSignalIn("Connect", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InInitTask) +{ + EXPECT_EXIT(RunSignalIn("InitTask", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InPreRun) +{ + EXPECT_EXIT(RunSignalIn("PreRun", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InRun) +{ + EXPECT_EXIT(RunSignalIn("Run", "_"), ::testing::ExitedWithCode(0), ""); +} +TEST(Signal_SIGINT, interactive_invalid_InPostRun) +{ + EXPECT_EXIT(RunSignalIn("PostRun", "_"), ::testing::ExitedWithCode(0), ""); +} + +} // namespace diff --git a/test/helper/devices/TestErrorState.h b/test/helper/devices/TestErrorState.h new file mode 100644 index 00000000..600bd9cc --- /dev/null +++ b/test/helper/devices/TestErrorState.h @@ -0,0 +1,111 @@ +/******************************************************************************** + * Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#ifndef FAIR_MQ_TEST_ERROR_STATE_H +#define FAIR_MQ_TEST_ERROR_STATE_H + +#include +#include + +#include + +namespace fair +{ +namespace mq +{ +namespace test +{ + +class ErrorState : public FairMQDevice +{ + public: + void Init() override + { + std::string state("Init"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + void Bind() override + { + std::string state("Bind"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + void Connect() override + { + std::string state("Connect"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void InitTask() override + { + std::string state("InitTask"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void PreRun() override + { + std::string state("PreRun"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void Run() override + { + std::string state("Run"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void PostRun() override + { + std::string state("PostRun"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void ResetTask() override + { + std::string state("ResetTask"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } + + void Reset() override + { + std::string state("Reset"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "going to change to Error state from " << state << "()"; + ChangeState(fair::mq::Transition::ErrorFound); + } + } +}; + +} // namespace test +} // namespace mq +} // namespace fair + +#endif /* FAIR_MQ_TEST_ERROR_STATE_H */ diff --git a/test/helper/devices/TestExceptions.h b/test/helper/devices/TestExceptions.h index 0a58b724..6661bb9b 100644 --- a/test/helper/devices/TestExceptions.h +++ b/test/helper/devices/TestExceptions.h @@ -32,6 +32,20 @@ class Exceptions : public FairMQDevice throw std::runtime_error("exception in " + state + "()"); } } + auto Bind() -> void override + { + std::string state("Bind"); + if (std::string::npos != GetId().find("_" + state + "_")) { + throw std::runtime_error("exception in " + state + "()"); + } + } + auto Connect() -> void override + { + std::string state("Connect"); + if (std::string::npos != GetId().find("_" + state + "_")) { + throw std::runtime_error("exception in " + state + "()"); + } + } auto InitTask() -> void override { diff --git a/test/helper/devices/TestSignals.h b/test/helper/devices/TestSignals.h new file mode 100644 index 00000000..f85a1a97 --- /dev/null +++ b/test/helper/devices/TestSignals.h @@ -0,0 +1,112 @@ +/******************************************************************************** + * Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#ifndef FAIR_MQ_TEST_SIGNALS_H +#define FAIR_MQ_TEST_SIGNALS_H + +#include +#include + +#include +#include + +namespace fair +{ +namespace mq +{ +namespace test +{ + +class Signals : public FairMQDevice +{ + public: + void Init() override + { + std::string state("Init"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + void Bind() override + { + std::string state("Bind"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + void Connect() override + { + std::string state("Connect"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void InitTask() override + { + std::string state("InitTask"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void PreRun() override + { + std::string state("PreRun"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void Run() override + { + std::string state("Run"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void PostRun() override + { + std::string state("PostRun"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void ResetTask() override + { + std::string state("ResetTask"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } + + void Reset() override + { + std::string state("Reset"); + if (std::string::npos != GetId().find("_" + state + "_")) { + LOG(debug) << "raising SIGINT from " << state << "()"; + raise(SIGINT); + } + } +}; + +} // namespace test +} // namespace mq +} // namespace fair + +#endif /* FAIR_MQ_TEST_SIGNALS_H */ diff --git a/test/helper/runTestDevice.cxx b/test/helper/runTestDevice.cxx index 23f67714..ea2316e6 100644 --- a/test/helper/runTestDevice.cxx +++ b/test/helper/runTestDevice.cxx @@ -19,6 +19,8 @@ #include "devices/TestTransferTimeout.h" #include "devices/TestWaitFor.h" #include "devices/TestExceptions.h" +#include "devices/TestErrorState.h" +#include "devices/TestSignals.h" #include @@ -40,60 +42,38 @@ auto getDevice(const FairMQProgOptions& config) -> FairMQDevicePtr using namespace fair::mq::test; auto id = config.GetValue("id"); - if (0 == id.find("pull_")) - { + + if (0 == id.find("pull_")) { return new Pull; - } - else if (0 == id.find("push_")) - { + } else if (0 == id.find("push_")) { return new Push; - } - else if (0 == id.find("sub_")) - { + } else if (0 == id.find("sub_")) { return new Sub; - } - else if (0 == id.find("pub_")) - { + } else if (0 == id.find("pub_")) { return new Pub; - } - else if (0 == id.find("req_")) - { + } else if (0 == id.find("req_")) { return new Req; - } - else if (0 == id.find("rep_")) - { + } else if (0 == id.find("rep_")) { return new Rep; - } - else if (0 == id.find("transfer_timeout_")) - { + } else if (0 == id.find("transfer_timeout_")) { return new TransferTimeout; - } - else if (0 == id.find("pollout_")) - { + } else if (0 == id.find("pollout_")) { return new PollOut; - } - else if (0 == id.find("pollin_")) - { + } else if (0 == id.find("pollin_")) { return new PollIn; - } - else if (0 == id.find("pairleft_")) - { + } else if (0 == id.find("pairleft_")) { return new PairLeft; - } - else if (0 == id.find("pairright_")) - { + } else if (0 == id.find("pairright_")) { return new PairRight; - } - else if (0 == id.find("waitfor_")) - { + } else if (0 == id.find("waitfor_")) { return new TestWaitFor; - } - else if (0 == id.find("exceptions_")) - { + } else if (0 == id.find("exceptions_")) { return new Exceptions; - } - else - { + } else if (0 == id.find("error_state_")) { + return new ErrorState; + } else if (0 == id.find("signals_")) { + return new Signals; + } else { cerr << "Don't know id '" << id << "'" << endl; return nullptr; }