Skip to content
Snippets Groups Projects
Commit ff6b5985 authored by Jaime Arias's avatar Jaime Arias
Browse files

Add basic tests for the automaton class

parent 9751caa0
No related branches found
No related tags found
No related merge requests found
#include "automaton.hpp" #include "automaton.hpp"
Automaton::Automaton(State* initial_state): initial_state_(initial_state){ Automaton::Automaton(State *initial_state) : initial_state_(initial_state) {
auto correct_type = initial_state->get_state_type() == StateType::Initial; bool correct_type = initial_state->get_state_type() == StateType::Initial;
assert(("Incorrect type for the parameter initial_state, must be Initial type", correct_type)); if (!correct_type)
++current_id; throw "Incorrect type for the parameter initial_state, must be Initial "
id = current_id; "type";
this->state_ids_.insert(initial_state->get_id());
this->states_.push_back(initial_state);
}
Automaton::~Automaton(){ ++current_id;
delete this->initial_state_; id = current_id;
this->state_ids_.insert(initial_state->get_id());
this->states_.push_back(initial_state);
} }
Automaton::~Automaton() { delete this->initial_state_; }
/* Gets */ /* Gets */
int Automaton::get_id(){ int Automaton::get_id() { return this->id; }
return this->id;
}
State* Automaton::get_initial_state(){ State *Automaton::get_initial_state() { return this->initial_state_; }
return this->initial_state_;
}
set<int> Automaton::get_transition_ids(){ set<int> Automaton::get_transition_ids() { return this->transition_ids_; }
return this->transition_ids_;
}
set<int> Automaton::get_state_ids(){ set<int> Automaton::get_state_ids() { return this->state_ids_; }
return this->state_ids_;
}
vector<State*> Automaton::get_states(){ vector<State *> Automaton::get_states() { return this->states_; }
return this->states_;
}
vector<Transition*> Automaton::get_transitions(){ vector<Transition *> Automaton::get_transitions() { return this->transitions_; }
return this->transitions_;
}
string Automaton::get_info(){ string Automaton::get_info() {
string info_amaton = "Automaton " + to_string(this->id) + ":\n"; string info_amaton = "Automaton " + to_string(this->id) + ":\n";
for(auto& i : this->states_){ for (auto &i : this->states_) {
info_amaton += "\t" + i->get_info(2); info_amaton += "\t" + i->get_info(2);
info_amaton += i != this->states_.back() ? "\n" : ""; info_amaton += i != this->states_.back() ? "\n" : "";
} }
return info_amaton; return info_amaton;
} }
/* Sets */ /* Sets */
void Automaton::set_initial_state(State* initial_state){ void Automaton::set_initial_state(State *initial_state) {
State *tmp_state = new State; State *tmp_state = new State;
tmp_state = this->initial_state_; tmp_state = this->initial_state_;
this->initial_state_ = initial_state; this->initial_state_ = initial_state;
tmp_state->set_state_type(StateType::Normal); tmp_state->set_state_type(StateType::Normal);
this->initial_state_->set_state_type(StateType::Initial); this->initial_state_->set_state_type(StateType::Initial);
this->state_ids_.insert(initial_state->get_id()); this->state_ids_.insert(initial_state->get_id());
this->states_.push_back(initial_state); this->states_.push_back(initial_state);
}
void Automaton::set_transition_ids(set<int> transition_ids){
this->transition_ids_ = transition_ids;
}
void Automaton::set_state_ids(set<int> state_ids){
this->state_ids_ = state_ids;
}
void Automaton::set_states(vector<State*> vector_states){
this->states_ = vector_states;
}
void Automaton::set_transitions(vector<Transition*> vector_transitions){
this->transitions_ = vector_transitions;
} }
int Automaton::current_id = 0; int Automaton::current_id = 0;
...@@ -82,123 +55,164 @@ int Automaton::current_id = 0; ...@@ -82,123 +55,164 @@ int Automaton::current_id = 0;
// Adding... // Adding...
void Automaton::add_transition(State *source_state, State *destination_state, Action *action){ void Automaton::add_transition(State *source_state, State *destination_state,
auto source_state_in_automaton = this->state_ids_.find(source_state->get_id()) != this->state_ids_.end(); Action *action) {
auto dest_state_in_automaton = this->state_ids_.find(destination_state->get_id()) != this->state_ids_.end(); auto source_state_in_automaton =
assert(("both states have to exist already in the automaton", source_state_in_automaton && dest_state_in_automaton)); this->state_ids_.find(source_state->get_id()) != this->state_ids_.end();
Transition *new_transition = new Transition(source_state, destination_state, action); auto dest_state_in_automaton =
this->state_ids_.find(destination_state->get_id()) !=
vector<Transition*> tmp_transitions = source_state->get_transitions(); this->state_ids_.end();
tmp_transitions.push_back(new_transition); assert(("both states have to exist already in the automaton",
source_state->set_transitions(tmp_transitions); source_state_in_automaton && dest_state_in_automaton));
Transition *new_transition =
this->transition_ids_.insert(new_transition->get_id()); new Transition(source_state, destination_state, action);
this->transitions_.push_back(new_transition);
}
void Automaton::add_state(State *new_state){
auto state_in_automaton = this->state_ids_.find(new_state->get_id()) == this->state_ids_.end();
assert(("state can't be added to the automaton because it exists already", state_in_automaton));
this->state_ids_.insert(new_state->get_id());
this->states_.push_back(new_state);
}
void Automaton::add_state_pos(State *new_state, int pos){
assert(("pos can't be negative", pos >= 0));
assert(("pos is greater than state's number of this automaton.", pos <= this->get_state_ids().size()));
auto state_in_automaton = this->state_ids_.find(new_state->get_id()) == this->state_ids_.end();
assert(("state can't be added to the automaton because it exists already", state_in_automaton));
auto it = this->states_.begin();
it = this->states_.insert(it+pos, new_state);
this->state_ids_.insert(new_state->get_id());
}
// Removing...
void Automaton::remove_transition(int transition_id){
auto transition_in_automaton = this->transition_ids_.find(transition_id) != this->transition_ids_.end();
assert(("transition can't be removed since it doesn't belong to this automaton", transition_in_automaton));
auto it = this->transitions_.begin();
for(; it != this->transitions_.end() && (*it)->get_id() != transition_id; it++){}
remove_transition(*it);
}
void Automaton::remove_transition(Transition *cur_transition){
auto transition_in_automaton = this->transition_ids_.find(cur_transition->get_id()) != this->transition_ids_.end();
assert(("transition can't be removed since it doesn't belong to this automaton", transition_in_automaton));
more_transitions_initial_state(cur_transition);
/*Deleting transition pointer in transitions vector of the source state */
vector<Transition*> tmp_transitions = cur_transition->get_source_state()->get_transitions();
auto it = tmp_transitions.begin();
for(; it != tmp_transitions.end() && (*it)->get_id() != cur_transition->get_id(); it++){}
it = tmp_transitions.erase(it);
cur_transition->get_source_state()->set_transitions(tmp_transitions);
it = this->transitions_.begin();
for(; it != this->transitions_.end() && (*it)->get_id() != cur_transition->get_id(); it++){}
it = this->transitions_.erase(it);
this->transition_ids_.erase(cur_transition->get_id());
delete cur_transition;
}
void Automaton::remove_initial_state(){ vector<Transition *> tmp_transitions = source_state->get_transitions();
vector<Transition*> tmp_transitions = this->initial_state_->get_transitions(); tmp_transitions.push_back(new_transition);
source_state->set_transitions(tmp_transitions);
auto no_transitions = tmp_transitions.empty();
assert(("in order to delete initial state, you must ensure there is not more transitions in the whole automaton", no_transitions && this->transitions_.empty()));
auto it = this->states_.begin();
for(; it != this->states_.end() && (*it)->get_id() != this->initial_state_->get_id(); it++){}
it = this->states_.erase(it);
this->state_ids_.erase(this->initial_state_->get_id());
this->initial_state_ = nullptr;
}
void Automaton::remove_state(State *cur_state){ this->transition_ids_.insert(new_transition->get_id());
auto state_in_automaton = this->state_ids_.find(cur_state->get_id()) != this->state_ids_.end(); this->transitions_.push_back(new_transition);
assert(("state can't be removed since it doesn't belong to this automaton", state_in_automaton));
auto no_initial_state = cur_state->get_id() != this->initial_state_->get_id();
assert(("you can't remove their automaton initial state before replace it", no_initial_state));
for(int i = cur_state->get_transitions().size() - 1; i >= 0; i--){
remove_transition(cur_state->get_transitions()[i]);
}
/*Deleting transition pointers in transitions vector of the automaton which have as destination state this cur_state */
remove_transition_due_removing_state(cur_state);
auto it = this->states_.begin();
for(; it != this->states_.end() && (*it)->get_id() != cur_state->get_id(); it++){}
it = this->states_.erase(it);
this->state_ids_.erase(cur_state->get_id());
} }
void Automaton::more_transitions_initial_state(Transition *cur_transition){ void Automaton::add_state(State *new_state) {
bool more_transitions_initial_state = 1; auto state_in_automaton =
int several_states = this->states_.size(); this->state_ids_.find(new_state->get_id()) == this->state_ids_.end();
if ((cur_transition->get_source_state() == this->initial_state_ || cur_transition->get_destination_state() == this->initial_state_) && several_states > 2) assert(("state can't be added to the automaton because it exists already",
more_transitions_initial_state = this->initial_state_->get_transitions().size() > 1; state_in_automaton));
assert(("You can't remove this transition since it is the unique transition associated with the initial state", more_transitions_initial_state)); this->state_ids_.insert(new_state->get_id());
this->states_.push_back(new_state);
} }
void Automaton::remove_transition_due_removing_state(State *cur_state){ // Removing...
for(int i = this->transitions_.size() - 1; i >= 0; i--){ void Automaton::remove_transition(int transition_id) {
if(this->transitions_[i]->get_destination_state() == cur_state){ auto transition_in_automaton =
Transition *on_transition = this->transitions_[i]; this->transition_ids_.find(transition_id) != this->transition_ids_.end();
assert(
more_transitions_initial_state(on_transition); ("transition can't be removed since it doesn't belong to this automaton",
transition_in_automaton));
vector<Transition*> source_state_transitions = on_transition->get_source_state()->get_transitions();
auto it = source_state_transitions.begin(); auto it = this->transitions_.begin();
for(; it != source_state_transitions.end() && (*it)->get_id() != on_transition->get_id(); it++){} for (; it != this->transitions_.end() && (*it)->get_id() != transition_id;
it = source_state_transitions.erase(it); it++) {
on_transition->get_source_state()->set_transitions(source_state_transitions); }
remove_transition(*it);
it = this->transitions_.begin(); }
it = this->transitions_.erase(it+i);
this->transition_ids_.erase(on_transition->get_id()); void Automaton::remove_transition(Transition *cur_transition) {
delete on_transition; auto transition_in_automaton =
} this->transition_ids_.find(cur_transition->get_id()) !=
this->transition_ids_.end();
assert(
("transition can't be removed since it doesn't belong to this automaton",
transition_in_automaton));
more_transitions_initial_state(cur_transition);
/*Deleting transition pointer in transitions vector of the source state */
vector<Transition *> tmp_transitions =
cur_transition->get_source_state()->get_transitions();
auto it = tmp_transitions.begin();
for (; it != tmp_transitions.end() &&
(*it)->get_id() != cur_transition->get_id();
it++) {
}
it = tmp_transitions.erase(it);
cur_transition->get_source_state()->set_transitions(tmp_transitions);
it = this->transitions_.begin();
for (; it != this->transitions_.end() &&
(*it)->get_id() != cur_transition->get_id();
it++) {
}
it = this->transitions_.erase(it);
this->transition_ids_.erase(cur_transition->get_id());
delete cur_transition;
}
void Automaton::remove_initial_state() {
vector<Transition *> tmp_transitions =
this->initial_state_->get_transitions();
auto no_transitions = tmp_transitions.empty();
assert(
("in order to delete initial state, you must ensure there is not more "
"transitions in the whole automaton",
no_transitions && this->transitions_.empty()));
auto it = this->states_.begin();
for (; it != this->states_.end() &&
(*it)->get_id() != this->initial_state_->get_id();
it++) {
}
it = this->states_.erase(it);
this->state_ids_.erase(this->initial_state_->get_id());
this->initial_state_ = nullptr;
}
void Automaton::remove_state(State *cur_state) {
// Check that the state belongs to the automaton
bool state_in_automaton =
this->state_ids_.find(cur_state->get_id()) != this->state_ids_.end();
assert(("state can't be removed since it doesn't belong to this automaton",
state_in_automaton));
// Check that the state is not the initial state
bool is_initial_state = cur_state->get_id() == this->initial_state_->get_id();
if (is_initial_state)
throw "you can't remove their automaton initial state before replace it";
for (int i = cur_state->get_transitions().size() - 1; i >= 0; i--) {
remove_transition(cur_state->get_transitions()[i]);
}
/*Deleting transition pointers in transitions vector of the automaton which
* have as destination state this cur_state */
remove_transition_due_removing_state(cur_state);
auto it = this->states_.begin();
for (; it != this->states_.end() && (*it)->get_id() != cur_state->get_id();
it++) {
}
it = this->states_.erase(it);
this->state_ids_.erase(cur_state->get_id());
}
void Automaton::more_transitions_initial_state(Transition *cur_transition) {
bool more_transitions_initial_state = 1;
int several_states = this->states_.size();
if ((cur_transition->get_source_state() == this->initial_state_ ||
cur_transition->get_destination_state() == this->initial_state_) &&
several_states > 2)
more_transitions_initial_state =
this->initial_state_->get_transitions().size() > 1;
assert(
("You can't remove this transition since it is the unique transition "
"associated with the initial state",
more_transitions_initial_state));
}
void Automaton::remove_transition_due_removing_state(State *cur_state) {
for (int i = this->transitions_.size() - 1; i >= 0; i--) {
if (this->transitions_[i]->get_destination_state() == cur_state) {
Transition *on_transition = this->transitions_[i];
more_transitions_initial_state(on_transition);
vector<Transition *> source_state_transitions =
on_transition->get_source_state()->get_transitions();
auto it = source_state_transitions.begin();
for (; it != source_state_transitions.end() &&
(*it)->get_id() != on_transition->get_id();
it++) {
}
it = source_state_transitions.erase(it);
on_transition->get_source_state()->set_transitions(
source_state_transitions);
it = this->transitions_.begin();
it = this->transitions_.erase(it + i);
this->transition_ids_.erase(on_transition->get_id());
delete on_transition;
} }
}
} }
#ifndef AUTOMATON_HPP #ifndef AUTOMATON_HPP
#define AUTOMATON_HPP #define AUTOMATON_HPP
#include "transition.hpp"
#include "state.hpp" #include "state.hpp"
#include "transition.hpp"
//! Automaton entity, compose by states and transitions to connect them. //! Automaton entity, compose by states and transitions to connect them.
/*! /*!
A class to model an agent which is an abstract machine with states and transitions among them. Each agent (Automaton) has an unique id number. A class to model an agent which is an abstract machine with states and
*/ transitions among them. Each agent (Automaton) has an unique id number.
class Automaton{ */
class Automaton {
private: private:
//! A private attribute of integer type to save id number of an Automaton instance. //! A private attribute of integer type to save id number of an Automaton
/*! //! instance.
this variable is responsible for save a counter value that is incremented in current_id. It happens each time an Automaton instance is created. /*!
*/ this variable is responsible for save a counter value that is incremented
int id; in current_id. It happens each time an Automaton instance is created.
*/
//! A private static attribute of integer type to increment and to have a record about id numbers. int id;
/*!
this variable increments anytime an Automaton instance is created because of static property, it does not start each time from 0. //! A private static attribute of integer type to increment and to have a
*/ //! record about id numbers.
static int current_id; /*!
this variable increments anytime an Automaton instance is created because
//! A private attribute of State pointer type to point a state which shall be of initial type. of static property, it does not start each time from 0.
/*! */
An Automaton instance must always have a state associated in this variable. It also have to be in states_. static int current_id;
*/
State *initial_state_; //! A private attribute of State pointer type to point a state which shall be
//! of initial type.
//! A private attribute of set type to collect integers. /*!
/*! An Automaton instance must always have a state associated in this
It is used to save State ids to take advantage of set definition since ids must be unique and can not exist twice same State instances in Automaton. variable. It also have to be in states_.
*/ */
set<int> state_ids_; State *initial_state_;
//! A private attribute of set type to collect integers. //! A private attribute of set type to collect integers.
/*! /*!
It is used to save Transition ids to take advantage of set definition since ids must be unique and can not exist twice same Transition instances in Automaton. It is used to save State ids to take advantage of set definition since ids
*/ must be unique and can not exist twice same State instances in Automaton.
set<int> transition_ids_; */
set<int> state_ids_;
//! A private attribute of vector type to collect State pointers.
/*! //! A private attribute of set type to collect integers.
It is used to save State pointers which are in the Automaton. The pointers here must be correlated with ids saved in state_ids_. /*!
*/ It is used to save Transition ids to take advantage of set definition
vector<State*> states_; since ids must be unique and can not exist twice same Transition instances
in Automaton.
//! A private attribute of vector type to collect Transition pointers. */
/*! set<int> transition_ids_;
It is used to save Transition pointers which are in the Automaton. The pointers here must be correlated with ids saved in transition_ids_.
*/ //! A private attribute of vector type to collect State pointers.
vector<Transition*> transitions_; /*!
It is used to save State pointers which are in the Automaton. The pointers
//! A private method to remove a Transition instance to an Automaton instance because removing a state. here must be correlated with ids saved in state_ids_.
/*! */
This method delete all transitions in other State instances which point to cur_state before deleting it. It is private because is called to check just internally by remove_state calling. vector<State *> states_;
\param[in] cur_state is the current State instance to be removed. Strictly, it must exist in the Automaton. //! A private attribute of vector type to collect Transition pointers.
*/ /*!
void remove_transition_due_removing_state(State *cur_state); It is used to save Transition pointers which are in the Automaton. The
pointers here must be correlated with ids saved in transition_ids_.
//! A private method to check if initial_state_ has more transitions. */
/*! vector<Transition *> transitions_;
This method has an assert which stop execution when try to delete the last Transition instance associated with initial_state_. It is private because is used to check just internally in remove_transition and remove_transition_due_removing_state.
//! A private method to remove a Transition instance to an Automaton instance
\param[in] cur_transition is the current Transition instance to be removed. Strictly, it must exist in the Automaton. //! because removing a state.
*/ /*!
void more_transitions_initial_state(Transition *cur_transition); This method delete all transitions in other State instances which point to
cur_state before deleting it. It is private because is called to check just
public: internally by remove_state calling.
//! Automaton constructor.
/*! \param[in] cur_state is the current State instance to be removed.
An instance of Automaton is created. Strictly, it must exist in the Automaton.
@param initial_state mandatory pointer to State for their initial_state_ of this Automaton instance. */
*/ void remove_transition_due_removing_state(State *cur_state);
Automaton(State *initial_state);
//! Automaton destructor. //! A private method to check if initial_state_ has more transitions.
/*! /*!
It deletes their pointer to initial_state_. This method has an assert which stop execution when try to delete the last
*/ Transition instance associated with initial_state_. It is private because
~Automaton(); is used to check just internally in remove_transition and
remove_transition_due_removing_state.
/* Gets */
//! A public method to get the id number of an Automaton instance. \param[in] cur_transition is the current Transition instance to be
/*! removed. Strictly, it must exist in the Automaton.
Member part of getters. */
\return A integer type corresponding to an id number. void more_transitions_initial_state(Transition *cur_transition);
*/
int get_id(); public:
//! Automaton constructor.
//! A public method to get the id number of an Automaton instance. /*!
/*! An instance of Automaton is created.
Member part of getters. @param initial_state mandatory pointer to State for their initial_state_
\return A integer type corresponding to an id number. of this Automaton instance.
*/ */
State* get_initial_state(); Automaton(State *initial_state);
//! Automaton destructor.
//! A public method to get ids of State instances associated with this Automaton instance. /*!
/*! It deletes their pointer to initial_state_.
Member part of getters. */
\return A set of type int which are State ids associated with this Automaton instance. ~Automaton();
*/
set<int> get_state_ids(); /* Gets */
//! A public method to get the id number of an Automaton instance.
//! A public method to get ids of Transition instances associated with this Automaton instance. /*!
/*! Member part of getters.
Member part of getters. \return A integer type corresponding to an id number.
\return A set of type int which are Transition ids associated with this Automaton instance. */
*/ int get_id();
set<int> get_transition_ids();
//! A public method to get the id number of an Automaton instance.
//! A public method to get vector pointers of State instances. /*!
/*! Member part of getters.
Member part of getters. \return A integer type corresponding to an id number.
\return A vector of type State pointers. */
*/ State *get_initial_state();
vector<State*> get_states();
//! A public method to get ids of State instances associated with this
//! A public method to get vector pointers of Transition instances. //! Automaton instance.
/*! /*!
Member part of getters. Member part of getters.
\return A vector of type Transition pointers. \return A set of type int which are State ids associated with this
*/ Automaton instance.
vector<Transition*> get_transitions(); */
set<int> get_state_ids();
//! A public method to get a information type of string.
/*! //! A public method to get ids of Transition instances associated with this
Member part of getters. //! Automaton instance.
\return A string which contain information about an Automaton instance, their State and Transition instances. Indentation applied for each Transition instance associated with a particular State. /*!
*/ Member part of getters.
string get_info(); \return A set of type int which are Transition ids associated with this
Automaton instance.
/* Sets */ */
set<int> get_transition_ids();
//! A public method to set the initial State of an Automaton instance.
/*! //! A public method to get vector pointers of State instances.
Member is part of setters. /*!
\param[in] inital_state Member part of getters.
a State pointer to change current initial state. \return A vector of type State pointers.
*/ */
void set_initial_state(State *initial_state); vector<State *> get_states();
//! A public method to set the set of State ids. //! A public method to get vector pointers of Transition instances.
/*! /*!
Member is part of setters. Member part of getters.
\param[in] state_ids a set of integers which are a new State ids for this Automaton. \return A vector of type Transition pointers.
*/ */
void set_state_ids(set<int> state_ids); vector<Transition *> get_transitions();
//! A public method to set the set of Transition ids. //! A public method to get a information type of string.
/*! /*!
Member is part of setters. Member part of getters.
\param[in] transition_ids a set of integers which are a new Transition ids for this Automaton. \return A string which contain information about an Automaton instance,
*/ their State and Transition instances. Indentation applied for each
void set_transition_ids(set<int> transition_ids); Transition instance associated with a particular State.
*/
//! A public method to set the vector of State pointers. string get_info();
/*!
Member is part of setters. /* Sets */
\param[in] vector_states
a vector of State pointers to change current one. //! A public method to set the initial State of an Automaton instance.
*/ /*!
void set_states(vector<State*> vector_states); Member is part of setters.
\param[in] inital_state
//! A public method to set the vector of Transition pointers. a State pointer to change current initial state.
/*! */
Member is part of setters. void set_initial_state(State *initial_state);
\param[in] vector_transitions
a vector of Transition pointers to change current one. /* Other methods */
*/ // Adding...
void set_transitions(vector<Transition*> vector_transitions);
//! A public method to add a Transition instance to an Automaton instance.
/*!
/* Other methods */ \param[in] source_state
// Adding... is a State instance to be assigned as the State from which a Transition
goes to. \param[in] destination_state is a State instance to be assigned as
//! A public method to add a Transition instance to an Automaton instance. the State to which a Transition points to. \param[in] action is an Action
/*! instance to be assigned as the Action event associated with the Transition
\param[in] source_state to be added.
is a State instance to be assigned as the State from which a Transition goes to.
\param[in] destination_state is a State instance to be assigned as the State to which a Transition points to. Strictly, source_state and destination_state must be already in the
\param[in] action is an Action instance to be assigned as the Action event associated with the Transition to be added. Automaton. This method makes a call to Transition constructor hence has
same entries.
Strictly, source_state and destination_state must be already in the Automaton. This method makes a call to Transition constructor hence has same entries. */
*/ void add_transition(State *source_state, State *destination_state,
void add_transition(State *source_state, State *destination_state, Action *action); Action *action);
//! A public method to add an State instance to an Automaton instance. //! A public method to add an State instance to an Automaton instance.
/*! /*!
\param[in] new_state \param[in] new_state
is a State instance to be added. Strictly, it can not exist in the Automata. is a State instance to be added. Strictly, it can not exist in the
*/ Automata.
void add_state(State *new_state); */
void add_state(State *new_state);
//! A public method to add an State instance to an Automaton instance with regard to certain order.
/*! // Removing...
\param[in] new_state /**
is a State instance to be added. Strictly, it can not exist in the Automata. * A public method to remove a Transition instance to an Automaton instance
\param[in] pos is a integer to insert in states_ a new State instance before the element at the specified position. It can not be negative either be greater than state's number in this Automaton. * (overloaded).
*
Strictly, new_state can not exist in the Automaton. * @param cur_transition is the current Transition instance to be removed.
*/ * Strictly, it must exist in the Automaton.
void add_state_pos(State *new_state, int pos = 0); */
void remove_transition(Transition *cur_transition);
// Removing...
/** /**
* A public method to remove a Transition instance to an Automaton instance (overloaded). * A public method to remove a Transition instance to an Automaton instance
* * (overloaded).
* @param cur_transition is the current Transition instance to be removed. Strictly, it must exist in the Automaton. *
*/ * @param transition_id is the current Transition instance id to be removed.
void remove_transition(Transition *cur_transition); * Strictly, it must exist in the Automaton.
*/
/** void remove_transition(int transition_id);
* A public method to remove a Transition instance to an Automaton instance (overloaded).
* /**
* @param transition_id is the current Transition instance id to be removed. Strictly, it must exist in the Automaton. * A public method to remove a State instance to an Automaton instance.
*/ *
void remove_transition(int transition_id); * @param cur_state is the current State instance to be removed. Strictly, it
* must exist in the Automaton and can not be equal to initial_state_.
/** */
* A public method to remove a State instance to an Automaton instance. void remove_state(State *cur_state);
*
* @param cur_state is the current State instance to be removed. Strictly, it must exist in the Automaton and can not be equal to initial_state_. /**
*/ * A public method to remove their initial_state_ instance to an Automaton
void remove_state(State *cur_state); * instance.
*
/** * It is mandatory, to have deleted completely Transitions.
* A public method to remove their initial_state_ instance to an Automaton instance. */
* void remove_initial_state();
* It is mandatory, to have deleted completely Transitions.
*/
void remove_initial_state();
}; };
#endif #endif
\ No newline at end of file
...@@ -5,6 +5,6 @@ cmake_minimum_required(VERSION 3.0.0) ...@@ -5,6 +5,6 @@ cmake_minimum_required(VERSION 3.0.0)
project(amas_tests CXX) project(amas_tests CXX)
# Add the test files for the AMAS implementation # Add the test files for the AMAS implementation
set(TEST_FILES label.cpp channel.cpp synchronization_type.cpp state_type.cpp synchronization.cpp state.cpp transition.cpp) set(TEST_FILES label.cpp channel.cpp synchronization_type.cpp state_type.cpp synchronization.cpp state.cpp transition.cpp automaton.cpp)
add_test_suite("AMAS" amas_lib "${TEST_FILES}") add_test_suite("AMAS" amas_lib "${TEST_FILES}")
#include "automaton.hpp"
#include <catch.hpp>
using Catch::Matchers::Contains;
/* TODO
* 1) Add test for get_info
*/
TEST_CASE("An automaton has states", "[automaton]") {
State *initial_s = new State(StateType::Initial);
State *new_state = new State();
Automaton automaton(initial_s);
REQUIRE(automaton.get_states().size() == 1);
REQUIRE(automaton.get_state_ids().size() == 1);
SECTION("a new state can be added") {
automaton.add_state(new_state);
REQUIRE(automaton.get_states().size() == 2);
REQUIRE(automaton.get_state_ids().size() == 2);
}
SECTION("an existing state can be removed") {
automaton.add_state(new_state);
REQUIRE(automaton.get_states().size() == 2);
REQUIRE(automaton.get_state_ids().size() == 2);
REQUIRE_THROWS(automaton.remove_state(initial_s));
automaton.remove_state(new_state);
REQUIRE(automaton.get_states().size() == 1);
REQUIRE(automaton.get_state_ids().size() == 1);
}
}
TEST_CASE("An automaton has transitions", "[automaton]") {
State *initial_s = new State(StateType::Initial);
State *new_s = new State(StateType::Normal);
Automaton automaton(initial_s);
automaton.add_state(new_s);
REQUIRE(automaton.get_transition_ids().size() == 0);
REQUIRE(automaton.get_transitions().size() == 0);
SECTION("a new transition can be added") {
automaton.add_transition(initial_s, new_s, new Label("A"));
REQUIRE(automaton.get_transition_ids().size() == 1);
REQUIRE(automaton.get_transitions().size() == 1);
Transition *t = *automaton.get_transitions().begin();
REQUIRE(initial_s->get_transitions().size() == 1);
REQUIRE(*initial_s->get_transitions().begin() == t);
REQUIRE(t->get_source_state() == initial_s);
REQUIRE(t->get_destination_state() == new_s);
}
SECTION("an existing transition can be removed") {
automaton.add_transition(initial_s, new_s, new Label("A"));
REQUIRE(automaton.get_transition_ids().size() == 1);
REQUIRE(automaton.get_transitions().size() == 1);
Transition *t = *automaton.get_transitions().begin();
automaton.remove_transition(t);
REQUIRE(automaton.get_transition_ids().size() == 0);
REQUIRE(automaton.get_transitions().size() == 0);
}
SECTION("an existing transition can be removed by its ID") {
automaton.add_transition(initial_s, new_s, new Label("A"));
REQUIRE(automaton.get_transition_ids().size() == 1);
REQUIRE(automaton.get_transitions().size() == 1);
int t_id = *automaton.get_transition_ids().begin();
automaton.remove_transition(t_id);
REQUIRE(automaton.get_transition_ids().size() == 0);
REQUIRE(automaton.get_transitions().size() == 0);
}
}
TEST_CASE("An automaton has an initial state", "[automaton]") {
State *initial_s = new State(StateType::Initial);
Automaton automaton(initial_s);
REQUIRE(automaton.get_initial_state() == initial_s);
REQUIRE(automaton.get_state_ids().size() == 1);
REQUIRE(automaton.get_states().size() == 1);
SECTION("it must be of type StateType::Initial") {
REQUIRE_THROWS_WITH(new Automaton(new State(StateType::Normal)),
Contains("must be Initial"));
}
SECTION("it can be retrieved and modified") {
State *state = new State(StateType::Normal);
automaton.set_initial_state(state);
REQUIRE(automaton.get_initial_state() == state);
REQUIRE(state->get_state_type() == StateType::Initial);
REQUIRE(initial_s->get_state_type() == StateType::Normal);
REQUIRE(automaton.get_state_ids().size() == 2);
REQUIRE(automaton.get_states().size() == 2);
}
SECTION("it can be removed") {
automaton.remove_initial_state();
REQUIRE(automaton.get_initial_state() == nullptr);
REQUIRE(automaton.get_state_ids().size() == 0);
REQUIRE(automaton.get_states().size() == 0);
}
};
TEST_CASE("A new automaton", "[automaton]") {
State *initial_s = new State(StateType::Initial);
Automaton automaton(initial_s);
SECTION("it must have an initial state") {
REQUIRE(automaton.get_initial_state() == initial_s);
REQUIRE(automaton.get_states().size() == 1);
REQUIRE(automaton.get_states()[0] == initial_s);
REQUIRE(automaton.get_state_ids().size() == 1);
REQUIRE(*automaton.get_state_ids().begin() == initial_s->get_id());
}
SECTION("it has no transitions") {
REQUIRE(automaton.get_transitions().size() == 0);
REQUIRE(automaton.get_transition_ids().size() == 0);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment