Browse Source

Tests: PityTest - PityUnit, move tree functionality into base class

LIB-11
heck 11 months ago
parent
commit
f08fd36f42
4 changed files with 248 additions and 111 deletions
  1. +45
    -94
      test/pitytest11/src/AbstractPityUnit.cc
  2. +5
    -17
      test/pitytest11/src/AbstractPityUnit.hh
  3. +59
    -0
      test/pitytest11/src/PityTree.hh
  4. +139
    -0
      test/pitytest11/src/PityTree.hxx

+ 45
- 94
test/pitytest11/src/AbstractPityUnit.cc View File

@ -25,18 +25,29 @@ namespace pEp {
// static
int AbstractPityUnit::procUnitsCount = 0;
AbstractPityUnit::AbstractPityUnit(const std::string &name, ExecutionMode exec_mode) :
PityTree<AbstractPityUnit>(*this, name),
_exec_mode{ exec_mode }
{
_init();
}
AbstractPityUnit::AbstractPityUnit(
AbstractPityUnit *const parent,
AbstractPityUnit &parent,
const std::string &name,
ExecutionMode exec_mode) :
_parent{ parent },
_name{ _normalizeName(name) }, _exec_mode{ exec_mode }
PityTree<AbstractPityUnit>(*this, name, parent),
_exec_mode{ exec_mode }
{
_init();
}
void AbstractPityUnit::_init()
{
logger_debug.set_instancename(getPath());
if (!_isRootUnit()) {
parent->_addChildUnit(*this);
if (!isRoot()) {
// Inherit
procUnitNr = _parent->procUnitNr;
procUnitNr = getParent()->procUnitNr;
//Or update if procUnit
if (_isProcessUnit()) {
_createTransport();
@ -47,36 +58,18 @@ namespace pEp {
procUnitNr = procUnitsCount;
}
}
std::string AbstractPityUnit::getName() const
// static
void AbstractPityUnit::setGlobalRootDir(const std::string &dir)
{
return _name;
AbstractPityUnit::_global_root_dir = dir;
}
// name is alphanumeric only (everything else will be replaced by an underscore)
// static
std::string AbstractPityUnit::_normalizeName(std::string name)
std::string AbstractPityUnit::getGlobalRootDir()
{
replace_if(
name.begin(),
name.end(),
[](char c) -> bool { return !isalnum(c); },
'_');
return name;
return AbstractPityUnit::_global_root_dir;
}
std::string AbstractPityUnit::getPath() const
{
std::string ret;
if (!_isRootUnit()) {
ret = _parent->getPath() + "/" + getName();
} else {
ret = getName();
}
return ret;
}
// For:
// RootUnit - "<name>"
@ -86,13 +79,13 @@ namespace pEp {
std::string AbstractPityUnit::getPathShort() const
{
std::string ret;
if (_isRootUnit()) {
if (isRoot()) {
ret = getName();
} else {
if (_isProcessUnit()) {
ret += ".../" + getName();
} else {
if (&(parentingProcessUnit()) == (_parent)) {
if (&(parentingProcessUnit()) == (getParent())) {
ret = parentingProcessUnit().getPathShort() + "/" + getName();
} else {
ret = parentingProcessUnit().getPathShort() + "/.../" + getName();
@ -102,22 +95,17 @@ namespace pEp {
return ret;
}
AbstractPityUnit *AbstractPityUnit::getParent() const
{
return _parent;
}
// Every process has its own dir inside its rootUnitDir
// All other units inherit processDir from their Root/ProcessUnit
std::string AbstractPityUnit::processDir()
{
if (_isRootUnit()) {
if (isRoot()) {
return _rootUnitDir();
} else {
if (_isProcessUnit()) {
return _rootUnitDir() + getName() + "/";
} else {
return _parent->processDir();
return getParent()->processDir();
}
}
}
@ -125,36 +113,24 @@ namespace pEp {
// Every RootUnit has its own dir
std::string AbstractPityUnit::_rootUnitDir()
{
return getGlobalRootDir() + rootUnit()->getName() + "/";
return getGlobalRootDir() + getRoot().getName() + "/";
}
// Every process has its own dir inside its rootUnitDir
// All other units inherit transportDir from their Root/ProcessUnit
std::string AbstractPityUnit::transportDir()
{
if (_isRootUnit()) {
if (isRoot()) {
throw std::runtime_error("No transport dir");
} else {
if (_isProcessUnit()) {
return processDir() + "inbox/";
} else {
return _parent->transportDir();
return getParent()->transportDir();
}
}
}
// static
void AbstractPityUnit::setGlobalRootDir(const std::string &dir)
{
AbstractPityUnit::_global_root_dir = dir;
}
// static
std::string AbstractPityUnit::getGlobalRootDir()
{
return AbstractPityUnit::_global_root_dir;
}
void AbstractPityUnit::run()
{
pEpLogClass("called");
@ -163,8 +139,8 @@ namespace pEp {
setenv("HOME", processDir().c_str(), true);
if (_isRootUnit()) {
_init();
if (isRoot()) {
_initrun();
}
// Execute in fork and wait here until process ends
@ -182,7 +158,7 @@ namespace pEp {
throw std::invalid_argument(to_string(_exec_mode) + " - not implemented");
}
if (_isRootUnit()) {
if (isRoot()) {
_waitChildProcesses();
}
}
@ -202,9 +178,9 @@ namespace pEp {
ret = builder.str();
if (recursive) {
if (!_children.empty()) {
if (!getChildren().empty()) {
indent++;
for (const std::pair<std::string, AbstractPityUnit &> child : _children) {
for (const auto child : getChildren()) {
ret += child.second.to_string(true, indent);
}
indent--;
@ -236,8 +212,8 @@ namespace pEp {
void AbstractPityUnit::recreateDirsRecursively()
{
Utils::dir_recreate(processDir());
if (!_children.empty()) {
for (const std::pair<std::string, AbstractPityUnit &> child : _children) {
if (!getChildren().empty()) {
for (const auto child : getChildren()) {
child.second.recreateDirsRecursively();
}
}
@ -250,10 +226,10 @@ namespace pEp {
Endpoints &AbstractPityUnit::transportEndpoints()
{
if (_isRootUnit()) {
if (isRoot()) {
return _transport_endpoints;
} else {
return rootUnit()->transportEndpoints();
return getRoot().transportEndpoints();
}
}
@ -286,7 +262,7 @@ namespace pEp {
}
// PRIVATE ---------------------------------------------------------------------------------
void AbstractPityUnit::_init()
void AbstractPityUnit::_initrun()
{
logH1("PityTest Starting...");
_logRaw("RootUnit: " + getPathShort());
@ -310,8 +286,8 @@ namespace pEp {
void AbstractPityUnit::_runChildren() const
{
if (!_children.empty()) {
for (const std::pair<std::string, AbstractPityUnit &> child : _children) {
if (!getChildren().empty()) {
for (const auto child : getChildren()) {
child.second.run();
}
}
@ -350,11 +326,6 @@ namespace pEp {
}
}
void AbstractPityUnit::_addChildUnit(AbstractPityUnit &unit)
{
_children.insert(std::pair<std::string, AbstractPityUnit &>(unit.getName(), unit));
}
bool AbstractPityUnit::_isProcessUnit() const
{
bool ret = false;
@ -365,30 +336,12 @@ namespace pEp {
return ret;
}
bool AbstractPityUnit::_isRootUnit() const
{
if (_parent == nullptr) {
return true;
} else {
return false;
}
}
AbstractPityUnit *AbstractPityUnit::rootUnit()
{
if (!_isRootUnit()) {
return _parent->rootUnit();
} else {
return this;
}
}
const AbstractPityUnit &AbstractPityUnit::parentingProcessUnit() const
{
if (_isRootUnit() || _isProcessUnit()) {
if (isRoot() || _isProcessUnit()) {
return *this;
} else {
return _parent->parentingProcessUnit();
return getParent()->parentingProcessUnit();
}
}
@ -409,8 +362,8 @@ namespace pEp {
if (_transport != nullptr) {
ret = _transport.get();
} else {
if (!_isRootUnit()) {
ret = _parent->transport();
if (!isRoot()) {
ret = getParent()->transport();
}
}
return ret;
@ -449,7 +402,6 @@ namespace pEp {
}
}
Utils::Color AbstractPityUnit::_termColor() const
{
return _colForProcUnitNr(procUnitNr);
@ -465,4 +417,3 @@ namespace pEp {
} // namespace PityTest11
} // namespace pEp

+ 5
- 17
test/pitytest11/src/AbstractPityUnit.hh View File

@ -7,6 +7,7 @@
#include "../../../src/pEpLog.hh"
#include "../../../src/std_utils.hh"
#include "fs_mutex.hh"
#include "PityTree.hh"
#include "PityTransport.hh"
#include <string>
#include <map>
@ -18,7 +19,7 @@
namespace pEp {
namespace PityTest11 {
class AbstractPityUnit {
class AbstractPityUnit : public PityTree<AbstractPityUnit> {
public:
enum class ExecutionMode
{
@ -30,8 +31,9 @@ namespace pEp {
INHERIT
};
AbstractPityUnit(const std::string& name, ExecutionMode exec_mode = ExecutionMode::FUNCTION);
AbstractPityUnit(
AbstractPityUnit* const parent,
AbstractPityUnit& parent,
const std::string& name,
ExecutionMode exec_mode = ExecutionMode::FUNCTION);
@ -40,13 +42,9 @@ namespace pEp {
static std::string getGlobalRootDir();
// Read-Only
std::string getName() const;
std::string getPath() const;
std::string getPathShort() const;
std::string processDir(); // own process dir
std::string transportDir();
AbstractPityUnit* getParent() const;
bool _isRootUnit() const; // true if has no parent
// Main funcs
void run();
@ -61,8 +59,6 @@ namespace pEp {
void logH3(const std::string& msg) const;
// Util
static std::string _normalizeName(
std::string name); //TODO HACK in PityTransport this should be private
void recreateDirsRecursively();
//Transport
@ -87,17 +83,13 @@ namespace pEp {
// METHODS
// Execution
void _init();
void _initrun();
void _run();
virtual void _runSelf() = 0;
void _runChildren() const;
void _executeInFork(std::function<void(void)> func, bool wait_child) const;
void _waitChildProcesses() const;
// Modify
void _addChildUnit(AbstractPityUnit& unit);
AbstractPityUnit* rootUnit();
const AbstractPityUnit& parentingProcessUnit() const;
// Query
@ -107,13 +99,9 @@ namespace pEp {
// Transport
void _createTransport();
// Fields
// ------
AbstractPityUnit* _parent; //nullptr if RootUnit
std::map<const std::string, AbstractPityUnit&> _children; // map to guarantee uniqueness of sibling-names
static std::string _global_root_dir;
const std::string _name;
int procUnitNr;
ExecutionMode _exec_mode;
static int procUnitsCount; // will be increased in every constructor


+ 59
- 0
test/pitytest11/src/PityTree.hh View File

@ -0,0 +1,59 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef PITYTEST_PITYTREE_HH
#define PITYTEST_PITYTREE_HH
//#include "../../../src/pEpLog.hh"
#include <string>
#include <map>
#include <memory>
#include <unordered_map>
#include <functional>
#include <type_traits>
namespace pEp {
namespace PityTest11 {
template<class T>
class PityTree {
// TODO: NEEEEED THIS
// static_assert(std::is_base_of<PityTree<T>, T>::value, "PityTree<T> must be a base of T");
public:
using Children = std::map<const std::string, T&>;
explicit PityTree(T& self, const std::string& name);
explicit PityTree(T& self, const std::string& name, T& parent);
T& add(T& node);
T* getParent() const;
Children getChildren() const;
T& getRoot();
std::string getName() const;
std::string getPath() const;
bool isRoot() const; // true if has no parent
std::string to_string(bool recursive = true, int indent = 0);
//TODO HACK in PityTransport, this should be private
static std::string _normalizeName(std::string name);
virtual ~PityTree() = default;
protected:
void setParent(T* const parent);
private:
// Fields
const std::string _nodename;
T& _self;
T* _parent = nullptr; //nullptr if RootUnit
Children _children; // map to guarantee uniqueness of sibling-names
};
}; // namespace PityTest11
}; // namespace pEp
#include "PityTree.hxx"
#endif

+ 139
- 0
test/pitytest11/src/PityTree.hxx View File

@ -0,0 +1,139 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef PITYTEST_PITYTREE_HXX
#define PITYTEST_PITYTREE_HXX
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <sys/stat.h>
#include <functional>
#include <algorithm>
#include <sstream>
#include <exception>
#include <memory>
#include <unordered_map>
#include <sys/wait.h>
namespace pEp {
namespace PityTest11 {
template<class T>
PityTree<T>::PityTree(T& self, const std::string &name) :
_self{ self }, _nodename{ _normalizeName(name) }
{
}
template<class T>
PityTree<T>::PityTree(T& self, const std::string &name, T& parent) :
_self(self), _nodename{ _normalizeName(name) }
{
parent.add(_self);
}
template<class T>
T& PityTree<T>::add(T& node)
{
node.setParent(&_self);
_children.insert(std::pair<const std::string, T&>(node.getName(), node));
return node;
}
template<class T>
void PityTree<T>::setParent(T *parent)
{
_parent = parent;
}
template<class T>
T *PityTree<T>::getParent() const
{
return _parent;
}
template<class T>
bool PityTree<T>::isRoot() const
{
if (_parent == nullptr) {
return true;
} else {
return false;
}
}
template<class T>
std::string PityTree<T>::getName() const
{
return _nodename;
}
template<class T>
std::string PityTree<T>::getPath() const
{
std::string ret;
if (!isRoot()) {
ret = _parent->getPath() + "/" + getName();
} else {
ret = getName();
}
return ret;
}
template<class T>
std::string PityTree<T>::to_string(bool recursive, int indent)
{
std::string ret;
std::stringstream builder;
builder << std::string(indent * 4, ' ');
builder << getName();
builder << std::endl;
ret = builder.str();
if (recursive) {
if (!getChildren().empty()) {
indent++;
for (auto child : getChildren()) {
ret += child.second.to_string(true, indent);
}
indent--;
}
}
return ret;
}
template<class T>
T& PityTree<T>::getRoot()
{
if (!isRoot()) {
return _parent->getRoot();
} else {
return _self;
}
}
template<class T>
typename PityTree<T>::Children PityTree<T>::getChildren() const
{
return _children;
}
// name is alphanumeric only (everything else will be replaced by an underscore)
// static
template<class T>
std::string PityTree<T>::_normalizeName(std::string name)
{
replace_if(
name.begin(),
name.end(),
[](char c) -> bool { return !isalnum(c); },
'_');
return name;
}
} // namespace PityTest11
} // namespace pEp
#endif

Loading…
Cancel
Save