Browse Source

Tests: PityTest - integrate transport into PityUnit

master
heck 4 years ago
parent
commit
3654b5a86d
  1. 52
      src/PityUnit.hh
  2. 309
      src/PityUnit.hxx

52
src/PityUnit.hh

@ -10,12 +10,17 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include "fs_mutex.hh" #include "fs_mutex.hh"
#include "PityTransport.hh"
//#include "PityModel.hh"
// Yes, the mem mgmt is purely static on purpose (so far) // Yes, the mem mgmt is purely static on purpose (so far)
namespace pEp { namespace pEp {
namespace PityTest11 { namespace PityTest11 {
template<class T = void> class PityModel;
class PityPerspective;
template<class T = PityModel, class P = PityPerspective>
class PityUnit { class PityUnit {
public: public:
enum class ExecutionMode enum class ExecutionMode
@ -30,20 +35,20 @@ namespace pEp {
// Constructors are private // Constructors are private
PityUnit() = delete; PityUnit() = delete;
explicit PityUnit<T>( explicit PityUnit<T, P>(
PityUnit<T>* parent, PityUnit<>* parent,
const std::string& name, const std::string& name,
const std::function<void(const PityUnit&)> test_func = nullptr, const std::function<void(PityUnit&, T*, P*)> test_func = nullptr,
T* model = nullptr, T* model = nullptr,
P* perspective = nullptr,
ExecutionMode exec_mode = ExecutionMode::FUNCTION); ExecutionMode exec_mode = ExecutionMode::FUNCTION);
// Read-Only // Read-Only
std::string getName() const; std::string getName() const;
std::string getPath() const; std::string getPath() const;
std::string getPathShort() const; std::string getPathShort() const;
T* getModel() const; std::string processDir(); // own process dir
std::string processDir() const; // own process dir std::string transportDir();
// Read-Write // Read-Write
// void setExecutionMode(ExecutionMode mode); // void setExecutionMode(ExecutionMode mode);
static void setGlobalRootDir(const std::string& dir); static void setGlobalRootDir(const std::string& dir);
@ -52,11 +57,17 @@ namespace pEp {
// Main funcs // Main funcs
void run(); void run();
std::string to_string(bool recursive = true, int indent = 0) const; std::string to_string(bool recursive = true, int indent = 0);
static std::string to_string(const ExecutionMode& emode); static std::string to_string(const ExecutionMode& emode);
// Util // Util
void recreateDirsRecursively() const; void recreateDirsRecursively();
//Transport
PityTransport* transport() const;
void registerAsTransportEndpoint();
Endpoints& transportEndpoints();
// logging service // logging service
void log(const std::string& msg) const; void log(const std::string& msg) const;
@ -73,9 +84,9 @@ namespace pEp {
// METHODS // METHODS
// Execution // Execution
void _init() const; void _init();
void _run() const; void _run();
void _runSelf() const; void _runSelf();
void _runChildren() const; void _runChildren() const;
void _executeInFork(std::function<void(void)> func, bool wait_child) const; void _executeInFork(std::function<void(void)> func, bool wait_child) const;
void _waitChildProcesses() const; void _waitChildProcesses() const;
@ -86,9 +97,13 @@ namespace pEp {
// Query // Query
bool _isProcessUnit() const; bool _isProcessUnit() const;
bool _isRootUnit() const; bool _isRootUnit() const;
const PityUnit& _rootUnit() const; PityUnit* _rootUnit();
std::string _rootUnitDir() const; std::string _rootUnitDir();
const PityUnit& _parentingProcessUnit() const; const PityUnit& _parentingProcessUnit() const;
T* _getModel() const;
P* _getPerspective() const;
void createTransport();
// Util // Util
std::string _normalizeName(std::string name) const; std::string _normalizeName(std::string name) const;
@ -99,14 +114,17 @@ namespace pEp {
// Fields // Fields
const std::string _name; const std::string _name;
const PityUnit* _parent; //nullptr if RootUnit PityUnit* _parent; //nullptr if RootUnit
T* _model; //nullptr if inherited T* _model; //nullptr if inherited
const std::function<void(const PityUnit&)> _test_func; P* _perspective; //nullptr if inherited
const std::function<void(PityUnit&, T*, P*)> _test_func;
ExecutionMode _exec_mode; ExecutionMode _exec_mode;
static std::string _global_root_dir; static std::string _global_root_dir;
std::map<const std::string, PityUnit&> _children; // map to guarantee uniqueness of sibling-names std::map<const std::string, PityUnit&> _children; // map to guarantee uniqueness of sibling-names
int procUnitNr; int procUnitNr;
static int procUnitsCount; // will be increased in everuy constructor static int procUnitsCount; // will be increased in everuy constructor
std::shared_ptr<PityTransport> _transport; //only ever read via transport()
Endpoints _transport_endpoints; // only ever access via transportEndpoints()
std::shared_ptr<fs_mutex> _log_mutex = nullptr; std::shared_ptr<fs_mutex> _log_mutex = nullptr;
// internal logging // internal logging

309
src/PityUnit.hxx

@ -14,33 +14,34 @@
#include <sstream> #include <sstream>
#include <exception> #include <exception>
#include <memory> #include <memory>
#include <memory>
//using namespace pEp::Adapter::pEpLog; //using namespace pEp::Adapter::pEpLog;
namespace pEp { namespace pEp {
namespace PityTest11 { namespace PityTest11 {
// static // static
template<class T> template<class T, class P>
std::string PityUnit<T>::_global_root_dir = "./pitytest_data/"; std::string PityUnit<T, P>::_global_root_dir = "./pitytest_data/";
// static // static
template<class T> template<class T, class P>
bool PityUnit<T>::debug_log_enabled = false; bool PityUnit<T, P>::debug_log_enabled = false;
// static // static
template<class T> template<class T, class P>
int PityUnit<T>::procUnitsCount = 0; int PityUnit<T, P>::procUnitsCount = 0;
// CONSTRUCTOR // CONSTRUCTOR
template<class T> template<class T, class P>
PityUnit<T>::PityUnit( PityUnit<T, P>::PityUnit(
PityUnit<T>* const parent, PityUnit<>* const parent,
const std::string& name, const std::string& name,
const std::function<void(const PityUnit&)> test_func, const std::function<void(PityUnit&, T*, P*)> test_func,
T* model, T* model,
P* perspective,
ExecutionMode exec_mode) : ExecutionMode exec_mode) :
_parent{ parent }, _parent{ parent },
_model{ model }, _name{ _normalizeName(name) }, _test_func{ test_func }, _exec_mode{ _model{ model }, _perspective{ perspective }, _name{ _normalizeName(name) },
exec_mode _test_func{ test_func }, _exec_mode{ exec_mode }
}
{ {
logger_debug.set_instancename(getPath()); logger_debug.set_instancename(getPath());
if (!_isRootUnit()) { if (!_isRootUnit()) {
@ -49,6 +50,7 @@ namespace pEp {
procUnitNr = _parent->procUnitNr; procUnitNr = _parent->procUnitNr;
//Or update if procUnit //Or update if procUnit
if (_isProcessUnit()) { if (_isProcessUnit()) {
createTransport();
procUnitsCount++; procUnitsCount++;
procUnitNr = procUnitsCount; procUnitNr = procUnitsCount;
} }
@ -57,14 +59,14 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
std::string PityUnit<T>::getName() const std::string PityUnit<T, P>::getName() const
{ {
return _name; return _name;
} }
template<class T> template<class T, class P>
std::string PityUnit<T>::getPath() const std::string PityUnit<T, P>::getPath() const
{ {
std::string ret; std::string ret;
@ -81,8 +83,8 @@ namespace pEp {
// ProcessUnit - ".../<proc>" // ProcessUnit - ".../<proc>"
// When Process as dir. parent - ".../<proc>/name" // When Process as dir. parent - ".../<proc>/name"
// When no process as dir. parent - ".../<proc>/.../name" // When no process as dir. parent - ".../<proc>/.../name"
template<class T> template<class T, class P>
std::string PityUnit<T>::getPathShort() const std::string PityUnit<T, P>::getPathShort() const
{ {
std::string ret; std::string ret;
if (_isRootUnit()) { if (_isRootUnit()) {
@ -101,34 +103,18 @@ namespace pEp {
return ret; return ret;
} }
// Inherited (if null see parent recursively)
template<class T>
T* PityUnit<T>::getModel() const
{
pEpLogClass("called");
T* ret = nullptr;
if (_model != nullptr) {
ret = _model;
} else {
if (!_isRootUnit()) {
ret = _parent->getModel();
}
}
return ret;
}
// Every RootUnit has its own dir // Every RootUnit has its own dir
template<class T> template<class T, class P>
std::string PityUnit<T>::_rootUnitDir() const std::string PityUnit<T, P>::_rootUnitDir()
{ {
return getGlobalRootDir() + _rootUnit().getName() + "/"; return getGlobalRootDir() + _rootUnit()->getName() + "/";
} }
// Every process has its own dir inside its rootUnitDir // Every process has its own dir inside its rootUnitDir
// All other units inherit processDir from their Root/ProcessUnit // All other units inherit processDir from their Root/ProcessUnit
template<class T> template<class T, class P>
std::string PityUnit<T>::processDir() const std::string PityUnit<T, P>::processDir()
{ {
if (_isRootUnit()) { if (_isRootUnit()) {
return _rootUnitDir(); return _rootUnitDir();
@ -141,28 +127,44 @@ namespace pEp {
} }
} }
// template<class T> // Every process has its own dir inside its rootUnitDir
// void PityUnit<T>::setExecutionMode(ExecutionMode mode) // All other units inherit transportDir from their Root/ProcessUnit
template<class T, class P>
std::string PityUnit<T, P>::transportDir()
{
if (_isRootUnit()) {
throw std::runtime_error("No transport dir");
} else {
if (_isProcessUnit()) {
return processDir() + "inbox/";
} else {
return _parent->transportDir();
}
}
}
// template<class T, class P>
// void PityUnit<T, P>::setExecutionMode(ExecutionMode mode)
// { // {
// _exec_mode = mode; // _exec_mode = mode;
// } // }
// static // static
template<class T> template<class T, class P>
void PityUnit<T>::setGlobalRootDir(const std::string& dir) void PityUnit<T, P>::setGlobalRootDir(const std::string& dir)
{ {
PityUnit<T>::_global_root_dir = dir; PityUnit<T, P>::_global_root_dir = dir;
} }
// static // static
template<class T> template<class T, class P>
std::string PityUnit<T>::getGlobalRootDir() std::string PityUnit<T, P>::getGlobalRootDir()
{ {
return PityUnit::_global_root_dir; return PityUnit::_global_root_dir;
} }
template<class T> template<class T, class P>
void PityUnit<T>::run() void PityUnit<T, P>::run()
{ {
pEpLogClass("called"); pEpLogClass("called");
_log_mutex = std::make_shared<fs_mutex>("fds"); _log_mutex = std::make_shared<fs_mutex>("fds");
@ -174,10 +176,10 @@ namespace pEp {
// Execute in fork and wait here until process ends // Execute in fork and wait here until process ends
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL) { // fork if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL) { // fork
_executeInFork(std::bind(&PityUnit<T>::_run, this), true); _executeInFork(std::bind(&PityUnit<T, P>::_run, this), true);
// Execute in fork and go on, wait for process execution in the end // Execute in fork and go on, wait for process execution in the end
} else if (_exec_mode == ExecutionMode::PROCESS_PARALLEL) { } else if (_exec_mode == ExecutionMode::PROCESS_PARALLEL) {
_executeInFork(std::bind(&PityUnit<T>::_run, this), false); _executeInFork(std::bind(&PityUnit<T, P>::_run, this), false);
// Execute as normal funciton // Execute as normal funciton
} else if (_exec_mode == ExecutionMode::FUNCTION) { } else if (_exec_mode == ExecutionMode::FUNCTION) {
_run(); _run();
@ -192,8 +194,8 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
std::string PityUnit<T>::to_string(bool recursive, int indent) const std::string PityUnit<T, P>::to_string(bool recursive, int indent)
{ {
std::string ret; std::string ret;
std::stringstream builder; std::stringstream builder;
@ -210,7 +212,7 @@ namespace pEp {
if (recursive) { if (recursive) {
if (!_children.empty()) { if (!_children.empty()) {
indent++; indent++;
for (const std::pair<std::string, const PityUnit<T>&> child : _children) { for (const std::pair<std::string, PityUnit<T, P>&> child : _children) {
ret += child.second.to_string(true, indent); ret += child.second.to_string(true, indent);
} }
indent--; indent--;
@ -219,8 +221,8 @@ namespace pEp {
return ret; return ret;
} }
template<class T> template<class T, class P>
std::string PityUnit<T>::to_string(const ExecutionMode& emode) std::string PityUnit<T, P>::to_string(const ExecutionMode& emode)
{ {
switch (emode) { switch (emode) {
case ExecutionMode::FUNCTION: case ExecutionMode::FUNCTION:
@ -240,8 +242,36 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
void PityUnit<T>::log(const std::string& msg) const void PityUnit<T, P>::recreateDirsRecursively()
{
Utils::dir_recreate(processDir());
if (!_children.empty()) {
for (const std::pair<std::string, PityUnit<T, P>&> child : _children) {
child.second.recreateDirsRecursively();
}
}
}
template<class T, class P>
void PityUnit<T, P>::registerAsTransportEndpoint()
{
transportEndpoints().insert({ getName(), transportDir() });
}
template<class T, class P>
Endpoints& PityUnit<T, P>::transportEndpoints()
{
if (_isRootUnit()) {
return _transport_endpoints;
} else {
return _rootUnit()->transportEndpoints();
}
}
template<class T, class P>
void PityUnit<T, P>::log(const std::string& msg) const
{ {
std::stringstream builder; std::stringstream builder;
builder << "["; builder << "[";
@ -255,28 +285,28 @@ namespace pEp {
} }
template<class T> template<class T, class P>
void PityUnit<T>::logH1(const std::string& msg) const void PityUnit<T, P>::logH1(const std::string& msg) const
{ {
Adapter::pEpLog::logH1(msg, _termColor()); Adapter::pEpLog::logH1(msg, _termColor());
} }
template<class T> template<class T, class P>
void PityUnit<T>::logH2(const std::string& msg) const void PityUnit<T, P>::logH2(const std::string& msg) const
{ {
Adapter::pEpLog::logH2(msg, _termColor()); Adapter::pEpLog::logH2(msg, _termColor());
} }
template<class T> template<class T, class P>
void PityUnit<T>::logH3(const std::string& msg) const void PityUnit<T, P>::logH3(const std::string& msg) const
{ {
Adapter::pEpLog::logH3(msg, _termColor()); Adapter::pEpLog::logH3(msg, _termColor());
} }
// PRIVATE --------------------------------------------------------------------------------- // PRIVATE ---------------------------------------------------------------------------------
template<class T> template<class T, class P>
void PityUnit<T>::_init() const void PityUnit<T, P>::_init()
{ {
logH1("PityTest Starting..."); logH1("PityTest Starting...");
logRaw("RootUnit: " + getPathShort()); logRaw("RootUnit: " + getPathShort());
@ -292,20 +322,20 @@ namespace pEp {
} }
template<class T> template<class T, class P>
void PityUnit<T>::_run() const void PityUnit<T, P>::_run()
{ {
logH2(_status_string("STARTING")); logH2(_status_string("STARTING"));
_runSelf(); _runSelf();
_runChildren(); _runChildren();
} }
template<class T> template<class T, class P>
void PityUnit<T>::_runSelf() const void PityUnit<T, P>::_runSelf()
{ {
if (_test_func != nullptr) { if (_test_func != nullptr) {
try { try {
_test_func(*this); _test_func(*this, _getModel(), _getPerspective());
logH3(_status_string("\033[1m\033[32mSUCCESS" + Utils::to_termcol(_termColor()))); logH3(_status_string("\033[1m\033[32mSUCCESS" + Utils::to_termcol(_termColor())));
} catch (const std::exception& e) { } catch (const std::exception& e) {
logRaw("reason: " + std::string(e.what())); logRaw("reason: " + std::string(e.what()));
@ -316,18 +346,18 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
void PityUnit<T>::_runChildren() const void PityUnit<T, P>::_runChildren() const
{ {
if (!_children.empty()) { if (!_children.empty()) {
for (const std::pair<std::string, PityUnit<T>&> child : _children) { for (const std::pair<std::string, PityUnit<T, P>&> child : _children) {
child.second.run(); child.second.run();
} }
} }
} }
template<class T> template<class T, class P>
void PityUnit<T>::_executeInFork(std::function<void(void)> func, bool wait_child) const void PityUnit<T, P>::_executeInFork(std::function<void(void)> func, bool wait_child) const
{ {
pid_t pid; pid_t pid;
pid = fork(); pid = fork();
@ -342,8 +372,8 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
void PityUnit<T>::_waitChildProcesses() const void PityUnit<T, P>::_waitChildProcesses() const
{ {
int status; int status;
pid_t pid; pid_t pid;
@ -354,14 +384,14 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
void PityUnit<T>::_addChildUnit(PityUnit<T>& unit) void PityUnit<T, P>::_addChildUnit(PityUnit<T, P>& unit)
{ {
_children.insert(std::pair<std::string, PityUnit<T>&>(unit.getName(), unit)); _children.insert(std::pair<std::string, PityUnit<T, P>&>(unit.getName(), unit));
} }
template<class T> template<class T, class P>
bool PityUnit<T>::_isProcessUnit() const bool PityUnit<T, P>::_isProcessUnit() const
{ {
bool ret = false; bool ret = false;
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL || if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL ||
@ -371,8 +401,8 @@ namespace pEp {
return ret; return ret;
} }
template<class T> template<class T, class P>
bool PityUnit<T>::_isRootUnit() const bool PityUnit<T, P>::_isRootUnit() const
{ {
if (_parent == nullptr) { if (_parent == nullptr) {
return true; return true;
@ -381,23 +411,23 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
const PityUnit<T>& PityUnit<T>::_rootUnit() const PityUnit<T, P>* PityUnit<T, P>::_rootUnit()
{ {
const PityUnit<T>* ret = nullptr; // const PityUnit<T, P>* ret = nullptr;
if (!_isRootUnit()) { if (!_isRootUnit()) {
ret = &(_parent->_rootUnit()); return _parent->_rootUnit();
} else { } else {
ret = this; return this;
} }
assert(ret != nullptr); // assert(ret != nullptr);
// cant be null because for createChildUnit() you need to provide a TestUnit& and // cant be null because for createChildUnit() you need to provide a TestUnit& and
// the only other way is using createRootUnit() which has parent == nullptr // the only other way is using createRootUnit() which has parent == nullptr
return *ret; // return *ret;
} }
template<class T> template<class T, class P>
const PityUnit<T>& PityUnit<T>::_parentingProcessUnit() const const PityUnit<T, P>& PityUnit<T, P>::_parentingProcessUnit() const
{ {
if (_isRootUnit() || _isProcessUnit()) { if (_isRootUnit() || _isProcessUnit()) {
return *this; return *this;
@ -406,9 +436,68 @@ namespace pEp {
} }
} }
// Inherited (if null see parent recursively)
template<class T, class P>
T* PityUnit<T, P>::_getModel() const
{
pEpLogClass("called");
T* ret = nullptr;
if (_model != nullptr) {
ret = _model;
} else {
if (!_isRootUnit()) {
ret = _parent->_getModel();
}
}
return ret;
}
// Inherited (if null see parent recursively)
template<class T, class P>
P* PityUnit<T, P>::_getPerspective() const
{
pEpLogClass("called");
P* ret = nullptr;
if (_perspective != nullptr) {
ret = _perspective;
} else {
if (!_isRootUnit()) {
ret = _parent->_getPerspective();
}
}
return ret;
}
// Inherited (if null see parent recursively)
template<class T, class P>
void PityUnit<T, P>::createTransport()
{
registerAsTransportEndpoint();
_transport = std::shared_ptr<PityTransport>(transportDir(), transportEndpoints());
}
// Inherited (if null see parent recursively)
template<class T, class P>
PityTransport* PityUnit<T, P>::transport() const
{
pEpLogClass("called");
PityTransport* ret = nullptr;
if (_transport.get() != nullptr) {
ret = _transport.get();
} else {
if (!_isRootUnit()) {
ret = _parent->transport();
}
}
return ret;
}
// name is alphanumeric only (everything else will be replaced by an underscore) // name is alphanumeric only (everything else will be replaced by an underscore)
template<class T> template<class T, class P>
std::string PityUnit<T>::_normalizeName(std::string name) const std::string PityUnit<T, P>::_normalizeName(std::string name) const
{ {
replace_if( replace_if(
name.begin(), name.begin(),
@ -419,8 +508,8 @@ namespace pEp {
return name; return name;
} }
template<class T> template<class T, class P>
std::string PityUnit<T>::_status_string(const std::string& msg) const std::string PityUnit<T, P>::_status_string(const std::string& msg) const
{ {
std::string ret; std::string ret;
ret = "[ " + to_string(_exec_mode) + ":" + std::to_string(getpid()) + " ] [ " + ret = "[ " + to_string(_exec_mode) + ":" + std::to_string(getpid()) + " ] [ " +
@ -429,8 +518,8 @@ namespace pEp {
} }
template<class T> template<class T, class P>
Utils::Color PityUnit<T>::_colForProcUnitNr(int procUnitNr) const Utils::Color PityUnit<T, P>::_colForProcUnitNr(int procUnitNr) const
{ {
int nrColors = 7; int nrColors = 7;
switch (procUnitNr % nrColors) { switch (procUnitNr % nrColors) {
@ -453,32 +542,20 @@ namespace pEp {
} }
} }
template<class T> template<class T, class P>
Utils::Color PityUnit<T>::_termColor() const Utils::Color PityUnit<T, P>::_termColor() const
{ {
return _colForProcUnitNr(procUnitNr); return _colForProcUnitNr(procUnitNr);
} }
template<class T> template<class T, class P>
void PityUnit<T>::logRaw(const std::string& msg) const void PityUnit<T, P>::logRaw(const std::string& msg) const
{ {
_log_mutex->aquire(); _log_mutex->aquire();
Adapter::pEpLog::log(msg, _termColor()); Adapter::pEpLog::log(msg, _termColor());
_log_mutex->release(); _log_mutex->release();
} }
template<class T>
void PityUnit<T>::recreateDirsRecursively() const
{
Utils::dir_recreate(processDir());
if (!_children.empty()) {
for (const std::pair<std::string, PityUnit<T>&> child : _children) {
child.second.recreateDirsRecursively();
}
}
}
} // namespace PityTest11 } // namespace PityTest11
} // namespace pEp } // namespace pEp

Loading…
Cancel
Save