logic issue being worked, "independent test 1" should be throwing an exception with current settings. Is ignoring the throw call.

This commit is contained in:
Phanes
2017-12-01 21:41:22 -05:00
parent 19c465bdaf
commit 9e4c88262a
5 changed files with 174 additions and 65 deletions

View File

@@ -13,6 +13,15 @@ class Task_NotReady: public std::runtime_error { public:
Task_NotReady(): std::runtime_error("Task: Attempted to access a unit of a Task that is not defined.") {}
};
/// Task_RequiredButFailedTask - Exception thrown when a Task is failed but required, and rectification also failed.
class Task_RequiredButFailedTask: public std::runtime_error { public:
Task_RequiredButFailedTask(): std::runtime_error("Task: Attempted to access a unit of a Task that failed, but was required, and the corresponding rectification target also failed..") {}
};
/// Task_RequiredButFailedTask - Exception thrown when a Task is failed but required, and rectification also failed but returned with a zero exit code (dont try to fool the check).
class Task_RequiredButRectifierDoesNotHeal: public std::runtime_error { public:
Task_RequiredButRectifierDoesNotHeal(): std::runtime_error("Task: The rectification script was executed and reported success, but did not actually heal the faulty condition of the Task target.") {}
};
/// Task::Task() - Constructor for the Task class. The Task is the building block of a Plan indicating of which Unit to
/// execute, and its dependencies on other units to have already been completed successfully.
@@ -86,33 +95,130 @@ bool Task::has_definition() {
}
/// Task::execute - execute a task's unit definition.
/// See the design document for what flow control needs to look like here.
/// \param verbose - Verbosity level - not implemented yet.
void Task::execute( bool verbose )
{
// throw if unit not coupled
// DUFFING
// PREWORK
// throw if unit not coupled to all necessary values since Task is stateful (stateful is okay)
if (! this->has_definition() ) { throw Task_NotReady(); }
// get the name
std::string task_name = this->definition.get_name();
// END PREWORK
// get the target execution command
std::string target_command = this->definition.get_target();
// if we're in verbose mode, do some verbose things
if ( verbose )
{
std::cout << "\t Using unit \"" << this->definition.get_name() << "\"." << std::endl;
std::cout << "\t Executing target \"" << this->definition.get_target() << "\"." << std::endl;
std::cout << "\tUsing unit \"" << task_name << "\"." << std::endl;
std::cout << "\tExecuting target \"" << target_command << "\"." << std::endl;
}
std::string executionString = this->definition.get_target();
std::string rectifierString = this->definition.get_rectifier();
// execute target
int return_code = Sproc::execute( target_command );
int return_code = Sproc::execute( executionString );
if ( return_code )
// d[0] check exit code of target
if (return_code == 0)
{
std::cout << "Process failed with exit code " << return_code << "." << std::endl;
std::cout << "Performing rectification: " << rectifierString << "." << std::endl;
int rectifier_error = Sproc::execute( rectifierString );
if ( rectifier_error )
// Zero d[0] return from target execution, good to return
if ( verbose )
{
std::cout << "Designated rectification script failed with error " << rectifier_error << "." << std::endl;
std::cout << "\tTarget " << task_name << " succeeded." << std::endl;
}
// next
return;
} else {
// Non-Zero d[0] from initial target execution, get to d[1]
std::cout << "\tTarget \"" << task_name << "\" failed with exit code " << return_code << "." << std::endl;
// check if rectify pattern is enabled d[1]
if ( this->definition.get_rectify() )
{
// yes d[1]
std::cout << "\tRectification pattern is enabled for \"" << task_name << "\"." << std::endl;
// execute RECTIFIER
std::string rectifier_command = this->definition.get_rectifier();
std::cout << "\tExecuting rectification: " << rectifier_command << "." << std::endl;
int rectifier_error = Sproc::execute( rectifier_command );
// d[3] check exit code of rectifier
if ( rectifier_error )
{
//d[3] non-zero
std::cout << "\tRectification of \"" << task_name << "\" failed with exit code " << rectifier_error << "." << std::endl;
// d[2] check if REQUIRED
if ( this->definition.get_required() )
{
// d[2] yes
// halt/exception
throw Task_RequiredButFailedTask();
} else {
// d[2] no
// next
return;
}
} else {
// d[3] zero
// execute target
std::cout << "\tRe-Executing target \"" << this->definition.get_target() << "\"." << std::endl;
int retry_code = Sproc::execute( target_command );
// d[4] exit code of target retry
if (retry_code == 0) {
// d[4] zero
return;
} else {
// d[4] non-zero
// d[5] required check
if ( this->definition.get_required() )
{
// d[5] yes
throw Task_RequiredButRectifierDoesNotHeal();
} else {
// d[5] no
// next
return;
}
}
}
} else {
// no d[1]
std::cout << "\tRectification is not enabled for \"" << task_name << "\"." << std::endl;
// required d[2]
if ( this->definition.get_required() )
{
// d[2] yes
// This is executing.....
std::cout << "\tThis task is required to continue the plan." << std::endl;
// but these are NOT executing?????
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
throw Task_RequiredButFailedTask();
} else {
// d[2] no
std::cout << "\tThis task is not required to continue the plan." << std::endl;
return;
}
}
}
}

View File

@@ -52,13 +52,13 @@ int Unit::load_root(Json::Value loader_root)
{ this->rectifier = loader_root.get("rectifier", errmsg).asString(); } else throw Unit_DataStructureException();
if ( loader_root.isMember("active") )
{ this->active = loader_root.get("active", errmsg).asString(); } else throw Unit_DataStructureException();
{ this->active = loader_root.get("active", errmsg).asBool(); } else throw Unit_DataStructureException();
if ( loader_root.isMember("required") )
{ this->required = loader_root.get("required", errmsg).asString(); } else throw Unit_DataStructureException();
{ this->required = loader_root.get("required", errmsg).asBool(); } else throw Unit_DataStructureException();
if ( loader_root.isMember("rectify") )
{ this->rectify = loader_root.get("rectify", errmsg).asString(); } else throw Unit_DataStructureException();
{ this->rectify = loader_root.get("rectify", errmsg).asBool(); } else throw Unit_DataStructureException();
this->populated = true;
@@ -119,7 +119,7 @@ std::string Unit::get_rectifier()
/// Unit::get_active - retrieves the armed status of the unit.
///
/// \return the armed status of the unit.
std::string Unit::get_active()
bool Unit::get_active()
{
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->active;
@@ -128,7 +128,7 @@ std::string Unit::get_active()
/// Unit::get_required - retrieves the requirement status of the unit.
///
/// \return the requirement status of the unit.
std::string Unit::get_required()
bool Unit::get_required()
{
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->required;
@@ -137,7 +137,7 @@ std::string Unit::get_required()
/// Unit::get_rectify - retrieves the rectification status of the unit.
///
/// \return the rectification status of the unit.
std::string Unit::get_rectify()
bool Unit::get_rectify()
{
if ( ! this->populated ) { throw Unit_NotPopulated(); }
return this->rectify;

View File

@@ -28,15 +28,15 @@ private:
// an indicator of whether the test is active or not
// this is used as a way to give definers a way to force executors to edit arbitrary fields or prevent
// execution of potentially dangerous or intrusive tests
std::string active;
bool active;
// an indicator of whether or not this test is required to pass.
// intended to be used as a flag to halt execution of further tests on failure
std::string required;
bool required;
// indicator of whether the rectifier executable should be run on test failures.
// if rectifier exits on non-zero return code, it should be trigger the behaviour indicated by required
std::string rectify;
bool rectify;
public:
Unit();
@@ -52,9 +52,9 @@ public:
std::string get_target();
std::string get_output();
std::string get_rectifier();
std::string get_active();
std::string get_required();
std::string get_rectify();
bool get_active();
bool get_required();
bool get_rectify();
};
#endif //FTESTS_UNIT_H