diff --git a/test/pEpTest/src/pEpTestTree.hh b/test/pEpTest/src/pEpTestTree.hh index 37259e0..206cbb0 100644 --- a/test/pEpTest/src/pEpTestTree.hh +++ b/test/pEpTest/src/pEpTestTree.hh @@ -8,12 +8,13 @@ #include #include #include "../../../src/pEpLog.hh" -#include "pEpTestModel.hh" +//#include "pEpTestModel.hh" // Yes, the mem mgmt is purely static on purpose (so far) namespace pEp { namespace Test { + template class pEpTestTree { public: using NodeFunc = std::function; @@ -21,42 +22,38 @@ namespace pEp { enum class ExecutionMode { FUNCTION, - PROCESS_SERIAL, + PROCESS_SEQUENTIAL, PROCESS_PARALLEL, - THREAD_SERIAL, // unimplemented - THREAD_PARALLEL, // unimplemented + THREAD_SEQUENTIAL, // 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, + explicit pEpTestTree( + pEpTestTree* parent, const std::string& name, - const NodeFunc& test_func, + const NodeFunc test_func = nullptr, + T* model = nullptr, 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; + std::string getNodeName() const; + std::string getNodePath() const; + std::string getNodePathShort() const; + T* getModel() const; + std::string rootNodeDir() const; + std::string processDir() const; // own process dir // Read-Write - static void setDataRoot(const std::string& dir); - static std::string getDataRoot(); + void setExecutionMode(ExecutionMode mode); + static void setGlobalRootDir(const std::string& dir); + static std::string getGlobalRootDir(); + // Main funcs - void run(const pEpTestTree* caller = nullptr) const; + void run() const; std::string to_string(bool recursive = true, int indent = 0) const; static std::string to_string(const ExecutionMode& emode); @@ -68,17 +65,14 @@ namespace pEp { 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); + // CONSTRUCTORS // METHODS // Execution + void _runRootNode() const; void _run() const; + void _runSelf() const; + void _runChildren() const; void _executeInFork(std::function func, bool wait_child) const; void _waitChildProcesses() const; @@ -88,8 +82,8 @@ namespace pEp { // Query bool _isProcessNode() const; bool _isRootNode() const; - const pEpTestTree& _getRootNode() const; - const pEpTestTree& _getParentingProcessNode() const; + const pEpTestTree& _rootNode() const; + const pEpTestTree& _parentingProcessNode() const; // Util std::string _normalizeName(std::string name) const; @@ -102,10 +96,10 @@ namespace pEp { // 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; + T* _model; //nullptr if inherited + const NodeFunc _test_func; + ExecutionMode _exec_mode; + static std::string _global_root_dir; std::map _children; // map to guarantee uniqueness of sibling-names @@ -115,4 +109,6 @@ namespace pEp { }; // namespace Test }; // namespace pEp +#include "pEpTestTree.hxx" + #endif // LIBPEPADAPTER_PEPTEST_PEPTESTTREE_HH diff --git a/test/pEpTest/src/pEpTestTree.cc b/test/pEpTest/src/pEpTestTree.hxx similarity index 55% rename from test/pEpTest/src/pEpTestTree.cc rename to test/pEpTest/src/pEpTestTree.hxx index 1c4d615..7aa5ff7 100644 --- a/test/pEpTest/src/pEpTestTree.cc +++ b/test/pEpTest/src/pEpTestTree.hxx @@ -16,38 +16,36 @@ 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, + template + string pEpTestTree::_global_root_dir = "./peptest"; + template + bool pEpTestTree::debug_log_enabled = false; + + // PUBLIC CONCSTRUCTORS / FACTORY ----------------------------------------------------------- + template + pEpTestTree::pEpTestTree( + pEpTestTree* const parent, const string& name, - const NodeFunc& test_func, - ExecutionMode exec_mode) + const NodeFunc test_func, + T* model, + ExecutionMode exec_mode) : + _parent(parent), + _model(model), _name(_normalizeName(name)), _test_func(test_func), _exec_mode(exec_mode) { - pEpTestTree ret(&parent, nullptr, name, test_func, exec_mode); - return ret; + logger_debug.set_instancename(getNodePath()); + if (!_isRootNode()) { + parent->_addChildNode(*this); + } } - string pEpTestTree::getNodeName() const + template + string pEpTestTree::getNodeName() const { return _name; } - string pEpTestTree::getNodePath() const + template + string pEpTestTree::getNodePath() const { pEpLogClass("called"); string ret; @@ -65,7 +63,8 @@ namespace pEp { // ProcessNode - ".../" // When Process as dir. parent - "...//name" // When no process as dir. parent - "...//.../name" - std::string pEpTestTree::getNodePathShort() const + template + std::string pEpTestTree::getNodePathShort() const { string ret; if (_isRootNode()) { @@ -74,10 +73,10 @@ namespace pEp { if (_isProcessNode()) { ret += ".../" + getNodeName(); } else { - if (&(_getParentingProcessNode()) == (_parent)) { - ret = _getParentingProcessNode().getNodePathShort() + "/" + getNodeName(); + if (&(_parentingProcessNode()) == (_parent)) { + ret = _parentingProcessNode().getNodePathShort() + "/" + getNodeName(); } else { - ret = _getParentingProcessNode().getNodePathShort() + "/.../" + getNodeName(); + ret = _parentingProcessNode().getNodePathShort() + "/.../" + getNodeName(); } } } @@ -85,94 +84,124 @@ namespace pEp { } // Inherited (if null see parent recursively) - pEpTestModel& pEpTestTree::getModel() const + template + T* pEpTestTree::getModel() const { pEpLogClass("called"); - pEpTestModel* ret = nullptr; - if (_model == nullptr) { - ret = &(_parent->getModel()); - } else { + T* ret = nullptr; + + if (_model != nullptr) { ret = _model; + } else { + if (!_isRootNode()) { + ret = _parent->getModel(); + } } - 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; + 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 + // string pEpTestTree::dataDir() const + // { + // pEpLogClass("called"); + // string ret; + // if(!_isRootNode()) { + // ret = getRootNodesDir() + _getRootNode().getNodeName() + "/" + _getParentingProcessNode().getNodeName() + "/"; + // } else { + // ret = getRootNodesDir() + _getRootNode().getNodeName() + "/"; + // } + // return ret; + // } + // + + // Every RootNode has its own dir + template + string pEpTestTree::rootNodeDir() const + { + return getGlobalRootDir() + _rootNode().getNodeName() + "/"; + } + + // Every process has its own dir inside its rootNodeDir + // The Root node has its own processDir for future use + template + string pEpTestTree::processDir() const { - pEpLogClass("called"); - string ret; if (_isRootNode()) { - ret = getDataRoot() + getNodeName() + "/"; + return rootNodeDir() + "rootnode_data"; } else { - if (_parent->_exec_mode == ExecutionMode::PROCESS_SERIAL || - _parent->_exec_mode == ExecutionMode::PROCESS_PARALLEL) { - - ret = _parent->getDataDir() + getNodeName(); + if (&_parentingProcessNode() == &_rootNode()) { + return rootNodeDir() + getNodeName() + "/"; } else { - // inherit - ret = _parent->getDataDir(); - } + return rootNodeDir() + _parentingProcessNode().getNodeName() + "/"; + }; } - return ret; } - // static - void pEpTestTree::setDataRoot(const string& dir) + template + void pEpTestTree::setExecutionMode(ExecutionMode mode) { - pEpTestTree::_data_root = dir; + _exec_mode = mode; } // static - string pEpTestTree::getDataRoot() + template<> + void pEpTestTree::setGlobalRootDir(const string& dir) { - return pEpTestTree::_data_root; + pEpTestTree::_global_root_dir = dir; } + // static + template + string pEpTestTree::getGlobalRootDir() + { + return pEpTestTree::_global_root_dir + "/"; + } - void pEpTestTree::run(const pEpTestTree* caller) const + template + void pEpTestTree::run() const { pEpLogClass("called"); // caller is never nullptr if called by another pEpTestTree - if (caller == nullptr) { + if (_isRootNode()) { 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 + if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL) { // fork + pEpLog::logH2("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + "]"); _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) { + pEpLog::logH2("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + "]"); _executeInFork(bind(&pEpTestTree::_run, this), false); // Execute as normal funciton } else if (_exec_mode == ExecutionMode::FUNCTION) { + pEpLog::logH3("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + "]"); _run(); } else if (_exec_mode == ExecutionMode::THREAD_PARALLEL) { throw invalid_argument(to_string(_exec_mode) + " - not implemented"); - } else if (_exec_mode == ExecutionMode::THREAD_SERIAL) { + } else if (_exec_mode == ExecutionMode::THREAD_SEQUENTIAL) { throw invalid_argument(to_string(_exec_mode) + " - not implemented"); } - if (caller == nullptr) { - _waitChildProcesses(); - } + _waitChildProcesses(); } - string pEpTestTree::to_string(bool recursive, int indent) const + template + string pEpTestTree::to_string(bool recursive, int indent) const { string ret; stringstream builder; - builder << string(indent, '\t'); + builder << string(indent * 4, ' '); + builder << getNodeName(); - builder << "[" << to_string(_exec_mode) << "]"; + builder << " [ "; + builder << to_string(_exec_mode) << " - "; + builder << "\"" << processDir() << "\""; + builder << " ]"; builder << endl; ret = builder.str(); @@ -186,19 +215,20 @@ namespace pEp { return ret; } - string pEpTestTree::to_string(const ExecutionMode& emode) + template + string pEpTestTree::to_string(const ExecutionMode& emode) { switch (emode) { case ExecutionMode::FUNCTION: return "FUNCTION"; - case ExecutionMode::PROCESS_SERIAL: - return "PROCESS_SERIAL"; + case ExecutionMode::PROCESS_SEQUENTIAL: + return "PROC_SEQ"; case ExecutionMode::PROCESS_PARALLEL: - return "PROCESS_PARALLEL"; - case ExecutionMode::THREAD_SERIAL: - return "THREAD_SERIAL"; + return "PROC_PAR"; + case ExecutionMode::THREAD_SEQUENTIAL: + return "THREAD_S"; case ExecutionMode::THREAD_PARALLEL: - return "THREAD_PARALLEL"; + return "THREAD_P"; case ExecutionMode::INHERIT: return "INHERIT"; default: @@ -207,7 +237,8 @@ namespace pEp { } //Well, ok, lets just add some little convenience logging service in here, too - void pEpTestTree::log(const string& msg) const + template + void pEpTestTree::log(const string& msg) const { stringstream builder; builder << "["; @@ -222,36 +253,35 @@ namespace pEp { // 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) + template + void pEpTestTree::_run() const { - logger_debug.set_instancename(getNodePath()); - if (!_isRootNode()) { - parent->_addChildNode(*this); - } + _runSelf(); + _runChildren(); } - void pEpTestTree::_run() const + template + void pEpTestTree::_runSelf() const { - if (_test_func) { + if (_test_func != nullptr) { _test_func(*this); } else { pEpLog::log("No function to execute"); } + } + + template + void pEpTestTree::_runChildren() const + { if (!_children.empty()) { for (const pair child : _children) { - child.second.run(this); + child.second.run(); } } } - void pEpTestTree::_executeInFork(function func, bool wait_child) const + template + void pEpTestTree::_executeInFork(function func, bool wait_child) const { pid_t pid; pid = fork(); @@ -266,7 +296,8 @@ namespace pEp { } } - void pEpTestTree::_waitChildProcesses() const + template + void pEpTestTree::_waitChildProcesses() const { int status; pid_t pid; @@ -277,35 +308,39 @@ namespace pEp { } } - void pEpTestTree::_addChildNode(pEpTestTree& node) + template + void pEpTestTree::_addChildNode(pEpTestTree& node) { _children.insert(pair(node.getNodeName(), node)); } - bool pEpTestTree::_isProcessNode() const + template + bool pEpTestTree::_isProcessNode() const { bool ret = false; - if (_exec_mode == ExecutionMode::PROCESS_SERIAL || + if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL || _exec_mode == ExecutionMode::PROCESS_PARALLEL) { ret = true; } return ret; } - bool pEpTestTree::_isRootNode() const + template + bool pEpTestTree::_isRootNode() const { - bool ret = false; if (_parent == nullptr) { - ret = true; + return true; + } else { + return false; } - return ret; } - const pEpTestTree& pEpTestTree::_getRootNode() const + template + const pEpTestTree& pEpTestTree::_rootNode() const { const pEpTestTree* ret = nullptr; if (!_isRootNode()) { - ret = &(_parent->_getRootNode()); + ret = &(_parent->_rootNode()); } else { ret = this; } @@ -315,17 +350,19 @@ namespace pEp { return *ret; } - const pEpTestTree& pEpTestTree::_getParentingProcessNode() const + template + const pEpTestTree& pEpTestTree::_parentingProcessNode() const { if (_isRootNode() || _isProcessNode()) { return *this; } else { - return _parent->_getParentingProcessNode(); + return _parent->_parentingProcessNode(); } } // name is alphanumeric only (everything else will be replaced by an underscore) - string pEpTestTree::_normalizeName(string name) const + template + string pEpTestTree::_normalizeName(string name) const { replace_if( name.begin(), @@ -336,22 +373,25 @@ namespace pEp { return name; } - void pEpTestTree::_data_dir_create() + template + void pEpTestTree::_data_dir_create() { - // Utils::dir_create(getDataDir()); - pEpLog::log("creating dir:" + getDataRoot()); + // Utils::dir_create(dataDir()); + pEpLog::log("creating dir:" + getGlobalRootDir()); } - void pEpTestTree::_data_dir_delete() + template + void pEpTestTree::_data_dir_delete() { try { - Utils::path_delete_all(getDataRoot()); + Utils::path_delete_all(getGlobalRootDir()); } catch (const exception& e) { - pEpLog::log("DistTest: - could not delete data dir: " + getDataRoot()); + pEpLog::log("DistTest: - could not delete data dir: " + getGlobalRootDir()); } } - void pEpTestTree::_data_dir_recreate() + template + void pEpTestTree::_data_dir_recreate() { _data_dir_delete(); _data_dir_create();