|
@@ -56,11 +56,17 @@ public:
|
|
///@brief Event issued when all the work is done.
|
|
///@brief Event issued when all the work is done.
|
|
static const int ALL_DONE_EVT = SM_EVENT_MAX + 3;
|
|
static const int ALL_DONE_EVT = SM_EVENT_MAX + 3;
|
|
|
|
|
|
|
|
+ ///@brief Event used to trigger an attempt to transition to bad state
|
|
|
|
+ static const int FORCE_UNDEFINED_ST_EVT = SM_EVENT_MAX + 4;
|
|
|
|
+
|
|
|
|
+ ///@brief Event used to trigger an attempt to transition to bad state
|
|
|
|
+ static const int SIMULATE_ERROR_EVT = SM_EVENT_MAX + 5;
|
|
|
|
+
|
|
/// @brief Constructor
|
|
/// @brief Constructor
|
|
///
|
|
///
|
|
/// Parameters match those needed by StateModel.
|
|
/// Parameters match those needed by StateModel.
|
|
- StateModelTest() : dummy_called_(false), model_failure_called_(false),
|
|
|
|
- work_completed_(false) {
|
|
|
|
|
|
+ StateModelTest() : dummy_called_(false), work_completed_(false),
|
|
|
|
+ failure_explanation_("") {
|
|
}
|
|
}
|
|
/// @brief Destructor
|
|
/// @brief Destructor
|
|
virtual ~StateModelTest() {
|
|
virtual ~StateModelTest() {
|
|
@@ -79,13 +85,12 @@ public:
|
|
dummy_called_ = true;
|
|
dummy_called_ = true;
|
|
}
|
|
}
|
|
|
|
|
|
- /// @brief Returns indication of whether or not the model failed to execute.
|
|
|
|
|
|
+ /// @brief Returns the failure explanation string.
|
|
///
|
|
///
|
|
- /// If true, this indicates that the test model suffered an error
|
|
|
|
- /// during execution such as an invalid state, event, or exception thrown by
|
|
|
|
- /// a state handler. The flag is only set true by onModelFailure() method.
|
|
|
|
- bool getModelFailureCalled() {
|
|
|
|
- return (model_failure_called_);
|
|
|
|
|
|
+ /// This value is set only via onModelFailure and it stores whatever
|
|
|
|
+ /// explanation that method was passed.
|
|
|
|
+ const std::string& getFailureExplanation() {
|
|
|
|
+ return (failure_explanation_);
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief Returns indication of whether or not the model succeeded.
|
|
/// @brief Returns indication of whether or not the model succeeded.
|
|
@@ -131,6 +136,12 @@ public:
|
|
work_completed_ = true;
|
|
work_completed_ = true;
|
|
transition(DONE_ST, ALL_DONE_EVT);
|
|
transition(DONE_ST, ALL_DONE_EVT);
|
|
break;
|
|
break;
|
|
|
|
+ case FORCE_UNDEFINED_ST_EVT:
|
|
|
|
+ transition(9999, ALL_DONE_EVT);
|
|
|
|
+ break;
|
|
|
|
+ case SIMULATE_ERROR_EVT:
|
|
|
|
+ throw std::logic_error("Simulated Unexpected Error");
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
// its bogus
|
|
// its bogus
|
|
isc_throw(StateModelError, "doWorkHandler:invalid event: "
|
|
isc_throw(StateModelError, "doWorkHandler:invalid event: "
|
|
@@ -154,79 +165,116 @@ public:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// @brief Construct the event dictionary.
|
|
virtual void defineEvents() {
|
|
virtual void defineEvents() {
|
|
|
|
+ // Invoke the base call implementation first.
|
|
StateModel::defineEvents();
|
|
StateModel::defineEvents();
|
|
|
|
+
|
|
|
|
+ // Define our events.
|
|
defineEvent(WORK_START_EVT, "WORK_START_EVT");
|
|
defineEvent(WORK_START_EVT, "WORK_START_EVT");
|
|
defineEvent(WORK_DONE_EVT , "WORK_DONE_EVT");
|
|
defineEvent(WORK_DONE_EVT , "WORK_DONE_EVT");
|
|
defineEvent(ALL_DONE_EVT, "ALL_DONE_EVT");
|
|
defineEvent(ALL_DONE_EVT, "ALL_DONE_EVT");
|
|
|
|
+ defineEvent(FORCE_UNDEFINED_ST_EVT, "FORCE_UNDEFINED_ST_EVT");
|
|
|
|
+ defineEvent(SIMULATE_ERROR_EVT, "SIMULATE_ERROR_EVT");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// @brief Verify the event dictionary.
|
|
virtual void verifyEvents() {
|
|
virtual void verifyEvents() {
|
|
|
|
+ // Invoke the base call implementation first.
|
|
StateModel::verifyEvents();
|
|
StateModel::verifyEvents();
|
|
|
|
+
|
|
|
|
+ // Verify our events.
|
|
getEvent(WORK_START_EVT);
|
|
getEvent(WORK_START_EVT);
|
|
getEvent(WORK_DONE_EVT);
|
|
getEvent(WORK_DONE_EVT);
|
|
getEvent(ALL_DONE_EVT);
|
|
getEvent(ALL_DONE_EVT);
|
|
|
|
+ getEvent(FORCE_UNDEFINED_ST_EVT);
|
|
|
|
+ getEvent(SIMULATE_ERROR_EVT);
|
|
}
|
|
}
|
|
|
|
|
|
- /// @brief Initializes the state handler map.
|
|
|
|
- virtual void initStateHandlerMap() {
|
|
|
|
- addToStateHandlerMap(DUMMY_ST,
|
|
|
|
- boost::bind(&StateModelTest::dummyHandler, this));
|
|
|
|
|
|
+ /// @brief Construct the state dictionary.
|
|
|
|
+ virtual void defineStates() {
|
|
|
|
+ // Invoke the base call implementation first.
|
|
|
|
+ StateModel::defineStates();
|
|
|
|
+
|
|
|
|
+ // Define our states.
|
|
|
|
+ defineState(DUMMY_ST, "DUMMY_ST",
|
|
|
|
+ boost::bind(&StateModelTest::dummyHandler, this));
|
|
|
|
|
|
- addToStateHandlerMap(READY_ST,
|
|
|
|
|
|
+ defineState(READY_ST, "READY_ST",
|
|
boost::bind(&StateModelTest::readyHandler, this));
|
|
boost::bind(&StateModelTest::readyHandler, this));
|
|
|
|
|
|
- addToStateHandlerMap(DO_WORK_ST,
|
|
|
|
|
|
+ defineState(DO_WORK_ST, "DO_WORK_ST",
|
|
boost::bind(&StateModelTest::doWorkHandler, this));
|
|
boost::bind(&StateModelTest::doWorkHandler, this));
|
|
|
|
|
|
- addToStateHandlerMap(DONE_ST,
|
|
|
|
|
|
+ defineState(DONE_ST, "DONE_ST",
|
|
boost::bind(&StateModelTest::doneWorkHandler, this));
|
|
boost::bind(&StateModelTest::doneWorkHandler, this));
|
|
}
|
|
}
|
|
|
|
|
|
- /// @brief Validates the contents of the state handler map.
|
|
|
|
- virtual void verifyStateHandlerMap() {
|
|
|
|
- getStateHandler(DUMMY_ST);
|
|
|
|
- getStateHandler(READY_ST);
|
|
|
|
- getStateHandler(DO_WORK_ST);
|
|
|
|
- getStateHandler(DONE_ST);
|
|
|
|
|
|
+ /// @brief Verify the state dictionary.
|
|
|
|
+ virtual void verifyStates() {
|
|
|
|
+ // Invoke the base call implementation first.
|
|
|
|
+ StateModel::verifyStates();
|
|
|
|
+
|
|
|
|
+ // Verify our states.
|
|
|
|
+ getState(DUMMY_ST);
|
|
|
|
+ getState(READY_ST);
|
|
|
|
+ getState(DO_WORK_ST);
|
|
|
|
+ getState(DONE_ST);
|
|
}
|
|
}
|
|
|
|
|
|
- /// @brief Handler called when the model suffers an execution error.
|
|
|
|
- virtual void onModelFailure() {
|
|
|
|
- model_failure_called_ = true;
|
|
|
|
|
|
+ /// @brief Manually construct the event and state dictionaries.
|
|
|
|
+ /// This allows testing without running startModel.
|
|
|
|
+ void initDictionaires() {
|
|
|
|
+ ASSERT_NO_THROW(defineEvents());
|
|
|
|
+ ASSERT_NO_THROW(verifyEvents());
|
|
|
|
+ ASSERT_NO_THROW(defineStates());
|
|
|
|
+ ASSERT_NO_THROW(verifyStates());
|
|
}
|
|
}
|
|
|
|
|
|
- const char* getStateLabel(const int state) const {
|
|
|
|
- const char* str = "Unknown";
|
|
|
|
- switch(state) {
|
|
|
|
- case DUMMY_ST:
|
|
|
|
- str = "StateModelTest::DUMMY_ST";
|
|
|
|
- break;
|
|
|
|
- case READY_ST:
|
|
|
|
- str = "StateModelTest::READY_ST";
|
|
|
|
- break;
|
|
|
|
- case DO_WORK_ST:
|
|
|
|
- str = "StateModelTest::DO_WORK_ST";
|
|
|
|
- break;
|
|
|
|
- case DONE_ST:
|
|
|
|
- str = "StateModelTest::DONE_ST";
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- str = StateModel::getStateLabel(state);
|
|
|
|
- break;
|
|
|
|
|
|
+ /// @brief Tests the event dictionary entry for the given event value.
|
|
|
|
+ bool checkEvent(const int value, const std::string& label) {
|
|
|
|
+ EventPtr event;
|
|
|
|
+ try {
|
|
|
|
+ event = getEvent(value);
|
|
|
|
+ EXPECT_TRUE(event);
|
|
|
|
+ EXPECT_EQ(value, event->getValue());
|
|
|
|
+ EXPECT_EQ(label, std::string(event->getLabel()));
|
|
|
|
+ } catch (const std::exception& ex) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// @brief Tests the state dictionary entry for the given state value.
|
|
|
|
+ bool checkState(const int value, const std::string& label) {
|
|
|
|
+ EventPtr state;
|
|
|
|
+ try {
|
|
|
|
+ state = getState(value);
|
|
|
|
+ EXPECT_TRUE(state);
|
|
|
|
+ EXPECT_EQ(value, state->getValue());
|
|
|
|
+ EXPECT_EQ(label, std::string(state->getLabel()));
|
|
|
|
+ } catch (const std::exception& ex) {
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
- return (str);
|
|
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /// @brief Handler called when the model suffers an execution error.
|
|
|
|
+ virtual void onModelFailure(const std::string& explanation) {
|
|
|
|
+ failure_explanation_ = explanation;
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief Indicator of whether or not the DUMMY_ST handler has been called.
|
|
/// @brief Indicator of whether or not the DUMMY_ST handler has been called.
|
|
bool dummy_called_;
|
|
bool dummy_called_;
|
|
|
|
|
|
- /// @brief Indicator of whether or not onModelError has been called.
|
|
|
|
- bool model_failure_called_;
|
|
|
|
-
|
|
|
|
/// @brief Indicator of whether or not DONE_ST handler has been called.
|
|
/// @brief Indicator of whether or not DONE_ST handler has been called.
|
|
bool work_completed_;
|
|
bool work_completed_;
|
|
|
|
+
|
|
|
|
+ /// @brief Stores the failure explanation
|
|
|
|
+ std::string failure_explanation_;
|
|
};
|
|
};
|
|
|
|
|
|
// Declare them so gtest can see them.
|
|
// Declare them so gtest can see them.
|
|
@@ -238,129 +286,173 @@ const int StateModelTest::WORK_START_EVT;
|
|
const int StateModelTest::WORK_DONE_EVT;
|
|
const int StateModelTest::WORK_DONE_EVT;
|
|
const int StateModelTest::ALL_DONE_EVT;
|
|
const int StateModelTest::ALL_DONE_EVT;
|
|
|
|
|
|
-/// @brief Tests the fundamental methods used for state handler mapping.
|
|
|
|
-/// Verifies the ability to search for and add entries in the state handler map.
|
|
|
|
-TEST_F(StateModelTest, basicStateMapping) {
|
|
|
|
- // After construction, the state map should be empty. Verify that
|
|
|
|
- // getStateHandler will throw when, state cannot be found.
|
|
|
|
- EXPECT_THROW(getStateHandler(READY_ST), StateModelError);
|
|
|
|
|
|
+/// @brief Checks the fundamentals of defining and retrieving events.
|
|
|
|
+TEST_F(StateModelTest, eventDefinition) {
|
|
|
|
+ // After construction, the event dictionary should be empty. Verify that
|
|
|
|
+ // getEvent will throw when event is not defined.
|
|
|
|
+ EXPECT_THROW(getEvent(NOP_EVT), StateModelError);
|
|
|
|
|
|
// Verify that we can add a handler to the map.
|
|
// Verify that we can add a handler to the map.
|
|
- ASSERT_NO_THROW(addToStateHandlerMap(READY_ST,
|
|
|
|
- boost::bind(&StateModelTest::
|
|
|
|
- dummyHandler, this)));
|
|
|
|
|
|
+ ASSERT_NO_THROW(defineEvent(NOP_EVT, "NOP_EVT"));
|
|
|
|
|
|
- // Verify that we can find the handler by its state.
|
|
|
|
- StateHandler retreived_handler;
|
|
|
|
- EXPECT_NO_THROW(retreived_handler = getStateHandler(READY_ST));
|
|
|
|
|
|
+ // Verify that we can find the event by value and its content is correct.
|
|
|
|
+ EXPECT_TRUE(checkEvent(NOP_EVT, "NOP_EVT"));
|
|
|
|
|
|
- // Now we will Verify that retrieved handler executes the correct method.
|
|
|
|
- // Make sure the dummy called flag is false prior to invocation.
|
|
|
|
- EXPECT_FALSE(getDummyCalled());
|
|
|
|
-
|
|
|
|
- // Invoke the retreived handler.
|
|
|
|
- ASSERT_NO_THROW((retreived_handler)());
|
|
|
|
|
|
+ // Verify that we cannot add a duplicate.
|
|
|
|
+ ASSERT_THROW(defineEvent(NOP_EVT, "NOP_EVT"), StateModelError);
|
|
|
|
|
|
- // Verify the dummy called flag is now true.
|
|
|
|
- EXPECT_TRUE(getDummyCalled());
|
|
|
|
|
|
+ // Verify that we can still find the event.
|
|
|
|
+ EXPECT_TRUE(checkEvent(NOP_EVT, "NOP_EVT"));
|
|
|
|
+}
|
|
|
|
|
|
- // Verify that we cannot add a duplicate.
|
|
|
|
- EXPECT_THROW(addToStateHandlerMap(READY_ST,
|
|
|
|
- boost::bind(&StateModelTest::readyHandler,
|
|
|
|
- this)),
|
|
|
|
- StateModelError);
|
|
|
|
|
|
+/// @brief Tests event dictionary construction and verification.
|
|
|
|
+TEST_F(StateModelTest, eventDictionary) {
|
|
|
|
+ // After construction, the event dictionary should be empty.
|
|
|
|
+ // Make sure that verifyEvents() throws.
|
|
|
|
+ EXPECT_THROW(verifyEvents(), StateModelError);
|
|
|
|
+
|
|
|
|
+ // Construct the dictionary and verify it.
|
|
|
|
+ EXPECT_NO_THROW(defineEvents());
|
|
|
|
+ EXPECT_NO_THROW(verifyEvents());
|
|
|
|
+
|
|
|
|
+ // Verify base class events are defined.
|
|
|
|
+ EXPECT_TRUE(checkEvent(NOP_EVT, "NOP_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(START_EVT, "START_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(END_EVT, "END_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(FAIL_EVT, "FAIL_EVT"));
|
|
|
|
+
|
|
|
|
+ // Verify stub class events are defined.
|
|
|
|
+ EXPECT_TRUE(checkEvent(WORK_START_EVT, "WORK_START_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(WORK_DONE_EVT, "WORK_DONE_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(ALL_DONE_EVT, "ALL_DONE_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(FORCE_UNDEFINED_ST_EVT, "FORCE_UNDEFINED_ST_EVT"));
|
|
|
|
+ EXPECT_TRUE(checkEvent(SIMULATE_ERROR_EVT, "SIMULATE_ERROR_EVT"));
|
|
|
|
+
|
|
|
|
+ // Verify that undefined events are handled correctly.
|
|
|
|
+ EXPECT_THROW(getEvent(9999), StateModelError);
|
|
|
|
+ EXPECT_EQ(LabeledValueSet::UNDEFINED_LABEL, getEventLabel(9999));
|
|
|
|
+}
|
|
|
|
|
|
- // Verify that we can still find the handler by its state.
|
|
|
|
- EXPECT_NO_THROW(getStateHandler(READY_ST));
|
|
|
|
|
|
+/// @brief General testing of event context accessors.
|
|
|
|
+/// Most if not all of these are also tested as a byproduct off larger tests.
|
|
|
|
+TEST_F(StateModelTest, eventContextAccessors) {
|
|
|
|
+ // Construct the event definitions, normally done by startModel.
|
|
|
|
+ ASSERT_NO_THROW(defineEvents());
|
|
|
|
+ ASSERT_NO_THROW(verifyEvents());
|
|
|
|
|
|
|
|
+ // Verify the post-construction values.
|
|
|
|
+ EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
+ EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
|
|
|
|
- // Verify that we cannot add a handler for NEW_ST.
|
|
|
|
- EXPECT_THROW(addToStateHandlerMap(NEW_ST,
|
|
|
|
- boost::bind(&StateModelTest::dummyHandler,
|
|
|
|
- this)),
|
|
|
|
- StateModelError);
|
|
|
|
|
|
+ // Call setEvent which will update both next event and last event.
|
|
|
|
+ EXPECT_NO_THROW(postNextEvent(START_EVT));
|
|
|
|
|
|
- // Verify that we cannot add a handler for END_ST.
|
|
|
|
- EXPECT_THROW(addToStateHandlerMap(END_ST,
|
|
|
|
- boost::bind(&StateModelTest::dummyHandler,
|
|
|
|
- this)),
|
|
|
|
- StateModelError);
|
|
|
|
-}
|
|
|
|
|
|
+ // Verify the values are what we expect.
|
|
|
|
+ EXPECT_EQ(START_EVT, getNextEvent());
|
|
|
|
+ EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
|
|
|
|
-/// @brief Tests state map initialization and validation.
|
|
|
|
-/// This tests the basic concept of state map initialization and verification
|
|
|
|
-/// by manually invoking the map methods normally called by startModel.
|
|
|
|
-TEST_F(StateModelTest, stateMapInit) {
|
|
|
|
- // Verify that the map validation throws prior to the map being
|
|
|
|
- // initialized.
|
|
|
|
- EXPECT_THROW(verifyStateHandlerMap(), StateModelError);
|
|
|
|
|
|
+ // Call setEvent again.
|
|
|
|
+ EXPECT_NO_THROW(postNextEvent(WORK_START_EVT));
|
|
|
|
|
|
- // Call initStateHandlerMap to initialize the state map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
|
|
+ // Verify the values are what we expect.
|
|
|
|
+ EXPECT_EQ(WORK_START_EVT, getNextEvent());
|
|
|
|
+ EXPECT_EQ(START_EVT, getLastEvent());
|
|
|
|
|
|
- // Verify that the map validation succeeds now that the map is initialized.
|
|
|
|
- EXPECT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ // Verify that posting an undefined event throws.
|
|
|
|
+ EXPECT_THROW(postNextEvent(9999), StateModelError);
|
|
}
|
|
}
|
|
|
|
|
|
-/// @brief Tests the ability to decode state values into text labels.
|
|
|
|
-TEST_F(StateModelTest, stateLabels) {
|
|
|
|
- // Verify base class labels.
|
|
|
|
- EXPECT_EQ("StateModel::NEW_ST", getStateLabel(NEW_ST));
|
|
|
|
- EXPECT_EQ("StateModel::END_ST", getStateLabel(END_ST));
|
|
|
|
-
|
|
|
|
- // Verify stub class labels.
|
|
|
|
- EXPECT_EQ("StateModelTest::DUMMY_ST", getStateLabel(DUMMY_ST));
|
|
|
|
- EXPECT_EQ("StateModelTest::READY_ST", getStateLabel(READY_ST));
|
|
|
|
- EXPECT_EQ("StateModelTest::DO_WORK_ST", getStateLabel(DO_WORK_ST));
|
|
|
|
- EXPECT_EQ("StateModelTest::DONE_ST", getStateLabel(DONE_ST));
|
|
|
|
|
|
+/// @brief Tests the fundamental methods used for state handler mapping.
|
|
|
|
+/// Verifies the ability to search for and add entries in the state handler map.
|
|
|
|
+TEST_F(StateModelTest, stateDefinition) {
|
|
|
|
+ // After construction, the state dictionary should be empty. Verify that
|
|
|
|
+ // getState will throw when, state is not defined.
|
|
|
|
+ EXPECT_THROW(getState(READY_ST), StateModelError);
|
|
|
|
+
|
|
|
|
+ // Verify that we can add a state to the dictionary.
|
|
|
|
+ ASSERT_NO_THROW(defineState(READY_ST, "READY_ST",
|
|
|
|
+ boost::bind(&StateModelTest::dummyHandler,
|
|
|
|
+ this)));
|
|
|
|
+
|
|
|
|
+ // Verify that we can find the state by its value.
|
|
|
|
+ StatePtr state;
|
|
|
|
+ EXPECT_NO_THROW(state = getState(READY_ST));
|
|
|
|
+ EXPECT_TRUE(state);
|
|
|
|
+
|
|
|
|
+ // Verify the state's value and label.
|
|
|
|
+ EXPECT_EQ(READY_ST, state->getValue());
|
|
|
|
+ EXPECT_EQ("READY_ST", std::string(state->getLabel()));
|
|
|
|
+
|
|
|
|
+ // Now verify that retrieved state's handler executes the correct method.
|
|
|
|
+ // Make sure the dummy called flag is false prior to invocation.
|
|
|
|
+ EXPECT_FALSE(getDummyCalled());
|
|
|
|
|
|
- // Verify unknown state.
|
|
|
|
- EXPECT_EQ("Unknown", getStateLabel(-1));
|
|
|
|
-}
|
|
|
|
|
|
+ // Invoke the state's handler.
|
|
|
|
+ EXPECT_NO_THROW(state->run());
|
|
|
|
|
|
-/// @brief Tests the ability to decode event values into text labels.
|
|
|
|
-TEST_F(StateModelTest, eventLabels) {
|
|
|
|
- // Verify base class labels.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
|
|
+ // Verify the dummy called flag is now true.
|
|
|
|
+ EXPECT_TRUE(getDummyCalled());
|
|
|
|
|
|
- EXPECT_EQ("NOP_EVT", std::string(getEventLabel(NOP_EVT)));
|
|
|
|
- EXPECT_EQ("START_EVT", std::string(getEventLabel(START_EVT)));
|
|
|
|
- EXPECT_EQ("END_EVT", std::string(getEventLabel(END_EVT)));
|
|
|
|
- EXPECT_EQ("FAIL_EVT", std::string(getEventLabel(FAIL_EVT)));
|
|
|
|
|
|
+ // Verify that we cannot add a duplicate.
|
|
|
|
+ EXPECT_THROW(defineState(READY_ST, "READY_ST",
|
|
|
|
+ boost::bind(&StateModelTest::readyHandler, this)),
|
|
|
|
+ StateModelError);
|
|
|
|
|
|
- // Verify stub class labels.
|
|
|
|
- EXPECT_EQ("WORK_START_EVT", std::string(getEventLabel(WORK_START_EVT)));
|
|
|
|
- EXPECT_EQ("WORK_DONE_EVT", std::string(getEventLabel(WORK_DONE_EVT)));
|
|
|
|
- EXPECT_EQ("ALL_DONE_EVT", std::string(getEventLabel(ALL_DONE_EVT)));
|
|
|
|
|
|
+ // Verify that we can still find the state.
|
|
|
|
+ EXPECT_NO_THROW(getState(READY_ST));
|
|
|
|
+}
|
|
|
|
|
|
- // Verify unknown state.
|
|
|
|
- EXPECT_EQ(LabeledValueSet::UNDEFINED_LABEL, getEventLabel(-1));
|
|
|
|
|
|
+/// @brief Tests state dictionary initialization and validation.
|
|
|
|
+/// This tests the basic concept of state dictionary initialization and
|
|
|
|
+/// verification by manually invoking the methods normally called by startModel.
|
|
|
|
+TEST_F(StateModelTest, stateDictionary) {
|
|
|
|
+ // Verify that the map validation throws prior to the dictionary being
|
|
|
|
+ // initialized.
|
|
|
|
+ EXPECT_THROW(verifyStates(), StateModelError);
|
|
|
|
+
|
|
|
|
+ // Construct the dictionary and verify it.
|
|
|
|
+ ASSERT_NO_THROW(defineStates());
|
|
|
|
+ EXPECT_NO_THROW(verifyStates());
|
|
|
|
+
|
|
|
|
+ // Verify the base class states.
|
|
|
|
+ EXPECT_TRUE(checkState(NEW_ST, "NEW_ST"));
|
|
|
|
+ EXPECT_TRUE(checkState(END_ST, "END_ST"));
|
|
|
|
+
|
|
|
|
+ // Verify stub class states.
|
|
|
|
+ EXPECT_TRUE(checkState(DUMMY_ST, "DUMMY_ST"));
|
|
|
|
+ EXPECT_TRUE(checkState(READY_ST, "READY_ST"));
|
|
|
|
+ EXPECT_TRUE(checkState(DO_WORK_ST, "DO_WORK_ST"));
|
|
|
|
+ EXPECT_TRUE(checkState(DONE_ST, "DONE_ST"));
|
|
|
|
+
|
|
|
|
+ // Verify that undefined states are handled correctly.
|
|
|
|
+ EXPECT_THROW(getState(9999), StateModelError);
|
|
|
|
+ EXPECT_EQ(LabeledValueSet::UNDEFINED_LABEL,
|
|
|
|
+ std::string(getStateLabel(9999)));
|
|
}
|
|
}
|
|
|
|
|
|
-/// @brief General testing of member accessors.
|
|
|
|
|
|
+/// @brief General testing of state context accessors.
|
|
/// Most if not all of these are also tested as a byproduct off larger tests.
|
|
/// Most if not all of these are also tested as a byproduct off larger tests.
|
|
-TEST_F(StateModelTest, stateAccessors) {
|
|
|
|
|
|
+TEST_F(StateModelTest, stateContextAccessors) {
|
|
// setState will throw unless we initialize the handler map.
|
|
// setState will throw unless we initialize the handler map.
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ ASSERT_NO_THROW(defineStates());
|
|
|
|
+ ASSERT_NO_THROW(verifyStates());
|
|
|
|
|
|
// Verify post-construction state values.
|
|
// Verify post-construction state values.
|
|
- EXPECT_EQ(NEW_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(NEW_ST, getCurrState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
|
|
|
|
// Call setState which will update both state and previous state.
|
|
// Call setState which will update both state and previous state.
|
|
EXPECT_NO_THROW(setState(READY_ST));
|
|
EXPECT_NO_THROW(setState(READY_ST));
|
|
|
|
|
|
// Verify the values are what we expect.
|
|
// Verify the values are what we expect.
|
|
- EXPECT_EQ(READY_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(READY_ST, getCurrState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
|
|
|
|
// Call setState again.
|
|
// Call setState again.
|
|
EXPECT_NO_THROW(setState(DO_WORK_ST));
|
|
EXPECT_NO_THROW(setState(DO_WORK_ST));
|
|
|
|
|
|
// Verify the values are what we expect.
|
|
// Verify the values are what we expect.
|
|
- EXPECT_EQ(DO_WORK_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(DO_WORK_ST, getCurrState());
|
|
EXPECT_EQ(READY_ST, getPrevState());
|
|
EXPECT_EQ(READY_ST, getPrevState());
|
|
|
|
|
|
// Verify that calling setState with an state that has no handler
|
|
// Verify that calling setState with an state that has no handler
|
|
@@ -372,45 +464,39 @@ TEST_F(StateModelTest, stateAccessors) {
|
|
|
|
|
|
// Verify that calling setState with END_ST is ok.
|
|
// Verify that calling setState with END_ST is ok.
|
|
EXPECT_NO_THROW(setState(END_ST));
|
|
EXPECT_NO_THROW(setState(END_ST));
|
|
-}
|
|
|
|
-
|
|
|
|
-TEST_F(StateModelTest, eventAccessors) {
|
|
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
|
|
|
|
- EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
- EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
|
|
|
|
+ // Verify that calling setState with an undefined state throws.
|
|
|
|
+ EXPECT_THROW(setState(9999), StateModelError);
|
|
|
|
+}
|
|
|
|
|
|
- // Call setEvent which will update both next event and last event.
|
|
|
|
- EXPECT_NO_THROW(postNextEvent(START_EVT));
|
|
|
|
|
|
+/// @brief Checks that invoking runModel prior to startModel is not allowed.
|
|
|
|
+TEST_F(StateModelTest, runBeforeStart) {
|
|
|
|
+ // Verify that the failure explanation is empty and work is not done.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
|
|
|
|
- // Verify the values are what we expect.
|
|
|
|
- EXPECT_EQ(START_EVT, getNextEvent());
|
|
|
|
- EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
|
|
|
|
+ // Attempt to call runModel before startModel. This should result in an
|
|
|
|
+ // orderly model failure.
|
|
|
|
+ ASSERT_NO_THROW(runModel(START_EVT));
|
|
|
|
|
|
- // Call setEvent again.
|
|
|
|
- EXPECT_NO_THROW(postNextEvent(WORK_START_EVT));
|
|
|
|
- EXPECT_EQ(WORK_START_EVT, getNextEvent());
|
|
|
|
- EXPECT_EQ(START_EVT, getLastEvent());
|
|
|
|
|
|
+ // Check that state and event are correct.
|
|
|
|
+ EXPECT_EQ(END_ST, getCurrState());
|
|
|
|
+ EXPECT_EQ(FAIL_EVT, getNextEvent());
|
|
|
|
|
|
- // Verify the values are what we expect.
|
|
|
|
|
|
+ // Verify that failure explanation is not empty.
|
|
|
|
+ EXPECT_FALSE(getFailureExplanation().empty());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Tests that the endModel may be used to transition the model to
|
|
|
|
+/// a normal conclusion.
|
|
TEST_F(StateModelTest, transitionWithEnd) {
|
|
TEST_F(StateModelTest, transitionWithEnd) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ // Init dictionaries manually, normally done by startModel.
|
|
|
|
+ initDictionaires();
|
|
|
|
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
|
|
|
|
// Verify that state and event members are as expected.
|
|
// Verify that state and event members are as expected.
|
|
- EXPECT_EQ(DUMMY_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(DUMMY_ST, getCurrState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(START_EVT, getNextEvent());
|
|
EXPECT_EQ(START_EVT, getNextEvent());
|
|
EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
@@ -419,48 +505,42 @@ TEST_F(StateModelTest, transitionWithEnd) {
|
|
EXPECT_NO_THROW(endModel());
|
|
EXPECT_NO_THROW(endModel());
|
|
|
|
|
|
// Verify state and event members are correctly set.
|
|
// Verify state and event members are correctly set.
|
|
- EXPECT_EQ(END_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(END_ST, getCurrState());
|
|
EXPECT_EQ(DUMMY_ST, getPrevState());
|
|
EXPECT_EQ(DUMMY_ST, getPrevState());
|
|
EXPECT_EQ(END_EVT, getNextEvent());
|
|
EXPECT_EQ(END_EVT, getNextEvent());
|
|
EXPECT_EQ(START_EVT, getLastEvent());
|
|
EXPECT_EQ(START_EVT, getLastEvent());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Tests that the abortModel may be used to transition the model to
|
|
|
|
+/// failed conclusion.
|
|
TEST_F(StateModelTest, transitionWithAbort) {
|
|
TEST_F(StateModelTest, transitionWithAbort) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ // Init dictionaries manually, normally done by startModel.
|
|
|
|
+ initDictionaires();
|
|
|
|
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
|
|
|
|
// Verify that state and event members are as expected.
|
|
// Verify that state and event members are as expected.
|
|
- EXPECT_EQ(DUMMY_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(DUMMY_ST, getCurrState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(NEW_ST, getPrevState());
|
|
EXPECT_EQ(START_EVT, getNextEvent());
|
|
EXPECT_EQ(START_EVT, getNextEvent());
|
|
EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
EXPECT_EQ(NOP_EVT, getLastEvent());
|
|
|
|
|
|
// Call endModel to transition us to the end of the model.
|
|
// Call endModel to transition us to the end of the model.
|
|
- EXPECT_NO_THROW(abortModel());
|
|
|
|
|
|
+ EXPECT_NO_THROW(abortModel("test invocation"));
|
|
|
|
|
|
// Verify state and event members are correctly set.
|
|
// Verify state and event members are correctly set.
|
|
- EXPECT_EQ(END_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(END_ST, getCurrState());
|
|
EXPECT_EQ(DUMMY_ST, getPrevState());
|
|
EXPECT_EQ(DUMMY_ST, getPrevState());
|
|
EXPECT_EQ(FAIL_EVT, getNextEvent());
|
|
EXPECT_EQ(FAIL_EVT, getNextEvent());
|
|
EXPECT_EQ(START_EVT, getLastEvent());
|
|
EXPECT_EQ(START_EVT, getLastEvent());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Tests that the boolean indicators for on state entry and exit
|
|
|
|
+/// work properly.
|
|
TEST_F(StateModelTest, doFlags) {
|
|
TEST_F(StateModelTest, doFlags) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ // Init dictionaries manually, normally done by startModel.
|
|
|
|
+ initDictionaires();
|
|
|
|
|
|
// Verify that "do" flags are false.
|
|
// Verify that "do" flags are false.
|
|
EXPECT_FALSE(doOnEntry());
|
|
EXPECT_FALSE(doOnEntry());
|
|
@@ -486,14 +566,12 @@ TEST_F(StateModelTest, doFlags) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Verifies that the model status methods accurately reflect the model
|
|
|
|
+/// status. It also verifies that the dictionaries can be modified before
|
|
|
|
+/// the model is running but not after.
|
|
TEST_F(StateModelTest, statusMethods) {
|
|
TEST_F(StateModelTest, statusMethods) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
- ASSERT_NO_THROW(defineEvents());
|
|
|
|
- ASSERT_NO_THROW(verifyEvents());
|
|
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ // Init dictionaries manually, normally done by startModel.
|
|
|
|
+ initDictionaires();
|
|
|
|
|
|
// After construction, state model is "new", all others should be false.
|
|
// After construction, state model is "new", all others should be false.
|
|
EXPECT_TRUE(isModelNew());
|
|
EXPECT_TRUE(isModelNew());
|
|
@@ -502,19 +580,23 @@ TEST_F(StateModelTest, statusMethods) {
|
|
EXPECT_FALSE(isModelDone());
|
|
EXPECT_FALSE(isModelDone());
|
|
EXPECT_FALSE(didModelFail());
|
|
EXPECT_FALSE(didModelFail());
|
|
|
|
|
|
- // verify that you can add to the before the model has started.
|
|
|
|
- EXPECT_NO_THROW(addToStateHandlerMap(9998,
|
|
|
|
- boost::bind(&StateModelTest::
|
|
|
|
- readyHandler, this)));
|
|
|
|
|
|
+ // Verify that events and states can be added before the model is started.
|
|
|
|
+ EXPECT_NO_THROW(defineEvent(9998, "9998"));
|
|
|
|
+ EXPECT_NO_THROW(defineState(9998, "9998",
|
|
|
|
+ boost::bind(&StateModelTest::readyHandler,
|
|
|
|
+ this)));
|
|
|
|
|
|
- // call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
|
|
|
|
+ // "START" the model.
|
|
|
|
+ // Fake out starting the model by calling transition to move from NEW_ST
|
|
|
|
+ // to DUMMY_ST with START_EVT. If we used startModel this would blow by
|
|
|
|
+ // the status of "running" but not "waiting".
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
|
|
|
|
|
|
|
|
- // verify that you cannot add to the map once the model has started.
|
|
|
|
- EXPECT_THROW(addToStateHandlerMap(9999,
|
|
|
|
- boost::bind(&StateModelTest::readyHandler,
|
|
|
|
- this)),
|
|
|
|
|
|
+ // Verify that events and states cannot be added after the model is started.
|
|
|
|
+ EXPECT_THROW(defineEvent(9999, "9999"), StateModelError);
|
|
|
|
+ EXPECT_THROW(defineState(9999, "9999",
|
|
|
|
+ boost::bind(&StateModelTest::readyHandler, this)),
|
|
StateModelError);
|
|
StateModelError);
|
|
|
|
|
|
// The state and event combos set above, should show the model as
|
|
// The state and event combos set above, should show the model as
|
|
@@ -547,20 +629,20 @@ TEST_F(StateModelTest, statusMethods) {
|
|
EXPECT_FALSE(didModelFail());
|
|
EXPECT_FALSE(didModelFail());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Tests that the model status methods are correct after a model
|
|
|
|
+/// failure.
|
|
TEST_F(StateModelTest, statusMethodsOnFailure) {
|
|
TEST_F(StateModelTest, statusMethodsOnFailure) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
|
|
+ // Construct the event and state definitions, normally done by startModel.
|
|
ASSERT_NO_THROW(defineEvents());
|
|
ASSERT_NO_THROW(defineEvents());
|
|
ASSERT_NO_THROW(verifyEvents());
|
|
ASSERT_NO_THROW(verifyEvents());
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ ASSERT_NO_THROW(defineStates());
|
|
|
|
+ ASSERT_NO_THROW(verifyStates());
|
|
|
|
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
// call transition to move from NEW_ST to DUMMY_ST with START_EVT
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
EXPECT_NO_THROW(transition(DUMMY_ST, START_EVT));
|
|
|
|
|
|
// Call endModel to transition us to the end of the model.
|
|
// Call endModel to transition us to the end of the model.
|
|
- EXPECT_NO_THROW(abortModel());
|
|
|
|
|
|
+ EXPECT_NO_THROW(abortModel("test invocation"));
|
|
|
|
|
|
// With state set to END_ST, model should be done.
|
|
// With state set to END_ST, model should be done.
|
|
EXPECT_FALSE(isModelNew());
|
|
EXPECT_FALSE(isModelNew());
|
|
@@ -570,44 +652,92 @@ TEST_F(StateModelTest, statusMethodsOnFailure) {
|
|
EXPECT_TRUE(didModelFail());
|
|
EXPECT_TRUE(didModelFail());
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// @brief Checks that the context strings accurately reflect context and
|
|
|
|
+/// are safe to invoke.
|
|
TEST_F(StateModelTest, contextStrs) {
|
|
TEST_F(StateModelTest, contextStrs) {
|
|
- // Construct the event definitions, normally done by startModel.
|
|
|
|
|
|
+ // Verify context methods do not throw prior to dictionary init.
|
|
|
|
+ ASSERT_NO_THROW(getContextStr());
|
|
|
|
+ ASSERT_NO_THROW(getPrevContextStr());
|
|
|
|
+
|
|
|
|
+ // Construct the event and state definitions, normally done by startModel.
|
|
ASSERT_NO_THROW(defineEvents());
|
|
ASSERT_NO_THROW(defineEvents());
|
|
ASSERT_NO_THROW(verifyEvents());
|
|
ASSERT_NO_THROW(verifyEvents());
|
|
-
|
|
|
|
- // Manually init the handlers map.
|
|
|
|
- ASSERT_NO_THROW(initStateHandlerMap());
|
|
|
|
- ASSERT_NO_THROW(verifyStateHandlerMap());
|
|
|
|
|
|
+ ASSERT_NO_THROW(defineStates());
|
|
|
|
+ ASSERT_NO_THROW(verifyStates());
|
|
|
|
|
|
// transition uses setState and setEvent, testing it tests all three.
|
|
// transition uses setState and setEvent, testing it tests all three.
|
|
EXPECT_NO_THROW(transition(READY_ST, START_EVT));
|
|
EXPECT_NO_THROW(transition(READY_ST, START_EVT));
|
|
|
|
|
|
- std::string ctx_str = getContextStr();
|
|
|
|
|
|
+ // Verify the current context string depicts correct state and event.
|
|
|
|
+ std::string ctx_str;
|
|
|
|
+ ASSERT_NO_THROW(ctx_str = getContextStr());
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getStateLabel(READY_ST)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getStateLabel(READY_ST)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getEventLabel(START_EVT)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getEventLabel(START_EVT)));
|
|
|
|
|
|
- ctx_str = getPrevContextStr();
|
|
|
|
|
|
+ // Verify the previous context string depicts correct state and event.
|
|
|
|
+ ASSERT_NO_THROW(ctx_str = getPrevContextStr());
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getStateLabel(NEW_ST)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getStateLabel(NEW_ST)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getEventLabel(NOP_EVT)));
|
|
EXPECT_NE(std::string::npos, ctx_str.find(getEventLabel(NOP_EVT)));
|
|
}
|
|
}
|
|
|
|
|
|
-/// @brief Tests that invalid states are handled gracefully.
|
|
|
|
-/// This test verifies that attempting to execute a state which has no handler
|
|
|
|
-/// results in a failed model.
|
|
|
|
-TEST_F(StateModelTest, invalidState) {
|
|
|
|
- // First, verify state is NEW_ST and that NEW_ST has no handler.
|
|
|
|
- // This is the state that runModel will attempt to execute.
|
|
|
|
- ASSERT_EQ(NEW_ST, getState());
|
|
|
|
- ASSERT_THROW(getStateHandler(NEW_ST), StateModelError);
|
|
|
|
-
|
|
|
|
- // Verify that the StateModelTest's outcome flags are both false.
|
|
|
|
- EXPECT_FALSE(getModelFailureCalled());
|
|
|
|
|
|
+/// @brief Tests that undefined states are handled gracefully.
|
|
|
|
+/// This test verifies that attempting to transition to an undefined state,
|
|
|
|
+/// which constitutes a model violation, results in an orderly model failure.
|
|
|
|
+TEST_F(StateModelTest, undefinedState) {
|
|
|
|
+ // Verify that the failure explanation is empty and work is not done.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
|
|
|
|
- // Now call runModel() which should not throw, but should result
|
|
|
|
- // in a failed model and a call to onModelFailure().
|
|
|
|
- //EXPECT_NO_THROW(runModel(START_EVT));
|
|
|
|
- (runModel(START_EVT));
|
|
|
|
|
|
+ // First, lets execute the state model to a known valid point, by
|
|
|
|
+ // calling startModel. This should run the model through to DO_WORK_ST.
|
|
|
|
+ ASSERT_NO_THROW(startModel(READY_ST));
|
|
|
|
+
|
|
|
|
+ // Verify we are in the state of DO_WORK_ST with event of NOP_EVT.
|
|
|
|
+ EXPECT_EQ(DO_WORK_ST, getCurrState());
|
|
|
|
+ EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
+
|
|
|
|
+ // Resume the model with next event set to cause the DO_WORK_ST handler
|
|
|
|
+ // to transition to an undefined state. This should cause it to return
|
|
|
|
+ // without throwing and yield a failed model.
|
|
|
|
+ EXPECT_NO_THROW(runModel(FORCE_UNDEFINED_ST_EVT));
|
|
|
|
+
|
|
|
|
+ // Verify that status methods are correct: model is done but failed.
|
|
|
|
+ EXPECT_FALSE(isModelNew());
|
|
|
|
+ EXPECT_FALSE(isModelRunning());
|
|
|
|
+ EXPECT_FALSE(isModelWaiting());
|
|
|
|
+ EXPECT_TRUE(isModelDone());
|
|
|
|
+ EXPECT_TRUE(didModelFail());
|
|
|
|
+
|
|
|
|
+ // Verify that failure explanation is not empty.
|
|
|
|
+ EXPECT_FALSE(getFailureExplanation().empty());
|
|
|
|
+
|
|
|
|
+ // Verify that work completed flag is still false.
|
|
|
|
+ EXPECT_FALSE(getWorkCompleted());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// @brief Tests that an unexpected exception thrown by a state handler is
|
|
|
|
+/// handled gracefully. State models are supposed to account for and handle
|
|
|
|
+/// all errors that they actions (i.e. handlers) may cause. In the event they
|
|
|
|
+/// do not, this constitutes a model violation. This test verifies such
|
|
|
|
+/// violations are handled correctly and result in an orderly model failure.
|
|
|
|
+TEST_F(StateModelTest, unexpectedError) {
|
|
|
|
+ // Verify that the failure explanation is empty and work is not done.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
|
|
+ EXPECT_FALSE(getWorkCompleted());
|
|
|
|
+
|
|
|
|
+ // First, lets execute the state model to a known valid point, by
|
|
|
|
+ // calling startModel with a start state of READY_ST.
|
|
|
|
+ // This should run the model through to DO_WORK_ST.
|
|
|
|
+ ASSERT_NO_THROW(startModel(READY_ST));
|
|
|
|
+
|
|
|
|
+ // Verify we are in the state of DO_WORK_ST with event of NOP_EVT.
|
|
|
|
+ EXPECT_EQ(DO_WORK_ST, getCurrState());
|
|
|
|
+ EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
+
|
|
|
|
+ // Resume the model with next event set to cause the DO_WORK_ST handler
|
|
|
|
+ // to transition to an undefined state. This should cause it to return
|
|
|
|
+ // without throwing and yield a failed model.
|
|
|
|
+ EXPECT_NO_THROW(runModel(SIMULATE_ERROR_EVT));
|
|
|
|
|
|
// Verify that status methods are correct: model is done but failed.
|
|
// Verify that status methods are correct: model is done but failed.
|
|
EXPECT_FALSE(isModelNew());
|
|
EXPECT_FALSE(isModelNew());
|
|
@@ -616,19 +746,20 @@ TEST_F(StateModelTest, invalidState) {
|
|
EXPECT_TRUE(isModelDone());
|
|
EXPECT_TRUE(isModelDone());
|
|
EXPECT_TRUE(didModelFail());
|
|
EXPECT_TRUE(didModelFail());
|
|
|
|
|
|
- // Verify that model failure flag is true.
|
|
|
|
- EXPECT_TRUE(getModelFailureCalled());
|
|
|
|
|
|
+ // Verify that failure explanation is not empty.
|
|
|
|
+ EXPECT_FALSE(getFailureExplanation().empty());
|
|
|
|
|
|
// Verify that work completed flag is still false.
|
|
// Verify that work completed flag is still false.
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
}
|
|
}
|
|
|
|
|
|
-/// @brief Tests that invalid events are handled gracefully.
|
|
|
|
-/// This test verifies that submitting an invalid event to the state machine
|
|
|
|
-/// results in a failed transaction.
|
|
|
|
-TEST_F(StateModelTest, invalidEvent) {
|
|
|
|
- // Verify that the StateModelTest's outcome flags are both false.
|
|
|
|
- EXPECT_FALSE(getModelFailureCalled());
|
|
|
|
|
|
+/// @brief Tests that undefined events are handled gracefully.
|
|
|
|
+/// This test verifies that submitting an undefined event to the state machine
|
|
|
|
+/// results, which constitutes a model violation, results in an orderly model
|
|
|
|
+/// failure.
|
|
|
|
+TEST_F(StateModelTest, undefinedEvent) {
|
|
|
|
+ // Verify that the failure explanation is empty and work is not done.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
|
|
|
|
// First, lets execute the state model to a known valid point, by
|
|
// First, lets execute the state model to a known valid point, by
|
|
@@ -637,13 +768,12 @@ TEST_F(StateModelTest, invalidEvent) {
|
|
ASSERT_NO_THROW(startModel(READY_ST));
|
|
ASSERT_NO_THROW(startModel(READY_ST));
|
|
|
|
|
|
// Verify we are in the state of DO_WORK_ST with event of NOP_EVT.
|
|
// Verify we are in the state of DO_WORK_ST with event of NOP_EVT.
|
|
- EXPECT_EQ(DO_WORK_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(DO_WORK_ST, getCurrState());
|
|
EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
|
|
- // Submitting an invalid event to a valid state, should cause runModel to
|
|
|
|
- // return without throwing and yield a failed model. (Current state is
|
|
|
|
- // DO_WORK_ST, during which START_EVT, is invalid).
|
|
|
|
- EXPECT_NO_THROW(runModel(START_EVT));
|
|
|
|
|
|
+ // Attempting to post an undefined event within runModel should cause it
|
|
|
|
+ // to return without throwing and yield a failed model.
|
|
|
|
+ EXPECT_NO_THROW(runModel(9999));
|
|
|
|
|
|
// Verify that status methods are correct: model is done but failed.
|
|
// Verify that status methods are correct: model is done but failed.
|
|
EXPECT_FALSE(isModelNew());
|
|
EXPECT_FALSE(isModelNew());
|
|
@@ -652,15 +782,15 @@ TEST_F(StateModelTest, invalidEvent) {
|
|
EXPECT_TRUE(isModelDone());
|
|
EXPECT_TRUE(isModelDone());
|
|
EXPECT_TRUE(didModelFail());
|
|
EXPECT_TRUE(didModelFail());
|
|
|
|
|
|
- // Verify that model failure flag is true.
|
|
|
|
- EXPECT_TRUE(getModelFailureCalled());
|
|
|
|
|
|
+ // Verify that failure explanation is not empty.
|
|
|
|
+ EXPECT_FALSE(getFailureExplanation().empty());
|
|
|
|
|
|
// Verify that work completed flag is still false.
|
|
// Verify that work completed flag is still false.
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
}
|
|
}
|
|
|
|
|
|
/// @brief Test the basic mechanics of state model execution.
|
|
/// @brief Test the basic mechanics of state model execution.
|
|
-/// This test exercises the ability to execute state model from state to
|
|
|
|
|
|
+/// This test exercises the ability to execute state model from start to
|
|
/// finish, including the handling of a asynchronous IO operation.
|
|
/// finish, including the handling of a asynchronous IO operation.
|
|
TEST_F(StateModelTest, stateModelTest) {
|
|
TEST_F(StateModelTest, stateModelTest) {
|
|
// Verify that status methods are correct: model is new.
|
|
// Verify that status methods are correct: model is new.
|
|
@@ -669,8 +799,8 @@ TEST_F(StateModelTest, stateModelTest) {
|
|
EXPECT_FALSE(isModelWaiting());
|
|
EXPECT_FALSE(isModelWaiting());
|
|
EXPECT_FALSE(isModelDone());
|
|
EXPECT_FALSE(isModelDone());
|
|
|
|
|
|
- // Verify that the StateModelTest's outcome flags are both false.
|
|
|
|
- EXPECT_FALSE(getModelFailureCalled());
|
|
|
|
|
|
+ // Verify that the failure explanation is empty and work is not done.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
EXPECT_FALSE(getWorkCompleted());
|
|
|
|
|
|
// Launch the transaction by calling startModel. The state model
|
|
// Launch the transaction by calling startModel. The state model
|
|
@@ -680,7 +810,7 @@ TEST_F(StateModelTest, stateModelTest) {
|
|
|
|
|
|
// Verify that we are now in state of DO_WORK_ST, the last event was
|
|
// Verify that we are now in state of DO_WORK_ST, the last event was
|
|
// WORK_START_EVT, the next event is NOP_EVT.
|
|
// WORK_START_EVT, the next event is NOP_EVT.
|
|
- EXPECT_EQ(DO_WORK_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(DO_WORK_ST, getCurrState());
|
|
EXPECT_EQ(WORK_START_EVT, getLastEvent());
|
|
EXPECT_EQ(WORK_START_EVT, getLastEvent());
|
|
EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
EXPECT_EQ(NOP_EVT, getNextEvent());
|
|
|
|
|
|
@@ -691,7 +821,7 @@ TEST_F(StateModelTest, stateModelTest) {
|
|
// Verify that the state model has progressed through to completion:
|
|
// Verify that the state model has progressed through to completion:
|
|
// it is in the DONE_ST, the status is ST_COMPLETED, and the next event
|
|
// it is in the DONE_ST, the status is ST_COMPLETED, and the next event
|
|
// is NOP_EVT.
|
|
// is NOP_EVT.
|
|
- EXPECT_EQ(END_ST, getState());
|
|
|
|
|
|
+ EXPECT_EQ(END_ST, getCurrState());
|
|
EXPECT_EQ(END_EVT, getNextEvent());
|
|
EXPECT_EQ(END_EVT, getNextEvent());
|
|
|
|
|
|
// Verify that status methods are correct: model done.
|
|
// Verify that status methods are correct: model done.
|
|
@@ -700,8 +830,8 @@ TEST_F(StateModelTest, stateModelTest) {
|
|
EXPECT_FALSE(isModelWaiting());
|
|
EXPECT_FALSE(isModelWaiting());
|
|
EXPECT_TRUE(isModelDone());
|
|
EXPECT_TRUE(isModelDone());
|
|
|
|
|
|
- // Verify that model failure flag is false.
|
|
|
|
- EXPECT_FALSE(getModelFailureCalled());
|
|
|
|
|
|
+ // Verify that failure explanation is empty.
|
|
|
|
+ EXPECT_TRUE(getFailureExplanation().empty());
|
|
|
|
|
|
// Verify that work completed flag is true.
|
|
// Verify that work completed flag is true.
|
|
EXPECT_TRUE(getWorkCompleted());
|
|
EXPECT_TRUE(getWorkCompleted());
|