Implement Device::TransitionTo() and test it

This commit is contained in:
Alexey Rybalchenko 2019-07-15 14:10:03 +02:00 committed by Dennis Klein
parent 1c7da53386
commit 74d301a16f
4 changed files with 106 additions and 3 deletions

View File

@ -169,15 +169,15 @@ fair::mq::State FairMQDevice::WaitForNextState()
fStatesCV.wait_for(lock, chrono::milliseconds(50)); fStatesCV.wait_for(lock, chrono::milliseconds(50));
} }
auto result = fStates.front(); auto state = fStates.front();
if (result == fair::mq::State::Error) { if (state == fair::mq::State::Error) {
throw DeviceStateError("Device transitioned to error state."); throw DeviceStateError("Device transitioned to error state.");
} }
fStates.pop(); fStates.pop();
return result; return state;
} }
void FairMQDevice::WaitForState(fair::mq::State state) void FairMQDevice::WaitForState(fair::mq::State state)
@ -185,6 +185,48 @@ void FairMQDevice::WaitForState(fair::mq::State state)
while (WaitForNextState() != state) {} while (WaitForNextState() != state) {}
} }
void FairMQDevice::TransitionTo(const fair::mq::State s)
{
using fair::mq::State;
State currentState = GetCurrentState();
while (s != currentState) {
switch (currentState) {
case State::Idle:
if (s == State::Exiting) { ChangeState(Transition::End); }
else { ChangeState(Transition::InitDevice); }
break;
case State::InitializingDevice:
ChangeState(Transition::CompleteInit);
break;
case State::Initialized:
if (s == State::Exiting || s == State::Idle) { ChangeState(Transition::ResetDevice); }
else { ChangeState(Transition::Bind); }
break;
case State::Bound:
if (s == State::DeviceReady || s == State::Ready || s == State::Running) { ChangeState(Transition::Connect); }
else { ChangeState(Transition::ResetDevice); }
break;
case State::DeviceReady:
if (s == State::Running || s == State::Ready) { ChangeState(Transition::InitTask); }
else { ChangeState(Transition::ResetDevice); }
break;
case State::Ready:
if (s == State::Running) { ChangeState(Transition::Run); }
else { ChangeState(Transition::ResetTask); }
break;
case State::Running:
ChangeState(Transition::Stop);
break;
default: // Binding, Connecting, InitializingTask, ResettingDevice, ResettingTask
LOG(debug) << "TransitionTo ignoring state: " << currentState;
break;
}
currentState = WaitForNextState();
}
}
bool FairMQDevice::ChangeState(const int transition) bool FairMQDevice::ChangeState(const int transition)
{ {
return ChangeState(backwardsCompatibilityChangeStateHelper.at(transition)); return ChangeState(backwardsCompatibilityChangeStateHelper.at(transition));

View File

@ -494,6 +494,8 @@ class FairMQDevice
void WaitForState(fair::mq::State state); void WaitForState(fair::mq::State state);
void WaitForState(const std::string& state) { WaitForState(fair::mq::StateMachine::GetState(state)); } void WaitForState(const std::string& state) { WaitForState(fair::mq::StateMachine::GetState(state)); }
void TransitionTo(const fair::mq::State state);
void SubscribeToStateChange(const std::string& key, std::function<void(const fair::mq::State)> callback) { fStateMachine.SubscribeToStateChange(key, callback); } void SubscribeToStateChange(const std::string& key, std::function<void(const fair::mq::State)> callback) { fStateMachine.SubscribeToStateChange(key, callback); }
void UnsubscribeFromStateChange(const std::string& key) { fStateMachine.UnsubscribeFromStateChange(key); } void UnsubscribeFromStateChange(const std::string& key) { fStateMachine.UnsubscribeFromStateChange(key); }

View File

@ -107,6 +107,7 @@ add_testsuite(Device
device/_exceptions.cxx device/_exceptions.cxx
device/_error_state.cxx device/_error_state.cxx
device/_signals.cxx device/_signals.cxx
device/_transitions.cxx
LINKS FairMQ LINKS FairMQ
DEPENDS testhelper_runTestDevice DEPENDS testhelper_runTestDevice

View File

@ -0,0 +1,58 @@
/********************************************************************************
* Copyright (C) 2014-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 <FairMQDevice.h>
#include <gtest/gtest.h>
#include <vector>
#include <thread>
namespace
{
using namespace std;
using namespace fair::mq;
void transitionTo(const std::vector<State>& states, int numExpectedStates)
{
FairMQDevice device;
thread t([&] {
for (const auto& s : states) {
device.TransitionTo(s);
}
});
int numStates = 0;
device.SubscribeToStateChange("testRunner", [&numStates](State /* state */) {
numStates++;
});
device.RunStateMachine();
if (t.joinable()) {
t.join();
}
LOG(info) << "expected " << numExpectedStates << ", encountered " << numStates << " states";
EXPECT_EQ(numStates, numExpectedStates);
}
TEST(Transitions, TransitionTo)
{
transitionTo({State::Exiting}, 2);
transitionTo({State::InitializingDevice, State::Initialized, State::Exiting}, 6);
transitionTo({State::Initialized, State::Exiting}, 6);
transitionTo({State::DeviceReady, State::Bound, State::Running, State::Exiting}, 24);
transitionTo({State::Ready, State::Exiting}, 14);
transitionTo({State::Running, State::Exiting}, 16);
}
} // namespace