dependency management implemented -- this should be polished later to say the task name in the exception message. last feature to implement is logging.
parent
c92be3f4be
commit
5f85185e8d
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"units_path": "/home/phanes/development/internal/Examplar/conf/units/all_test.units",
|
||||
"plan_path": "/home/phanes/development/internal/Examplar/conf/plans/test.plan"
|
||||
"plan_path": "/home/phanes/development/internal/Examplar/conf/plans/test.plan",
|
||||
"config_version": "1"
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
"plan": [
|
||||
{ "name": "independent test 1", "dependencies": [ null ] },
|
||||
{ "name": "independent test 2", "dependencies": [ null ] },
|
||||
{ "name": "dependent test", "dependencies": [ "independent test 1", null, null ] }
|
||||
{ "name": "dependent test", "dependencies": [ "independent test 1" ] }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
"target": "/usr/bin/false",
|
||||
"rectifier": "/usr/bin/true",
|
||||
"active": true,
|
||||
"required": true,
|
||||
"required": false,
|
||||
"rectify": true
|
||||
},
|
||||
{
|
||||
"name": "independent test 2",
|
||||
"target": "/usr/bin/false",
|
||||
"rectifier": "/usr/bin/false",
|
||||
"target": "/usr/bin/true",
|
||||
"rectifier": "/usr/bin/true",
|
||||
"active": true,
|
||||
"required": false,
|
||||
"rectify": false
|
||||
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
{
|
||||
"name": "dependent test",
|
||||
"target": "ssh root@phanes.silogroup.org",
|
||||
"target": "/usr/bin/true",
|
||||
"rectifier": "/usr/bin/false",
|
||||
"active": true,
|
||||
"required": false,
|
||||
|
|
|
@ -11,6 +11,14 @@ class Plan_InvalidTaskName: public std::runtime_error { public:
|
|||
Plan_InvalidTaskName(): std::runtime_error("Plan: Attempted to access a Task using an invalid name.") {}
|
||||
};
|
||||
|
||||
|
||||
/// Plan_Task_Missing_Dependency - Exception thrown when a Plan tries to access a contained Task's value by name not present
|
||||
/// in the Unit.
|
||||
class Plan_Task_Missing_Dependency: public std::runtime_error { public:
|
||||
Plan_Task_Missing_Dependency(): std::runtime_error("Plan: Attempted to execute a task that had unmet dependencies.") {}
|
||||
};
|
||||
|
||||
|
||||
/// Plan::Plan() - Constructor for Plan class. A Plan is a managed container for a Task vector. These tasks reference
|
||||
/// Units that are defined in the Units files (Suite). If Units are definitions, Tasks are selections of those
|
||||
/// definitions to execute, and if Units together form a Suite, Tasks together form a Plan.
|
||||
|
@ -53,7 +61,7 @@ void Plan::load_plan_file(std::string filename, bool verbose)
|
|||
/// \param result - The variable receiving the value.
|
||||
/// \param index - The numerical index in the Task vector to retrieve a value for.
|
||||
/// \param verbose - Whether to print verbose output to STDOUT.
|
||||
void Plan::get_task(Task & result, int index, bool verbose)
|
||||
void Plan::get_task(Task & result, int index )
|
||||
{
|
||||
if ( index <= this->tasks.size() )
|
||||
{
|
||||
|
@ -63,30 +71,6 @@ void Plan::get_task(Task & result, int index, bool verbose)
|
|||
}
|
||||
}
|
||||
|
||||
/// Plan::get_task - Retrieves a task by name.
|
||||
///
|
||||
/// \param result - The variable receiving the value.
|
||||
/// \param provided_name - The name to find a task by.
|
||||
/// \param verbose - Whether to print verbose output to STDOUT.
|
||||
void Plan::get_task(Task & result, std::string provided_name, bool verbose)
|
||||
{
|
||||
bool foundMatch = false;
|
||||
|
||||
for ( int i = 0; i < this->tasks.size(); i++ )
|
||||
{
|
||||
if ( this->tasks[i].get_name() == provided_name )
|
||||
{
|
||||
result = this->tasks[i];
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! foundMatch )
|
||||
{
|
||||
std::cerr << "Task name \"" << provided_name << "\" was referenced but not defined!" << std::endl;
|
||||
throw Plan_InvalidTaskName();
|
||||
}
|
||||
}
|
||||
|
||||
/// Plan::load_definitions - Load the units corresponding to each task in plan from the given Suite.
|
||||
///
|
||||
|
@ -108,6 +92,63 @@ void Plan::load_definitions( Suite unit_definitions, bool verbose )
|
|||
}
|
||||
}
|
||||
|
||||
/// Plan::get_task - Retrieves a task by name.
|
||||
///
|
||||
/// \param result - The variable receiving the value.
|
||||
/// \param provided_name - The name to find a task by.
|
||||
/// \param verbose - Whether to print verbose output to STDOUT.
|
||||
void Plan::get_task(Task & result, std::string provided_name )
|
||||
{
|
||||
bool foundMatch = false;
|
||||
|
||||
for ( int i = 0; i < this->tasks.size(); i++ )
|
||||
{
|
||||
if ( this->tasks[i].get_name() == provided_name )
|
||||
{
|
||||
result = this->tasks[i];
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! foundMatch )
|
||||
{
|
||||
std::cerr << "Task name \"" << provided_name << "\" was referenced but not defined!" << std::endl;
|
||||
throw Plan_InvalidTaskName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO dependency check goes here
|
||||
// This should check to see if there are unmet dependencies.
|
||||
// done -- add a "completed" attribute to Task
|
||||
// Iterate through Task::dependencies, a vector attached to tasks[i] containing task names
|
||||
// use Plan::get_task( name ) method to retrieve that task
|
||||
// check if it is in a ready state
|
||||
// return ready/not ready
|
||||
bool Plan::all_dependencies_complete(std::string name)
|
||||
{
|
||||
// get the task by name
|
||||
Task named_task;
|
||||
this->get_task( named_task, name );
|
||||
|
||||
// get the dependencies of that task
|
||||
std::vector<std::string> deps = named_task.get_dependencies();
|
||||
|
||||
// create an empty task to assign values to during iteration
|
||||
Task tmpTask;
|
||||
// iterate through its dependencies
|
||||
for ( int i = 0; i < deps.size(); i++ )
|
||||
{
|
||||
this->get_task( tmpTask, deps[i]);
|
||||
if (! tmpTask.is_complete() )
|
||||
{
|
||||
// error message?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Plan::execute() - Iterates through all tasks in a plan and executes them.
|
||||
///
|
||||
/// \param verbose
|
||||
|
@ -116,15 +157,17 @@ void Plan::execute( bool verbose )
|
|||
// for each task in this plan
|
||||
for ( int i = 0; i < this->tasks.size(); i++ )
|
||||
{
|
||||
if ( verbose ) {
|
||||
std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl;
|
||||
// std::cout << "Executing task \"" << this->tasks[0].get_name() << "\"." << std::endl;
|
||||
if (this->all_dependencies_complete(this->tasks[i].get_name()) )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl;
|
||||
}
|
||||
this->tasks[i].execute( verbose );
|
||||
} else {
|
||||
throw Plan_Task_Missing_Dependency();
|
||||
// not all deps met for this task
|
||||
}
|
||||
this->tasks[i].execute( verbose );
|
||||
// this->tasks[0].execute( verbose );
|
||||
|
||||
// for testing a logic issue in Task.execute(), remove when done
|
||||
// throw Plan_InvalidTaskIndex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,10 @@ class Plan: public JSON_Loader
|
|||
void load_plan_file( std::string filename, bool verbose );
|
||||
|
||||
// fetch a task from this->tasks
|
||||
void get_task( Task & result, std::string provided_name, bool verbose );
|
||||
void get_task( Task & result, std::string provided_name );
|
||||
|
||||
// fetch a task from this->tasks
|
||||
void get_task( Task & result, int index, bool verbose );
|
||||
void get_task( Task & result, int index );
|
||||
|
||||
// load unit definitions from a provided suite and import them into individual tasks
|
||||
void load_definitions( Suite unit_definitions, bool verbose );
|
||||
|
@ -32,6 +32,8 @@ class Plan: public JSON_Loader
|
|||
|
||||
// execute all tasks in this plan
|
||||
void execute( bool verbose );
|
||||
|
||||
bool all_dependencies_complete(std::string name);
|
||||
};
|
||||
|
||||
#endif //FTESTS_PLAN_H
|
||||
|
|
|
@ -91,6 +91,20 @@ bool Task::is_complete()
|
|||
return this->complete;
|
||||
}
|
||||
|
||||
|
||||
/// Task::mark_complete - Marks the task complete..
|
||||
void Task::mark_complete()
|
||||
{
|
||||
this->complete = true;
|
||||
}
|
||||
|
||||
|
||||
/// Task::get_dependencies - returns a pointer to the dependencies vector.
|
||||
std::vector<std::string> Task::get_dependencies()
|
||||
{
|
||||
return this->dependencies;
|
||||
}
|
||||
|
||||
/// Task::has_definition - Indicator if the task has attached its definition from a Suite.
|
||||
bool Task::has_definition()
|
||||
{
|
||||
|
@ -102,10 +116,10 @@ bool Task::has_definition()
|
|||
/// \param verbose - Verbosity level - not implemented yet.
|
||||
void Task::execute( bool verbose )
|
||||
{
|
||||
// DUFFING
|
||||
// DUFFING - If Examplar is broken it's probably going to be in this block.
|
||||
|
||||
// PREWORK
|
||||
// throw if unit not coupled to all necessary values since Task is stateful (stateful is okay)
|
||||
// throw if unit not coupled to all necessary values since Task is stateful (yes, stateful is okay)
|
||||
if (! this->has_definition() ) {
|
||||
throw Task_NotReady();
|
||||
}
|
||||
|
@ -133,6 +147,7 @@ void Task::execute( bool verbose )
|
|||
if ( verbose ) {
|
||||
std::cout << "\tTarget " << task_name << " succeeded." << std::endl;
|
||||
}
|
||||
this->mark_complete();
|
||||
// next
|
||||
} else {
|
||||
// Non-Zero d[0] from initial target execution, get to d[1]
|
||||
|
|
|
@ -42,6 +42,11 @@ class Task
|
|||
|
||||
// execute this task's definition
|
||||
void execute( bool verbose );
|
||||
|
||||
void mark_complete();
|
||||
|
||||
// returns a pointer to the dependencies vector
|
||||
std::vector<std::string> get_dependencies();
|
||||
};
|
||||
|
||||
#endif //FTESTS_TASK_H
|
||||
|
|
Loading…
Reference in New Issue