From 624e3a4a9c50af3caa0dcf1073dcd92a40374a59 Mon Sep 17 00:00:00 2001 From: Phanes Date: Sun, 3 Dec 2017 21:15:41 -0500 Subject: [PATCH] fixed exception handling for failed dependency checks --- examplar.cpp | 7 ++++++- src/loaders/Plan.cpp | 46 +++++++++++++++++++++++++++++++++++++++----- src/loaders/Task.cpp | 13 +++++++++---- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/examplar.cpp b/examplar.cpp index 6520a1e..fc18561 100644 --- a/examplar.cpp +++ b/examplar.cpp @@ -23,7 +23,12 @@ int main( ) std::cout << "Ready to execute all tasks in Plan." << std::endl; - plan.execute( verbose ); + try { + plan.execute( verbose ); + } + catch ( std::exception& e) { + std::cerr << e.what() << std::endl; + } return 0; } \ No newline at end of file diff --git a/src/loaders/Plan.cpp b/src/loaders/Plan.cpp index 351e8c8..39a7dec 100644 --- a/src/loaders/Plan.cpp +++ b/src/loaders/Plan.cpp @@ -14,10 +14,46 @@ class Plan_InvalidTaskName: public std::runtime_error { public: /// 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.") {} -}; +class Plan_Task_Missing_Dependency: public std::exception +{ +public: + /** Constructor (C strings). + * @param message C-style string error message. + * The string contents are copied upon construction. + * Hence, responsibility for deleting the char* lies + * with the caller. + */ + explicit Plan_Task_Missing_Dependency(const char* message): + msg_(message) + { + } + /** Constructor (C++ STL strings). + * @param message The error message. + */ + explicit Plan_Task_Missing_Dependency(const std::string& message): + msg_(message) + {} + + /** Destructor. + * Virtual to allow for subclassing. + */ + virtual ~Plan_Task_Missing_Dependency() throw (){} + + /** Returns a pointer to the (constant) error description. + * @return A pointer to a const char*. The underlying memory + * is in posession of the Exception object. Callers must + * not attempt to free the memory. + */ + virtual const char* what() const throw (){ + return msg_.c_str(); + } + +protected: + /** Error message. + */ + std::string msg_; +}; /// 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 @@ -165,8 +201,8 @@ void Plan::execute( bool verbose ) } this->tasks[i].execute( verbose ); } else { - throw Plan_Task_Missing_Dependency(); - // not all deps met for this task + // not all deps met for this task + throw Plan_Task_Missing_Dependency( "Task \"" + this->tasks[i].get_name() + "\" was specified in the Plan but not executed due to missing dependencies. Please revise your plan." ); } } } diff --git a/src/loaders/Task.cpp b/src/loaders/Task.cpp index 5a824ca..0c012ef 100644 --- a/src/loaders/Task.cpp +++ b/src/loaders/Task.cpp @@ -21,7 +21,8 @@ public: Task_RequiredButFailedTask(): std::runtime_error("Task: Attempted to execute a Task that failed and was required.") {} }; -/// 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). +/// 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.") {} @@ -60,7 +61,8 @@ void Task::load_root(Json::Value loader_root, bool verbose ) if ( des_dep_root[i].asString() != "" ) { this->dependencies.push_back( des_dep_root[i].asString() ); if ( verbose ) { - std::cout << "Added dependency \"" << des_dep_root[i].asString() << "\" to task \"" << this->get_name() << "\"." << std::endl; + std::cout << "Added dependency \"" << des_dep_root[i].asString() + << "\" to task \"" << this->get_name() << "\"." << std::endl; } } } @@ -80,7 +82,8 @@ void Task::load_definition( Unit selected_unit, bool verbose ) { this->definition = selected_unit; if ( verbose ) { - std::cout << "Loaded definition \"" << selected_unit.get_name() << "\" for task \"" << this->get_name() << "\"." << std::endl; + std::cout << "Loaded definition \"" << selected_unit.get_name() << "\" for task \"" + << this->get_name() << "\"." << std::endl; } this->defined = true; } @@ -166,7 +169,9 @@ void Task::execute( bool verbose ) if (rectifier_error) { //d[3] non-zero - std::cout << "\tRectification of \"" << task_name << "\" failed with exit code " << rectifier_error << "." << std::endl; + 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