diff --git a/test/pEpTest/src/pEpTestTree.cc b/test/pEpTest/src/pEpTestTree.cc new file mode 100644 index 0000000..1c4d615 --- /dev/null +++ b/test/pEpTest/src/pEpTestTree.cc @@ -0,0 +1,360 @@ +#include "pEpTestTree.hh" +#include "../../../src/std_utils.hh" +#include "../../framework/utils.hh" +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; +using namespace pEp::Adapter; +using namespace pEp::Utils; + +namespace pEp { + namespace Test { + string pEpTestTree::_data_root = "./peptest"; + bool pEpTestTree::debug_log_enabled = false; + + // PUBIC CONCSTRUCTORS / FACTORY ----------------------------------------------------------- + // static + pEpTestTree pEpTestTree::createRootNode( + pEpTestModel& model, + const string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode) + { + pEpTestTree ret(nullptr, &model, name, test_func, exec_mode); + return ret; + } + + // static + pEpTestTree pEpTestTree::createChildNode( + pEpTestTree& parent, + const string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode) + { + pEpTestTree ret(&parent, nullptr, name, test_func, exec_mode); + return ret; + } + + string pEpTestTree::getNodeName() const + { + return _name; + } + + string pEpTestTree::getNodePath() const + { + pEpLogClass("called"); + string ret; + + if (!_isRootNode()) { + ret = _parent->getNodePath() + "/" + getNodeName(); + } else { + ret = getNodeName(); + } + return ret; + } + + // For: + // RootNode - "" + // ProcessNode - ".../" + // When Process as dir. parent - "...//name" + // When no process as dir. parent - "...//.../name" + std::string pEpTestTree::getNodePathShort() const + { + string ret; + if (_isRootNode()) { + ret = getNodeName(); + } else { + if (_isProcessNode()) { + ret += ".../" + getNodeName(); + } else { + if (&(_getParentingProcessNode()) == (_parent)) { + ret = _getParentingProcessNode().getNodePathShort() + "/" + getNodeName(); + } else { + ret = _getParentingProcessNode().getNodePathShort() + "/.../" + getNodeName(); + } + } + } + return ret; + } + + // Inherited (if null see parent recursively) + pEpTestModel& pEpTestTree::getModel() const + { + pEpLogClass("called"); + pEpTestModel* ret = nullptr; + if (_model == nullptr) { + ret = &(_parent->getModel()); + } else { + ret = _model; + } + assert(ret != nullptr); + // cant be null because for createChildNode() you have to provide TestNode& instance, + // and the only other way to get one is by createRootNode() which in turn requires a TestModel& + return *ret; + } + + // RootNodes have their own data_dir + // ProcessNodes have their own data_dir inside their RootNote dir (nameclash prossible) + // All other nodes inherit data_dir from their Root/ProcessNode + string pEpTestTree::getDataDir() const + { + pEpLogClass("called"); + string ret; + if (_isRootNode()) { + ret = getDataRoot() + getNodeName() + "/"; + } else { + if (_parent->_exec_mode == ExecutionMode::PROCESS_SERIAL || + _parent->_exec_mode == ExecutionMode::PROCESS_PARALLEL) { + + ret = _parent->getDataDir() + getNodeName(); + } else { + // inherit + ret = _parent->getDataDir(); + } + } + return ret; + } + + // static + void pEpTestTree::setDataRoot(const string& dir) + { + pEpTestTree::_data_root = dir; + } + + // static + string pEpTestTree::getDataRoot() + { + return pEpTestTree::_data_root; + } + + + void pEpTestTree::run(const pEpTestTree* caller) const + { + pEpLogClass("called"); + // caller is never nullptr if called by another pEpTestTree + if (caller == nullptr) { + pEpLog::logH1("Starting pEpTestTree from node: " + getNodePathShort()); + pEpLog::log(to_string()); + } + + pEpLog::logH2( + "[ " + to_string(_exec_mode) + " / " + getNodePathShort() + "]"); + // Execute in fork and wait here until process ends + if (_exec_mode == ExecutionMode::PROCESS_SERIAL) { // fork + _executeInFork(bind(&pEpTestTree::_run, this), true); + // Execute in fork and go on, wait for process execution in the end + } else if (_exec_mode == ExecutionMode::PROCESS_PARALLEL) { + _executeInFork(bind(&pEpTestTree::_run, this), false); + // Execute as normal funciton + } else if (_exec_mode == ExecutionMode::FUNCTION) { + _run(); + } else if (_exec_mode == ExecutionMode::THREAD_PARALLEL) { + throw invalid_argument(to_string(_exec_mode) + " - not implemented"); + } else if (_exec_mode == ExecutionMode::THREAD_SERIAL) { + throw invalid_argument(to_string(_exec_mode) + " - not implemented"); + } + + if (caller == nullptr) { + _waitChildProcesses(); + } + } + + string pEpTestTree::to_string(bool recursive, int indent) const + { + string ret; + stringstream builder; + builder << string(indent, '\t'); + builder << getNodeName(); + builder << "[" << to_string(_exec_mode) << "]"; + builder << endl; + ret = builder.str(); + + if (recursive) { + indent++; + for (const pair child : _children) { + ret += child.second.to_string(true, indent); + } + indent--; + } + return ret; + } + + string pEpTestTree::to_string(const ExecutionMode& emode) + { + switch (emode) { + case ExecutionMode::FUNCTION: + return "FUNCTION"; + case ExecutionMode::PROCESS_SERIAL: + return "PROCESS_SERIAL"; + case ExecutionMode::PROCESS_PARALLEL: + return "PROCESS_PARALLEL"; + case ExecutionMode::THREAD_SERIAL: + return "THREAD_SERIAL"; + case ExecutionMode::THREAD_PARALLEL: + return "THREAD_PARALLEL"; + case ExecutionMode::INHERIT: + return "INHERIT"; + default: + return "UNDEFINED EXECUTION MODE"; + } + } + + //Well, ok, lets just add some little convenience logging service in here, too + void pEpTestTree::log(const string& msg) const + { + stringstream builder; + builder << "["; + builder << std::to_string(getpid()); + builder << " - "; + builder << getNodePathShort(); + builder << "] - "; + builder << msg; + builder << endl; + cout << builder.str(); + } + + // PRIVATE --------------------------------------------------------------------------------- + + pEpTestTree::pEpTestTree( + pEpTestTree* const parent, + pEpTestModel* model, + const string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode) : + _parent(parent), + _model(model), _name(_normalizeName(name)), _test_func(test_func), _exec_mode(exec_mode) + { + logger_debug.set_instancename(getNodePath()); + if (!_isRootNode()) { + parent->_addChildNode(*this); + } + } + + void pEpTestTree::_run() const + { + if (_test_func) { + _test_func(*this); + } else { + pEpLog::log("No function to execute"); + } + if (!_children.empty()) { + for (const pair child : _children) { + child.second.run(this); + } + } + } + + void pEpTestTree::_executeInFork(function func, bool wait_child) const + { + pid_t pid; + pid = fork(); + if (pid == pid_t(0)) { + func(); + exit(0); + } else if (pid < pid_t(0)) { + throw runtime_error("Error forking"); + } + if (wait_child) { + _waitChildProcesses(); + } + } + + void pEpTestTree::_waitChildProcesses() const + { + int status; + pid_t pid; + while ((pid = wait(&status)) > 0) { + pEpLog::log( + "process[" + std::to_string((int)pid) + + "] terminated with status: " + std::to_string(status)); + } + } + + void pEpTestTree::_addChildNode(pEpTestTree& node) + { + _children.insert(pair(node.getNodeName(), node)); + } + + bool pEpTestTree::_isProcessNode() const + { + bool ret = false; + if (_exec_mode == ExecutionMode::PROCESS_SERIAL || + _exec_mode == ExecutionMode::PROCESS_PARALLEL) { + ret = true; + } + return ret; + } + + bool pEpTestTree::_isRootNode() const + { + bool ret = false; + if (_parent == nullptr) { + ret = true; + } + return ret; + } + + const pEpTestTree& pEpTestTree::_getRootNode() const + { + const pEpTestTree* ret = nullptr; + if (!_isRootNode()) { + ret = &(_parent->_getRootNode()); + } else { + ret = this; + } + assert(ret != nullptr); + // cant be null because for createChildNode() you need to provide a TestNode& and + // the only other way is using createRootNode() which has parent == nullptr + return *ret; + } + + const pEpTestTree& pEpTestTree::_getParentingProcessNode() const + { + if (_isRootNode() || _isProcessNode()) { + return *this; + } else { + return _parent->_getParentingProcessNode(); + } + } + + // name is alphanumeric only (everything else will be replaced by an underscore) + string pEpTestTree::_normalizeName(string name) const + { + replace_if( + name.begin(), + name.end(), + [](char c) -> bool { return !isalnum(c); }, + '_'); + + return name; + } + + void pEpTestTree::_data_dir_create() + { + // Utils::dir_create(getDataDir()); + pEpLog::log("creating dir:" + getDataRoot()); + } + + void pEpTestTree::_data_dir_delete() + { + try { + Utils::path_delete_all(getDataRoot()); + } catch (const exception& e) { + pEpLog::log("DistTest: - could not delete data dir: " + getDataRoot()); + } + } + + void pEpTestTree::_data_dir_recreate() + { + _data_dir_delete(); + _data_dir_create(); + }; + } // namespace Test +} // namespace pEp diff --git a/test/pEpTest/src/pEpTestTree.hh b/test/pEpTest/src/pEpTestTree.hh new file mode 100644 index 0000000..37259e0 --- /dev/null +++ b/test/pEpTest/src/pEpTestTree.hh @@ -0,0 +1,118 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef LIBPEPADAPTER_PEPTEST_PEPTESTTREE_HH +#define LIBPEPADAPTER_PEPTEST_PEPTESTTREE_HH + +#include +#include +#include +#include "../../../src/pEpLog.hh" +#include "pEpTestModel.hh" + +// Yes, the mem mgmt is purely static on purpose (so far) + +namespace pEp { + namespace Test { + class pEpTestTree { + public: + using NodeFunc = std::function; + + enum class ExecutionMode + { + FUNCTION, + PROCESS_SERIAL, + PROCESS_PARALLEL, + THREAD_SERIAL, // unimplemented + THREAD_PARALLEL, // unimplemented + INHERIT + }; + + // Constructors are private + pEpTestTree() = delete; + + // Modify + static pEpTestTree createRootNode( + pEpTestModel& model, + const std::string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode = ExecutionMode::FUNCTION); + + static pEpTestTree createChildNode( + pEpTestTree& parent, + const std::string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode = ExecutionMode::FUNCTION); + + // Read-Only + std::string getNodeName() const; // name only + std::string getNodePath() const; // full path (is an ID) + std::string getNodePathShort() const; // parent process + name + pEpTestModel& getModel() const; + std::string getDataDir() const; + + // Read-Write + static void setDataRoot(const std::string& dir); + static std::string getDataRoot(); + + // Main funcs + void run(const pEpTestTree* caller = nullptr) const; + std::string to_string(bool recursive = true, int indent = 0) const; + static std::string to_string(const ExecutionMode& emode); + + // logging service + void log(const std::string& msg) const; + + // internal logging + static bool debug_log_enabled; + Adapter::pEpLog::pEpLogger logger_debug{ "pEpTestTree", debug_log_enabled }; + + private: + // CONSTRUCGTORS + explicit pEpTestTree( + pEpTestTree* parent, + pEpTestModel* model, + const std::string& name, + const NodeFunc& test_func, + ExecutionMode exec_mode); + + // METHODS + // Execution + void _run() const; + void _executeInFork(std::function func, bool wait_child) const; + void _waitChildProcesses() const; + + // Modify + void _addChildNode(pEpTestTree& node); + + // Query + bool _isProcessNode() const; + bool _isRootNode() const; + const pEpTestTree& _getRootNode() const; + const pEpTestTree& _getParentingProcessNode() const; + + // Util + std::string _normalizeName(std::string name) const; + + // TODO + void _data_dir_delete(); + void _data_dir_create(); + void _data_dir_recreate(); + + // Fields + const std::string _name; + const pEpTestTree* _parent; //nullptr if RootUnit + pEpTestModel* _model; //nullptr if inherited + const NodeFunc& _test_func; + const ExecutionMode _exec_mode; + static std::string _data_root; + + std::map _children; // map to guarantee uniqueness of sibling-names + + // internal logging + Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; + }; + }; // namespace Test +}; // namespace pEp + +#endif // LIBPEPADAPTER_PEPTEST_PEPTESTTREE_HH diff --git a/test/pEpTest/src/pEpTestUnit.cc b/test/pEpTest/src/pEpTestUnit.cc deleted file mode 100644 index 6a08c9f..0000000 --- a/test/pEpTest/src/pEpTestUnit.cc +++ /dev/null @@ -1,379 +0,0 @@ -#include "pEpTestUnit.hh" -#include "../../../src/std_utils.hh" -#include "../../framework/utils.hh" -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -namespace pEp { - namespace Test { - bool pEpTestUnit::log_enabled = true; - string pEpTestUnit::data_root = "./peptest"; - pEpTestUnit::ExecutionMode pEpTestUnit::emode_default = pEpTestUnit::ExecutionMode::FUNCTION; - - // RootNode factory - // static - pEpTestUnit pEpTestUnit::createRootNode( - pEpTestModel& model, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children) - { - pEpTestUnit ret(nullptr, &model, name, test_func, emode_children); - return ret; - } - - // ChildNode factory - // static - pEpTestUnit pEpTestUnit::createChildNode( - pEpTestUnit& parent, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children) - { - pEpTestUnit ret(&parent, nullptr, name, test_func, emode_children); - return ret; - } - - - // private - pEpTestUnit::pEpTestUnit( - pEpTestUnit* const parent, - pEpTestModel* model, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children) : - parent(parent), - model(model), name(normalizeName(name)), test_func(test_func), emode_chld(emode_children) - { - logger.set_instancename(getFQName()); - if (!isRootNode()) { - parent->addChildNode(*this); - } - } - - // static - void pEpTestUnit::setDefaultDataRoot(const std::string& dir) - { - pEpTestUnit::data_root = dir; - } - - // static - std::string pEpTestUnit::getDataRoot() - { - return pEpTestUnit::data_root; - } - - void pEpTestUnit::init(const pEpTestUnit* caller) const - { - //caller is never nullptr if called from another unit - if (caller == nullptr) {} - - // for (const pair elem : testnodes) { - // string home_dir = evalHomeDir(elem.second); - // pEpLogClass("creating home dir for '" + elem.second.getName() + "' - " + home_dir); mkdir(home_dir.c_str(), 0770); - // } - } - - void pEpTestUnit::addChildNode(pEpTestUnit& node) - { - children.insert(pair(node.getName(), node)); - } - - // name is alphanumeric only (everything else will be replaced by an underscore) - // private - string pEpTestUnit::normalizeName(string name) const - { - replace_if( - name.begin(), - name.end(), - [](char c) -> bool { return !isalnum(c); }, - '_'); - - return name; - } - - string pEpTestUnit::getName() const - { - return name; - } - - // RootNodes have their own data_dir - // ProcessNodes have their own data_dir inside their RootNote dir (nameclash prossible) - // All other nodes inherit data_dir from their Root/ProcessNode - string pEpTestUnit::getDataDir() const - { - string ret; - if (isRootNode()) { - ret = getDataRoot() + getName() + "/"; - } else { - if (parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_SERIAL || - parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_PARALLEL) { - - ret = parent->getDataDir() + getName(); - } else { - // inherit - ret = parent->getDataDir(); - } - } - return ret; - } - - void pEpTestUnit::run(const pEpTestUnit* caller) - { - pEpLogClass("called"); - // caller is never nullptr if called by another pEpTestUnit - if (caller == nullptr) { - pEpLogClass("\n" + to_string()); - } - - if (test_func) { - test_func(*this); - } else { - pEpLogClass("No function to execute"); - } - executeChildren(); - } - - // private - void pEpTestUnit::executeChildren() const - { - if (!children.empty()) { - const ExecutionMode& emode = getEffectiveExecutionMode(); - for (const pair elem : children) { - // Execute in fork and wait here until process ends - if (emode == ExecutionMode::PROCESS_SERIAL) { // fork - executeForked(elem.second); - waitChildProcesses(); - // Execute in fork and go on, wait for process execution in the end - } else if (emode == ExecutionMode::PROCESS_PARALLEL) { - executeForked(elem.second); - // Execute as normal funciton - } else if (emode == ExecutionMode::FUNCTION) { - elem.second.run(this); - } 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::executeForked(pEpTestUnit& unit) const - { - pid_t pid; - pid = fork(); - if (pid == pid_t(0)) { - // setenv("HOME", evalHomeDir().c_str(), 1); - unit.run(this); - exit(0); - } else if (pid < pid_t(0)) { - pEpLogClass("Error forking"); - } - } - - // private - void pEpTestUnit::waitChildProcesses() const - { - int status; - pid_t pid; - while ((pid = wait(&status)) > 0) { - pEpLogClass( - "process[" + to_string((int)pid) + - "] terminated with status: " + to_string(status)); - } - } - - // Inherited (if null see parent recursively) - pEpTestModel& pEpTestUnit::getModel() const - { - // pEpLogClass("called"); - pEpTestModel* ret = nullptr; - if (model == nullptr) { - ret = &parent->getModel(); - } else { - ret = model; - } - assert(ret != nullptr); - // cant be null because for createChildNode() you have to provide TestNode& instance, - // and the only other way to get one is by createRootNode() which in turn requires a TestModel& - return *ret; - } - - const pEpTestUnit& pEpTestUnit::getRoot() const - { - // pEpLogClass("called"); - const pEpTestUnit* ret = nullptr; - if (!isRootNode()) { - ret = &parent->getRoot(); - } else { - ret = this; - } - assert(ret != nullptr); - // cant be null because for createChildNode() you need to provide a TestNode& and - // the only other way is using createRootNode() which has parent == nullptr - return *ret; - } - - string pEpTestUnit::getFQNameNormalized() const - { - return normalizeName(getFQName()); - } - - string pEpTestUnit::getFQName() const - { - // pEpLogClass("called"); - string ret; - - if (!isRootNode()) { - ret = parent->getFQName() + "/" + getName(); - } else { - ret = getName(); - } - return ret; - } - - // // A process node is a node that spawns its own process - // bool pEpTestUnit::isProcessNode() const - // { - // bool ret = false; - // if (isRootNode() || - // parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_PARALLEL || - // parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_SERIAL) { - // ret = true; - // } - // return ret; - // } - - bool pEpTestUnit::isRootNode() const - { - bool ret = false; - if (parent == nullptr) { - ret = true; - } - return ret; - } - - void pEpTestUnit::data_dir_delete() - { - try { - Utils::path_delete_all(getDataRoot()); - } catch (const exception& e) { - pEpLogClass("DistTest: - could not delete data dir: " + getDataRoot()); - } - } - - void pEpTestUnit::data_dir_create() - { - // Utils::dir_create(getDataDir()); - pEpLogClass("creating dir:" + getDataRoot()); - } - - void pEpTestUnit::data_dir_recreate() - { - data_dir_delete(); - data_dir_create(); - }; - - // static - void pEpTestUnit::setDefaultExecutionMode(ExecutionMode emode) - { - pEpTestUnit::emode_default = emode; - } - - pEpTestUnit::ExecutionMode pEpTestUnit::getExecutionMode() const - { - return emode_chld; - } - - pEpTestUnit::ExecutionMode pEpTestUnit::getEffectiveExecutionMode() const - { - ExecutionMode ret{ emode_default }; - if (getExecutionMode() == ExecutionMode::INHERIT) { - if (!isRootNode()) { - // get from parent until not inherit - ret = parent->getEffectiveExecutionMode(); - } - } else { - ret = getExecutionMode(); - } - return ret; - } - - string pEpTestUnit::to_string(const ExecutionMode& emode) - { - switch (emode) { - case ExecutionMode::FUNCTION: - return "FUNCTION"; - case ExecutionMode::PROCESS_SERIAL: - return "PROCESS_SERIAL"; - case ExecutionMode::PROCESS_PARALLEL: - return "PROCESS_PARALLEL"; - case ExecutionMode::THREAD_SERIAL: - return "THREAD_SERIAL"; - case ExecutionMode::THREAD_PARALLEL: - return "THREAD_PARALLEL"; - case ExecutionMode::INHERIT: - return "INHERIT"; - default: - return "UNDEFINED EXECUTION MODE"; - } - } - - 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; - } - - const pEpTestUnit& pEpTestUnit::getParentProcessUnit() const - { - if (!isRootNode()) { - if (parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_PARALLEL || - parent->getEffectiveExecutionMode() == ExecutionMode::PROCESS_SERIAL || - parent->isRootNode()) { - return *this; - } else { - return parent->getParentProcessUnit(); - } - } else { - return *this; - } - } - - //Well, ok, lets just add some little convenience logging service in here, too - void pEpTestUnit::log(const string& msg) const - { - stringstream builder; - builder << "[" << std::to_string(getpid()) << "/" << getParentProcessUnit().getFQName() - << "] - "; - builder << msg << endl; - cout << builder.str(); - } - } // namespace Test -} // namespace pEp diff --git a/test/pEpTest/src/pEpTestUnit.hh b/test/pEpTest/src/pEpTestUnit.hh deleted file mode 100644 index 8759fda..0000000 --- a/test/pEpTest/src/pEpTestUnit.hh +++ /dev/null @@ -1,106 +0,0 @@ -// This file is under GNU General Public License 3.0 -// see LICENSE.txt - -#ifndef LIBPEPADAPTER_PEPTESTUNIT_HH -#define LIBPEPADAPTER_PEPTESTUNIT_HH - -#include -#include -#include -#include "../../../src/pEpLog.hh" -#include "pEpTestModel.hh" - -namespace pEp { - namespace Test { - class pEpTestUnit { - public: - using TestUnitFunction = std::function; - - enum class ExecutionMode - { - FUNCTION, - PROCESS_SERIAL, - PROCESS_PARALLEL, - THREAD_SERIAL, // unimplemented - THREAD_PARALLEL, // unimplemented - INHERIT - }; - static std::string to_string(const ExecutionMode& emode); - - // Constructors - pEpTestUnit() = delete; - - // Methods - static pEpTestUnit createRootNode( - pEpTestModel& model, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children = emode_default); - - static pEpTestUnit createChildNode( - pEpTestUnit& parent, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children = emode_default); - - void init(const pEpTestUnit* caller = nullptr) const; - static void setDefaultDataRoot(const std::string& dir); - static std::string getDataRoot(); - void addChildNode(pEpTestUnit& node); - void run(const pEpTestUnit* caller = nullptr); - std::string getName() const; - std::string getFQName() const; - std::string getFQNameNormalized() const; - pEpTestModel& getModel() const; - std::string getDataDir() const; - const pEpTestUnit& getParentProcessUnit() const; - std::string to_string(bool recursive = true, int indent = 0) const; - static void setDefaultExecutionMode(ExecutionMode emode); - - //logging service - void log(const std::string& msg) const; - - // internal logging - static bool log_enabled; - Adapter::pEpLog::pEpLogger logger{ "pEpTestUnit", log_enabled }; - - private: - // Constructors - explicit pEpTestUnit( - pEpTestUnit* parent, - pEpTestModel* model, - const std::string& name, - const TestUnitFunction& test_func, - ExecutionMode emode_children); - - // Methods - const pEpTestUnit& getRoot() const; - void executeChildren() const; - void executeForked(pEpTestUnit& unit) const; - void waitChildProcesses() const; - ExecutionMode getExecutionMode() const; - ExecutionMode getEffectiveExecutionMode() const; - void data_dir_delete(); - void data_dir_create(); - void data_dir_recreate(); - bool isRootNode() const; - // bool isProcessNode() const; - std::string normalizeName(std::string name) const; - - // Fields - const pEpTestUnit* parent; //nullptr if rootnode - const std::string name; - pEpTestModel* model; //nullptr if inherited - const TestUnitFunction& test_func; - const ExecutionMode emode_chld; - static ExecutionMode emode_default; - std::map children; - static std::string data_root; - - // logger - Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger; - }; - }; // namespace Test -}; // namespace pEp - -#endif // LIBPEPADAPTER_PEPTESTUNIT_HH diff --git a/test/pEpTest/test/test_pEpTest_basic.cc b/test/pEpTest/test/test_pEpTest_basic.cc index 3214488..3c59121 100644 --- a/test/pEpTest/test/test_pEpTest_basic.cc +++ b/test/pEpTest/test/test_pEpTest_basic.cc @@ -1,4 +1,4 @@ -#include "../src/pEpTestUnit.hh" +#include "../src/pEpTestTree.hh" #include "../../framework/utils.hh" #include #include @@ -8,12 +8,13 @@ using namespace pEp; using namespace pEp::Test; -void print_and_sleep(pEpTestUnit& myself, int sleepmilis, int rep_count) +void printHomeDir(pEpTestTree& myself, int sleepmilis, int rep_count) { -// TESTLOGH1("HYA FROM:" + myself.getFQName()); + // TESTLOGH1("HYA FROM:" + myself.getFQName()); int i = 0; while (i < rep_count) { - TESTLOG(string(myself.getFQName() + " - PID: " + to_string(getpid()) + " - " + to_string(i))); + myself.log(myself.getNodeName() + " - " + to_string(i)); + // TESTLOG(string(myself.getFQName() + " - PID: " + to_string(getpid()) + " - " + to_string(i))); sleep_millis(sleepmilis); i++; } @@ -24,30 +25,48 @@ int main(int argc, char* argv[]) string dummy; pEpTestModel model{ "pEpTestModel" }; { - // pEpTestUnit::setDefaultExecutionMode(pEp::Test::pEpTestUnit::ExecutionMode::PROCESS_SERIAL); - pEpTestUnit root = pEpTestUnit::createRootNode( + // DEBUG Logging of pEpTestTree itself + pEpTestTree::debug_log_enabled = true; + + // Configure DataRoot for all TestNodes + pEpTestTree::setDataRoot("./basic_data_root"); + + // The RootNode is the + pEpTestTree root = pEpTestTree::createRootNode( model, - "DistributedTest", - [](pEpTestUnit mynode) { print_and_sleep(mynode, 200, 5); }, - pEp::Test::pEpTestUnit::ExecutionMode::PROCESS_PARALLEL); + "Test Execution Model", + [](pEpTestTree mynode) { printHomeDir(mynode, 200, 5); }); - pEpTestUnit test1 = pEpTestUnit::createChildNode(root, "node1", [](pEpTestUnit mynode) { - print_and_sleep(mynode, 200, 10); + // Subprocess 1 + pEpTestTree test1 = pEpTestTree::createChildNode( + root, + "node1", + [](pEpTestTree mynode) { printHomeDir(mynode, 200, 10); }, + pEp::Test::pEpTestTree::ExecutionMode::PROCESS_PARALLEL); + + pEpTestTree test1_1 = pEpTestTree::createChildNode(test1, "test1.1", [](pEpTestTree mynode) { + printHomeDir(mynode, 200, 10); }); - pEpTestUnit test2 = pEpTestUnit::createChildNode(root, "node2", [](pEpTestUnit mynode) { - print_and_sleep(mynode, 200, 10); + pEpTestTree test1_2 = pEpTestTree::createChildNode(test1, "test1.2", [](pEpTestTree mynode) { + printHomeDir(mynode, 200, 10); }); - pEpTestUnit test1_1 = pEpTestUnit::createChildNode(test1, "test1.1", [](pEpTestUnit mynode) { - print_and_sleep(mynode, 200, 10); + // Subprocess 2 + pEpTestTree test2 = pEpTestTree::createChildNode( + root, + "node2", + [](pEpTestTree mynode) { printHomeDir(mynode, 200, 10); }, + pEp::Test::pEpTestTree::ExecutionMode::PROCESS_PARALLEL); + + pEpTestTree test2_1 = pEpTestTree::createChildNode(test2, "test2.1", [](pEpTestTree mynode) { + printHomeDir(mynode, 200, 10); }); - pEpTestUnit test2_1 = pEpTestUnit::createChildNode(test2, "test2.1", [](pEpTestUnit mynode) { - print_and_sleep(mynode, 200, 10); + pEpTestTree test2_2 = pEpTestTree::createChildNode(test2, "test2.2", [](pEpTestTree mynode) { + printHomeDir(mynode, 200, 10); }); - // cout << root.to_string() << endl; root.run(); } } \ No newline at end of file diff --git a/test/pEpTest/test/test_transport.cc b/test/pEpTest/test/test_transport.cc index 73e54a1..22ed387 100644 --- a/test/pEpTest/test/test_transport.cc +++ b/test/pEpTest/test/test_transport.cc @@ -1,4 +1,4 @@ -#include "../src/pEpTestUnit.hh" +#include "../src/pEpTestTree.hh" #include "../../framework/utils.hh" #include #include @@ -11,7 +11,7 @@ using namespace pEp; using namespace pEp::Test; -void printHomeDir(pEpTestUnit& myself) +void printHomeDir(pEpTestTree& myself) { // TESTLOG(string(myself.getFQName() + " - PID: " + to_string(getpid()))); // cout << "[" << to_string(getpid()) << "/" << myself.getFQName() << "] - " << endl; @@ -22,34 +22,34 @@ void printHomeDir(pEpTestUnit& myself) int main(int argc, char* argv[]) { pEpTestModel model{ "TestTransport" }; - pEpTestUnit::log_enabled = false; - pEpTestUnit::setDefaultDataRoot("./testdata/"); +// pEpTestTree::debug_log_enabled = true; + pEpTestTree::setDataRoot("./testdata/"); { - pEpTestUnit root = pEpTestUnit::createRootNode( + pEpTestTree root = pEpTestTree::createRootNode( model, "root node nr.1", - [](pEpTestUnit mynode) { printHomeDir(mynode); }, - pEp::Test::pEpTestUnit::ExecutionMode::PROCESS_PARALLEL); + [](pEpTestTree mynode) { printHomeDir(mynode); }, + pEp::Test::pEpTestTree::ExecutionMode::PROCESS_PARALLEL); - pEpTestUnit test1 = pEpTestUnit::createChildNode(root, "node 1", [](pEpTestUnit mynode) { + pEpTestTree test1 = pEpTestTree::createChildNode(root, "node 1", [](pEpTestTree mynode) { printHomeDir(mynode); }); - pEpTestUnit test1_1 = pEpTestUnit::createChildNode(test1, "node 1_1", [](pEpTestUnit mynode) { + pEpTestTree test1_1 = pEpTestTree::createChildNode(test1, "node 1.1", [](pEpTestTree mynode) { printHomeDir(mynode); }); - pEpTestUnit test2 = pEpTestUnit::createChildNode(root, "node 2", [](pEpTestUnit mynode) { + pEpTestTree test2 = pEpTestTree::createChildNode(root, "node 2", [](pEpTestTree mynode) { printHomeDir(mynode); }); - pEpTestUnit test2_1 = pEpTestUnit::createChildNode( + pEpTestTree test2_1 = pEpTestTree::createChildNode( test2, - "node 2_1", - [](pEpTestUnit mynode) { printHomeDir(mynode); }, - pEp::Test::pEpTestUnit::ExecutionMode::PROCESS_PARALLEL); + "node 2.1", + [](pEpTestTree mynode) { printHomeDir(mynode); }, + pEp::Test::pEpTestTree::ExecutionMode::PROCESS_PARALLEL); - pEpTestUnit test2_1_1 = pEpTestUnit::createChildNode(test2_1, "node 1", [](pEpTestUnit mynode) { + pEpTestTree test2_1_1 = pEpTestTree::createChildNode(test2_1, "node 2.1.1", [](pEpTestTree mynode) { printHomeDir(mynode); });