diff --git a/test/pEpTest/src/pEpTestModel.cc b/test/pEpTest/src/pEpTestModel.cc index a828b0e..880d992 100644 --- a/test/pEpTest/src/pEpTestModel.cc +++ b/test/pEpTest/src/pEpTestModel.cc @@ -1,9 +1,16 @@ #include "pEpTestModel.hh" +#include "iostream" -//using namespace std; +using namespace std; namespace pEp { namespace Test { bool pEpTestModel::log_enabled = true; + pEpTestModel::pEpTestModel(const string& name) : name(name) {} + + const std::string& pEpTestModel::getName() const + { + return name; + } } // namespace Test } // namespace pEp diff --git a/test/pEpTest/src/pEpTestModel.hh b/test/pEpTest/src/pEpTestModel.hh index 63b3198..5f1d06a 100644 --- a/test/pEpTest/src/pEpTestModel.hh +++ b/test/pEpTest/src/pEpTestModel.hh @@ -9,9 +9,13 @@ namespace pEp { namespace Test { class pEpTestModel { - public: + pEpTestModel() = delete; + pEpTestModel(const std::string& name); + const std::string& getName() const; + private: + const std::string name; static bool log_enabled; Adapter::pEpLog::pEpLogger logger{ "pEpTestModel", log_enabled }; Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger; diff --git a/test/pEpTest/src/pEpTestUnit.cc b/test/pEpTest/src/pEpTestUnit.cc index 674c24d..1deebf5 100644 --- a/test/pEpTest/src/pEpTestUnit.cc +++ b/test/pEpTest/src/pEpTestUnit.cc @@ -13,18 +13,17 @@ namespace pEp { namespace Test { bool pEpTestUnit::log_enabled = true; string pEpTestUnit::data_dir = "./"; - pEpTestUnit::ExecutionMode pEpTestUnit::exec_mode_default = pEpTestUnit::ExecutionMode::FUNCTION; + pEpTestUnit::ExecutionMode pEpTestUnit::emode_default = pEpTestUnit::ExecutionMode::FUNCTION; // RootNode factory //static pEpTestUnit pEpTestUnit::createRootNode( pEpTestModel& model, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode) + const TestUnitFunction& main_f, + ExecutionMode emode_children) { - pEpLog("called"); - pEpTestUnit ret(nullptr, &model, name, main_f, emode); + pEpTestUnit ret(nullptr, &model, name, main_f, emode_children); return ret; } @@ -33,11 +32,10 @@ namespace pEp { pEpTestUnit pEpTestUnit::createChildNode( pEpTestUnit& parent, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode) + const TestUnitFunction& main_f, + ExecutionMode emode_children) { - pEpLog("called"); - pEpTestUnit ret(&parent, nullptr, name, main_f, emode); + pEpTestUnit ret(&parent, nullptr, name, main_f, emode_children); return ret; } @@ -46,19 +44,18 @@ namespace pEp { pEpTestUnit* const parent, pEpTestModel* model, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode) : + const TestUnitFunction& main_f, + ExecutionMode emode_children) : parent(parent), - model(model), name(name), main_func(main_f), exec_mode(emode) + model(model), name(name), main_func(main_f), emode_chld(emode_children) { + logger.set_instancename(getFQName()); if (parent != nullptr) { parent->addChildNode(*this); } - logger.set_instancename(getFQName()); // data_dir_recreate(); } - //static void pEpTestUnit::setDefaultDataDir(const std::string& dir) { @@ -84,18 +81,20 @@ namespace pEp { void pEpTestUnit::waitChildProcesses() const { - pEpLogClass("called"); + pEpLogClass("Waiting for child processes to terminate..."); int status; pid_t pid; while ((pid = wait(&status)) > 0) { pEpLogClass( - "PID: " + std::to_string((int)pid) + " exit status: " + std::to_string(status)); + "process[" + std::to_string((int)pid) + + "] terminated with status: " + std::to_string(status)); } + pEpLogClass("All child processes terminated"); } void pEpTestUnit::addChildNode(const pEpTestUnit& node) { - children.insert(pair(node.getName(), node)); + children.insert(pair(node.getName(), node)); } string pEpTestUnit::getName() const @@ -105,62 +104,60 @@ namespace pEp { void pEpTestUnit::run(const pEpTestUnit* caller) const { - // pEpLogClass("called"); - // init(); - executeSelf(); - executeChildren(); - // if called by another TestNode, caller will not be nullptr, so caller will clean up - // if caller is mullptr, there is nobody who will do the cleanup, so we have to. - if (caller == nullptr) { - waitChildProcesses(); + pEpLogClass("called"); + // caller is never nullptr if called by another pEpTestUnit + if(caller == nullptr) { + pEpLogClass("\n" + to_string()); } - } - //private - void pEpTestUnit::executeSelf() const - { - // pEpLogClass("called"); + if (main_func) { - pEpLogClass(string("Starting as: " + to_string(getEffectiveExecutionMode()))); - // Execute in fork and go on, wait for process execution in the edn - if (getEffectiveExecutionMode() == ExecutionMode::PROCESS_PARALLEL) { // fork - executeTestFuncInFork(false); - // Execute in fork and wait here until process ends - } else if (getEffectiveExecutionMode() == ExecutionMode::PROCESS_SERIAL) { - executeTestFuncInFork(true); - // Execute as normal funciton - } else if (getEffectiveExecutionMode() == ExecutionMode::FUNCTION) { - // pEpLogClass("Executing in same process and thread"); - main_func(*this); - // pEpLogClass("Execution ended"); - } else if (getEffectiveExecutionMode() == ExecutionMode::THREAD_PARALLEL) { - throw runtime_error(to_string(getEffectiveExecutionMode()) + " - not implemented"); - } else if (getEffectiveExecutionMode() == ExecutionMode::THREAD_SERIAL) { - throw runtime_error(to_string(getEffectiveExecutionMode()) + " - not implemented"); - } + main_func(*this); } else { pEpLogClass("No function to execute"); } + executeChildren(); } //private void pEpTestUnit::executeChildren() const { - pEpLogClass("called"); - for (const pair elem : children) { - elem.second.run(this); + if (!children.empty()) { + const ExecutionMode& emode = getEffectiveExecutionMode(); + pEpLogClass(string("Executing children as: " + to_string(emode))); + for (const pair elem : children) { + // Execute in fork and go on, wait for process execution in the end + if (emode == ExecutionMode::PROCESS_PARALLEL) { // fork + executeForked(elem.second, false); + // Execute in fork and wait here until process ends + } else if (emode == ExecutionMode::PROCESS_SERIAL) { + executeForked(elem.second, true); + // Execute as normal funciton + } else if (emode == ExecutionMode::FUNCTION) { + pEpLogClass("Executing in same process and thread"); + elem.second.run(this); + pEpLogClass("Execution ended"); + } else if (emode == ExecutionMode::THREAD_PARALLEL) { + throw runtime_error(to_string(emode) + " - not implemented"); + } else if (emode == ExecutionMode::THREAD_SERIAL) { + throw runtime_error(to_string(emode) + " - not implemented"); + } + } + if (emode == ExecutionMode::PROCESS_PARALLEL) { + waitChildProcesses(); + } } } //private - void pEpTestUnit::executeTestFuncInFork(bool wait) const + void pEpTestUnit::executeForked(const pEpTestUnit& unit, bool wait) const { pid_t pid; pid = fork(); if (pid == pid_t(0)) { - pEpLogClass(string("pid: [" + std::to_string(getpid()) + "] - starting...")); + pEpLogClass(string("In pid: [" + std::to_string(getpid()) + "] - starting...")); setenv("HOME", getHomeDir().c_str(), 1); - main_func(*this); - pEpLogClass(string("pid: [" + std::to_string(getpid()) + "] - ended.")); + unit.run(this); + pEpLogClass(string("In pid: [" + std::to_string(getpid()) + "] - ended.")); exit(0); } else if (pid < pid_t(0)) { pEpLogClass("Error forking"); @@ -172,7 +169,7 @@ namespace pEp { pEpTestModel& pEpTestUnit::getModel() const { - pEpLogClass("called"); + // pEpLogClass("called"); pEpTestModel* ret = nullptr; if (model == nullptr) { ret = &parent->getModel(); @@ -187,7 +184,7 @@ namespace pEp { const pEpTestUnit& pEpTestUnit::getRoot() const { - pEpLogClass("called"); + // pEpLogClass("called"); const pEpTestUnit* ret = nullptr; if (parent != nullptr) { ret = &parent->getRoot(); @@ -238,27 +235,24 @@ namespace pEp { data_dir_create(); }; - + //static void pEpTestUnit::setDefaultExecutionMode(ExecutionMode emode) { - pEpTestUnit::exec_mode_default = emode; + pEpTestUnit::emode_default = emode; } pEpTestUnit::ExecutionMode pEpTestUnit::getExecutionMode() const { - return exec_mode; + return emode_chld; } pEpTestUnit::ExecutionMode pEpTestUnit::getEffectiveExecutionMode() const { - ExecutionMode ret; + ExecutionMode ret{ emode_default }; if (getExecutionMode() == ExecutionMode::INHERIT) { if (parent != nullptr) { // get from parent until not inherit ret = parent->getEffectiveExecutionMode(); - } else { - // get from static class config - ret = pEpTestUnit::exec_mode_default; } } else { ret = getExecutionMode(); @@ -285,5 +279,25 @@ namespace pEp { return "UNDEFINED EXECUTION MODE"; } } + + std::string pEpTestUnit::to_string(bool recursive, int indent) const + { + string ret; + stringstream builder; + builder << string(indent, '\t') << getName(); + builder << "[children=" << to_string(getEffectiveExecutionMode()) + "]"; + // builder << "/" << getModel().getName(); + builder << endl; + ret = builder.str(); + + if (recursive) { + indent++; + for (const pair elem : children) { + ret += elem.second.to_string(true, indent); + } + indent--; + } + return ret; + } } // namespace Test } // namespace pEp diff --git a/test/pEpTest/src/pEpTestUnit.hh b/test/pEpTest/src/pEpTestUnit.hh index b520b71..9ace2ea 100644 --- a/test/pEpTest/src/pEpTestUnit.hh +++ b/test/pEpTest/src/pEpTestUnit.hh @@ -14,7 +14,8 @@ namespace pEp { namespace Test { class pEpTestUnit { public: - using TestEntryFunc = std::function; + using TestUnitFunction = std::function; + enum class ExecutionMode { FUNCTION, @@ -33,14 +34,14 @@ namespace pEp { static pEpTestUnit createRootNode( pEpTestModel& model, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode = ExecutionMode::INHERIT); + const TestUnitFunction& main_f, + ExecutionMode emode_children = emode_default); static pEpTestUnit createChildNode( pEpTestUnit& parent, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode = ExecutionMode::INHERIT); + const TestUnitFunction& main_f, + ExecutionMode emode_children = emode_default); static void setDefaultDataDir(const std::string& dir); @@ -51,9 +52,8 @@ namespace pEp { std::string getFQName() const; pEpTestModel& getModel() const; std::string getHomeDir() const; + std::string to_string(bool recursive = true, int indent = 0) const; static void setDefaultExecutionMode(ExecutionMode emode); - ExecutionMode getExecutionMode() const; - ExecutionMode getEffectiveExecutionMode() const; private: // Constructors @@ -61,17 +61,18 @@ namespace pEp { pEpTestUnit* parent, pEpTestModel* model, const std::string& name, - const TestEntryFunc& main_f, - ExecutionMode emode); + const TestUnitFunction& main_f, + ExecutionMode emode_children); // Methods void init() const; const pEpTestUnit& getRoot() const; - void executeSelf() const; - void executeChildren() const; - void executeTestFuncInFork(bool wait) const; + void executeChildren() const; + void executeForked(const pEpTestUnit& unit, bool wait) const; void waitChildProcesses() const; + ExecutionMode getExecutionMode() const; + ExecutionMode getEffectiveExecutionMode() const; void data_dir_delete(); void data_dir_create(); void data_dir_recreate(); @@ -80,10 +81,10 @@ namespace pEp { const pEpTestUnit* parent; //nullptr if rootnode const std::string name; pEpTestModel* model; //nullptr if inherited - const TestEntryFunc& main_func; - ExecutionMode exec_mode; - static ExecutionMode exec_mode_default; - std::map children; + const TestUnitFunction& main_func; + const ExecutionMode emode_chld; + static ExecutionMode emode_default; + std::map children; static std::string data_dir; // logger