From 53ffd2170f553560b4e0c76009e1fafee4f2167f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel=20Gonz=C3=A1lez=20Santamarta?= Date: Fri, 8 Nov 2024 15:44:38 +0100 Subject: [PATCH] checking if state name is an outcome --- yasmin/include/yasmin/state_machine.hpp | 3 ++- yasmin/src/yasmin/state_machine.cpp | 6 ++++++ yasmin/tests/python/test_state_machine.py | 14 ++++++++++++++ yasmin/yasmin/state_machine.py | 6 +++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/yasmin/include/yasmin/state_machine.hpp b/yasmin/include/yasmin/state_machine.hpp index 3b45688..2d5fea4 100644 --- a/yasmin/include/yasmin/state_machine.hpp +++ b/yasmin/include/yasmin/state_machine.hpp @@ -71,7 +71,8 @@ class StateMachine : public State { * state. * @param transitions A map of transitions where the key is the outcome * and the value is the target state name. - * @throws std::logic_error If the state is already registered. + * @throws std::logic_error If the state is already registered or is an + * outcome. * @throws std::invalid_argument If any transition has empty source or target, * or references unregistered outcomes. */ diff --git a/yasmin/src/yasmin/state_machine.cpp b/yasmin/src/yasmin/state_machine.cpp index 068f54b..d7124ec 100644 --- a/yasmin/src/yasmin/state_machine.cpp +++ b/yasmin/src/yasmin/state_machine.cpp @@ -43,6 +43,12 @@ void StateMachine::add_state(std::string name, std::shared_ptr state, "' already registered in the state machine"); } + if (std::find(this->outcomes.begin(), this->outcomes.end(), name) != + this->outcomes.end()) { + throw std::logic_error("State name '" + name + + "' is already registered as an outcome"); + } + for (auto it = transitions.begin(); it != transitions.end(); ++it) { const std::string &key = it->first; const std::string &value = it->second; diff --git a/yasmin/tests/python/test_state_machine.py b/yasmin/tests/python/test_state_machine.py index e5a1301..c3d9643 100644 --- a/yasmin/tests/python/test_state_machine.py +++ b/yasmin/tests/python/test_state_machine.py @@ -107,6 +107,20 @@ def test_add_repeated_state(self): "\"State 'FOO' already registered in the state machine\"", ) + def test_add_outcome_state(self): + with self.assertRaises(KeyError) as context: + self.sm.add_state( + "outcome4", + FooState(), + transitions={ + "outcome1": "BAR", + }, + ) + self.assertEqual( + str(context.exception), + "\"State name 'outcome4' is already registered as an outcome\"", + ) + def test_add_state_with_wrong_outcome(self): with self.assertRaises(KeyError) as context: self.sm.add_state( diff --git a/yasmin/yasmin/state_machine.py b/yasmin/yasmin/state_machine.py index 8e4ef99..3bb064b 100644 --- a/yasmin/yasmin/state_machine.py +++ b/yasmin/yasmin/state_machine.py @@ -87,7 +87,7 @@ def add_state( transitions (Dict[str, str], optional): A dictionary mapping source outcomes to target states. Defaults to None. Raises: - KeyError: If the state name is already registered. + KeyError: If the state name is already registered or is an outcome. ValueError: If transitions contain empty keys or values. KeyError: If transitions reference unregistered outcomes. """ @@ -102,6 +102,10 @@ def add_state( if name in self._states: raise KeyError(f"State '{name}' already registered in the state machine") + # Check if state name is an outcome of the state machine + if name in self._outcomes: + raise KeyError(f"State name '{name}' is already registered as an outcome") + # Check the transitions for key in transitions: if not key: