
commit
e50ed656d7
7 changed files with 694 additions and 0 deletions
@ -0,0 +1,29 @@ |
|||||
|
LDLIBS=-lstdc++ -lpEpAdapter |
||||
|
LDFLAGS=-L../../src/ |
||||
|
CXXFLAGS=-std=c++11 -g |
||||
|
CXXFLAGS+=-I./src |
||||
|
TEST_EXTRA_OBJS=../framework/utils.o |
||||
|
|
||||
|
# Src
|
||||
|
SRC=$(wildcard src/*.cc) |
||||
|
OBJ=$(subst .cc,.o,$(SRC)) |
||||
|
|
||||
|
# Tests
|
||||
|
TEST_SRC=$(wildcard test/*.cc) |
||||
|
TEST_OBJ=$(subst .cc,,$(TEST_SRC)) |
||||
|
|
||||
|
|
||||
|
.PHONY: all clean rmtestdata |
||||
|
.DEFAULT_GOAL := all |
||||
|
|
||||
|
all: $(TEST_OBJ) |
||||
|
|
||||
|
$(TEST_OBJ): $(OBJ) $(TEST_EXTRA_OBJS) |
||||
|
|
||||
|
|
||||
|
clean: |
||||
|
rm -f $(OBJ) |
||||
|
rm -f $(TEST_OBJ) |
||||
|
rm -rf src/*.dSYM |
||||
|
rm -rf test/*.dSYM |
||||
|
|
@ -0,0 +1,16 @@ |
|||||
|
#include "PityModel.hh" |
||||
|
#include "iostream" |
||||
|
|
||||
|
using namespace std; |
||||
|
namespace pEp { |
||||
|
namespace PityTest11 { |
||||
|
bool PityModel::log_enabled = true; |
||||
|
|
||||
|
PityModel::PityModel(const string& name) : name(name) {} |
||||
|
|
||||
|
const std::string& PityModel::getName() const |
||||
|
{ |
||||
|
return name; |
||||
|
} |
||||
|
} // namespace Test
|
||||
|
} // namespace pEp
|
@ -0,0 +1,26 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef PITYTEST_PITYMODEL_HH |
||||
|
#define PITYTEST_PITYMODEL_HH |
||||
|
|
||||
|
#include "../../../src/pEpLog.hh" |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PityTest11 { |
||||
|
class PityModel { |
||||
|
public: |
||||
|
PityModel() = delete; |
||||
|
PityModel(const std::string& name); |
||||
|
virtual const std::string& getName() const; |
||||
|
|
||||
|
private: |
||||
|
const std::string name; |
||||
|
static bool log_enabled; |
||||
|
Adapter::pEpLog::pEpLogger logger{ "PityModel", log_enabled }; |
||||
|
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger; |
||||
|
}; |
||||
|
}; // namespace Test
|
||||
|
}; // namespace pEp
|
||||
|
|
||||
|
#endif // PITYTEST_PITYMODEL_HH
|
@ -0,0 +1,113 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef PITYTEST_PITYUNIT_HH |
||||
|
#define PITYTEST_PITYUNIT_HH |
||||
|
|
||||
|
#include <string> |
||||
|
#include <functional> |
||||
|
#include <map> |
||||
|
#include "../../../src/pEpLog.hh" |
||||
|
|
||||
|
// Yes, the mem mgmt is purely static on purpose (so far)
|
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PityTest11 { |
||||
|
template<class T = void> |
||||
|
class PityUnit { |
||||
|
public: |
||||
|
using NodeFunc = std::function<void(const PityUnit&)>; |
||||
|
|
||||
|
enum class ExecutionMode |
||||
|
{ |
||||
|
FUNCTION, |
||||
|
PROCESS_SEQUENTIAL, |
||||
|
PROCESS_PARALLEL, |
||||
|
THREAD_SEQUENTIAL, // unimplemented
|
||||
|
THREAD_PARALLEL, // unimplemented
|
||||
|
INHERIT |
||||
|
}; |
||||
|
|
||||
|
// Constructors are private
|
||||
|
PityUnit() = delete; |
||||
|
explicit PityUnit( |
||||
|
PityUnit* parent, |
||||
|
const std::string& name, |
||||
|
const NodeFunc test_func = nullptr, |
||||
|
T* model = nullptr, |
||||
|
ExecutionMode exec_mode = ExecutionMode::FUNCTION); |
||||
|
|
||||
|
// Read-Only
|
||||
|
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
|
||||
|
void setExecutionMode(ExecutionMode mode); |
||||
|
static void setGlobalRootDir(const std::string& dir); |
||||
|
static std::string getGlobalRootDir(); |
||||
|
|
||||
|
|
||||
|
// Main funcs
|
||||
|
void run() 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{ "PityUnit", debug_log_enabled }; |
||||
|
|
||||
|
private: |
||||
|
// CONSTRUCTORS
|
||||
|
|
||||
|
// METHODS
|
||||
|
// Execution
|
||||
|
void _runRootNode() const; |
||||
|
void _run() const; |
||||
|
void _runSelf() const; |
||||
|
void _runChildren() const; |
||||
|
void _executeInFork(std::function<void(void)> func, bool wait_child) const; |
||||
|
void _waitChildProcesses() const; |
||||
|
|
||||
|
// Modify
|
||||
|
void _addChildNode(PityUnit& node); |
||||
|
|
||||
|
// Query
|
||||
|
bool _isProcessNode() const; |
||||
|
bool _isRootNode() const; |
||||
|
const PityUnit& _rootNode() const; |
||||
|
const PityUnit& _parentingProcessNode() 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 PityUnit* _parent; //nullptr if RootUnit
|
||||
|
T* _model; //nullptr if inherited
|
||||
|
const NodeFunc _test_func; |
||||
|
ExecutionMode _exec_mode; |
||||
|
static std::string _global_root_dir; |
||||
|
|
||||
|
std::map<const std::string, PityUnit&> _children; // map to guarantee uniqueness of sibling-names
|
||||
|
|
||||
|
// internal logging
|
||||
|
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
||||
|
}; |
||||
|
}; // namespace Test
|
||||
|
}; // namespace pEp
|
||||
|
|
||||
|
#include "PityUnit.hxx" |
||||
|
|
||||
|
#endif // PITYTEST_PITYUNIT_HH
|
@ -0,0 +1,390 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#ifndef PITYTEST_PITYUNIT_HXX |
||||
|
#define PITYTEST_PITYUNIT_HXX |
||||
|
|
||||
|
#include "../../../src/std_utils.hh" |
||||
|
#include "../../framework/utils.hh" |
||||
|
#include <iostream> |
||||
|
#include <unistd.h> |
||||
|
#include <cstdlib> |
||||
|
#include <sys/stat.h> |
||||
|
#include <functional> |
||||
|
#include <algorithm> |
||||
|
#include <sstream> |
||||
|
|
||||
|
|
||||
|
using namespace pEp::Adapter::pEpLog; |
||||
|
|
||||
|
namespace pEp { |
||||
|
namespace PityTest11 { |
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::_global_root_dir = "./pitytest"; |
||||
|
template<class T> |
||||
|
bool PityUnit<T>::debug_log_enabled = false; |
||||
|
|
||||
|
// PUBLIC CONCSTRUCTORS / FACTORY -----------------------------------------------------------
|
||||
|
template<class T> |
||||
|
PityUnit<T>::PityUnit( |
||||
|
PityUnit* const parent, |
||||
|
const std::string& name, |
||||
|
const NodeFunc test_func, |
||||
|
T* model, |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::getNodeName() const |
||||
|
{ |
||||
|
return _name; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::getNodePath() const |
||||
|
{ |
||||
|
std::string ret; |
||||
|
|
||||
|
if (!_isRootNode()) { |
||||
|
ret = _parent->getNodePath() + "/" + getNodeName(); |
||||
|
} else { |
||||
|
ret = getNodeName(); |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
// For:
|
||||
|
// RootNode - "<name>"
|
||||
|
// ProcessNode - ".../<proc>"
|
||||
|
// When Process as dir. parent - ".../<proc>/name"
|
||||
|
// When no process as dir. parent - ".../<proc>/.../name"
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::getNodePathShort() const |
||||
|
{ |
||||
|
std::string ret; |
||||
|
if (_isRootNode()) { |
||||
|
ret = getNodeName(); |
||||
|
} else { |
||||
|
if (_isProcessNode()) { |
||||
|
ret += ".../" + getNodeName(); |
||||
|
} else { |
||||
|
if (&(_parentingProcessNode()) == (_parent)) { |
||||
|
ret = _parentingProcessNode().getNodePathShort() + "/" + getNodeName(); |
||||
|
} else { |
||||
|
ret = _parentingProcessNode().getNodePathShort() + "/.../" + getNodeName(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
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 (!_isRootNode()) { |
||||
|
ret = _parent->getModel(); |
||||
|
} |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
// Every RootNode has its own dir
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::rootNodeDir() const |
||||
|
{ |
||||
|
return getGlobalRootDir() + _rootNode().getNodeName() + "/"; |
||||
|
} |
||||
|
|
||||
|
// Every process has its own dir inside its rootNodeDir
|
||||
|
// All other nodes inherit processDir from their Root/ProcessNode
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::processDir() const |
||||
|
{ |
||||
|
if (_isRootNode()) { |
||||
|
return rootNodeDir(); |
||||
|
} else { |
||||
|
if (_isProcessNode()) { |
||||
|
return rootNodeDir() + getNodeName() + "/"; |
||||
|
} else{ |
||||
|
return _parent->processDir(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::setExecutionMode(ExecutionMode mode) |
||||
|
{ |
||||
|
_exec_mode = mode; |
||||
|
} |
||||
|
|
||||
|
// static
|
||||
|
template<> |
||||
|
void PityUnit<void>::setGlobalRootDir(const std::string& dir) |
||||
|
{ |
||||
|
PityUnit::_global_root_dir = dir; |
||||
|
} |
||||
|
|
||||
|
// static
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::getGlobalRootDir() |
||||
|
{ |
||||
|
return PityUnit::_global_root_dir; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::run() const |
||||
|
{ |
||||
|
pEpLogClass("called"); |
||||
|
// caller is never nullptr if called by another PityUnit
|
||||
|
if (_isRootNode()) { |
||||
|
logH1("Starting PityUnit from node: " + getNodePathShort()); |
||||
|
log(to_string()); |
||||
|
} |
||||
|
|
||||
|
// Execute in fork and wait here until process ends
|
||||
|
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL) { // fork
|
||||
|
logH2("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + " ]"); |
||||
|
_executeInFork(std::bind(&PityUnit::_run, this), true); |
||||
|
// Execute in fork and go on, wait for process execution in the end
|
||||
|
} else if (_exec_mode == ExecutionMode::PROCESS_PARALLEL) { |
||||
|
logH2("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + " ]"); |
||||
|
_executeInFork(std::bind(&PityUnit::_run, this), false); |
||||
|
// Execute as normal funciton
|
||||
|
} else if (_exec_mode == ExecutionMode::FUNCTION) { |
||||
|
logH3("[ " + to_string(_exec_mode) + " / " + getNodePathShort() + " ]"); |
||||
|
_run(); |
||||
|
} else if (_exec_mode == ExecutionMode::THREAD_PARALLEL) { |
||||
|
throw std::invalid_argument(to_string(_exec_mode) + " - not implemented"); |
||||
|
} else if (_exec_mode == ExecutionMode::THREAD_SEQUENTIAL) { |
||||
|
throw std::invalid_argument(to_string(_exec_mode) + " - not implemented"); |
||||
|
} |
||||
|
|
||||
|
if(_isRootNode()) { |
||||
|
_waitChildProcesses(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::to_string(bool recursive, int indent) const |
||||
|
{ |
||||
|
std::string ret; |
||||
|
std::stringstream builder; |
||||
|
builder << std::string(indent * 4, ' '); |
||||
|
|
||||
|
builder << getNodeName(); |
||||
|
builder << " [ "; |
||||
|
builder << to_string(_exec_mode) << " - "; |
||||
|
builder << "\"" << processDir() << "\""; |
||||
|
builder << " ]"; |
||||
|
builder << std::endl; |
||||
|
ret = builder.str(); |
||||
|
|
||||
|
if (recursive) { |
||||
|
indent++; |
||||
|
for (const std::pair<std::string, const PityUnit&> child : _children) { |
||||
|
ret += child.second.to_string(true, indent); |
||||
|
} |
||||
|
indent--; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::to_string(const ExecutionMode& emode) |
||||
|
{ |
||||
|
switch (emode) { |
||||
|
case ExecutionMode::FUNCTION: |
||||
|
return "FUNCTION"; |
||||
|
case ExecutionMode::PROCESS_SEQUENTIAL: |
||||
|
return "PROC_SEQ"; |
||||
|
case ExecutionMode::PROCESS_PARALLEL: |
||||
|
return "PROC_PAR"; |
||||
|
case ExecutionMode::THREAD_SEQUENTIAL: |
||||
|
return "THREAD_S"; |
||||
|
case ExecutionMode::THREAD_PARALLEL: |
||||
|
return "THREAD_P"; |
||||
|
case ExecutionMode::INHERIT: |
||||
|
return "INHERIT"; |
||||
|
default: |
||||
|
return "UNDEFINED EXECUTION MODE"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//Well, ok, lets just add some little convenience logging service in here, too
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::log(const std::string& msg) const |
||||
|
{ |
||||
|
std::stringstream builder; |
||||
|
builder << "["; |
||||
|
builder << std::to_string(getpid()); |
||||
|
builder << " - "; |
||||
|
builder << getNodePathShort(); |
||||
|
builder << "] - "; |
||||
|
builder << msg; |
||||
|
builder << std::endl; |
||||
|
std::cout << builder.str(); |
||||
|
} |
||||
|
|
||||
|
// PRIVATE ---------------------------------------------------------------------------------
|
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_run() const |
||||
|
{ |
||||
|
_runSelf(); |
||||
|
_runChildren(); |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_runSelf() const |
||||
|
{ |
||||
|
if (_test_func != nullptr) { |
||||
|
_test_func(*this); |
||||
|
} else { |
||||
|
log("No function to execute"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_runChildren() const |
||||
|
{ |
||||
|
if (!_children.empty()) { |
||||
|
for (const std::pair<std::string, PityUnit&> child : _children) { |
||||
|
child.second.run(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_executeInFork(std::function<void(void)> 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 std::runtime_error("Error forking"); |
||||
|
} |
||||
|
if (wait_child) { |
||||
|
_waitChildProcesses(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_waitChildProcesses() const |
||||
|
{ |
||||
|
int status; |
||||
|
pid_t pid; |
||||
|
while ((pid = wait(&status)) > 0) { |
||||
|
log( |
||||
|
"process[" + std::to_string((int)pid) + |
||||
|
"] terminated with status: " + std::to_string(status)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_addChildNode(PityUnit& node) |
||||
|
{ |
||||
|
_children.insert(std::pair<std::string, PityUnit&>(node.getNodeName(), node)); |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
bool PityUnit<T>::_isProcessNode() const |
||||
|
{ |
||||
|
bool ret = false; |
||||
|
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL || |
||||
|
_exec_mode == ExecutionMode::PROCESS_PARALLEL) { |
||||
|
ret = true; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
bool PityUnit<T>::_isRootNode() const |
||||
|
{ |
||||
|
if (_parent == nullptr) { |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
const PityUnit<T>& PityUnit<T>::_rootNode() const |
||||
|
{ |
||||
|
const PityUnit* ret = nullptr; |
||||
|
if (!_isRootNode()) { |
||||
|
ret = &(_parent->_rootNode()); |
||||
|
} 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; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
const PityUnit<T>& PityUnit<T>::_parentingProcessNode() const |
||||
|
{ |
||||
|
if (_isRootNode() || _isProcessNode()) { |
||||
|
return *this; |
||||
|
} else { |
||||
|
return _parent->_parentingProcessNode(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// name is alphanumeric only (everything else will be replaced by an underscore)
|
||||
|
template<class T> |
||||
|
std::string PityUnit<T>::_normalizeName(std::string name) const |
||||
|
{ |
||||
|
replace_if( |
||||
|
name.begin(), |
||||
|
name.end(), |
||||
|
[](char c) -> bool { return !isalnum(c); }, |
||||
|
'_'); |
||||
|
|
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_data_dir_create() |
||||
|
{ |
||||
|
// Utils::dir_create(dataDir());
|
||||
|
log("creating dir:" + getGlobalRootDir()); |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_data_dir_delete() |
||||
|
{ |
||||
|
try { |
||||
|
Utils::path_delete_all(getGlobalRootDir()); |
||||
|
} catch (const std::exception& e) { |
||||
|
log("DistTest: - could not delete data dir: " + getGlobalRootDir()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<class T> |
||||
|
void PityUnit<T>::_data_dir_recreate() |
||||
|
{ |
||||
|
_data_dir_delete(); |
||||
|
_data_dir_create(); |
||||
|
}; |
||||
|
} // namespace Test
|
||||
|
} // namespace pEp
|
||||
|
|
||||
|
#endif // PITYTEST_PITYUNIT_HXX
|
@ -0,0 +1,65 @@ |
|||||
|
#include "../src/PityUnit.hh" |
||||
|
#include <iostream> |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace pEp::PityTest11; |
||||
|
|
||||
|
void printHomeDir(const PityUnit<>& myself, int sleepmilis, int rep_count) |
||||
|
{ |
||||
|
int i = 0; |
||||
|
while (i < rep_count) { |
||||
|
myself.log(myself.getNodeName() + " - " + to_string(i)); |
||||
|
sleep_millis(sleepmilis); |
||||
|
i++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char* argv[]) |
||||
|
{ |
||||
|
{ |
||||
|
// DEBUG Logging of PityTestUnit itself
|
||||
|
PityUnit<>::debug_log_enabled = false; |
||||
|
|
||||
|
// Configure DataRoot for all TestNodes
|
||||
|
PityUnit<>::setGlobalRootDir("./basic_data_root"); |
||||
|
|
||||
|
// The RootNode is the
|
||||
|
PityUnit<> root = PityUnit<>{ nullptr, "Test Execution Model" }; |
||||
|
|
||||
|
// Subprocess 1
|
||||
|
PityUnit<> test1 = PityUnit<>{ &root, |
||||
|
"node1", |
||||
|
[](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
}, |
||||
|
nullptr, |
||||
|
pEp::PityTest11::PityUnit<>::ExecutionMode::PROCESS_PARALLEL }; |
||||
|
|
||||
|
PityUnit<> test1_1 = PityUnit<>{ &test1, "test1.1", [](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
} }; |
||||
|
|
||||
|
PityUnit<> test1_2 = PityUnit<>{ &test1, "test1.2", [](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
} }; |
||||
|
|
||||
|
// Subprocess 2
|
||||
|
PityUnit<> test2 = PityUnit<>{ &root, |
||||
|
"node2", |
||||
|
[](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
}, |
||||
|
nullptr, |
||||
|
pEp::PityTest11::PityUnit<>::ExecutionMode::PROCESS_PARALLEL }; |
||||
|
|
||||
|
PityUnit<> test2_1 = PityUnit<>{ &test2, "test2.1", [](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
} }; |
||||
|
|
||||
|
PityUnit<> test2_2 = PityUnit<>{ &test2, "test2.2", [](const PityUnit<>& mynode) { |
||||
|
printHomeDir(mynode, 200, 10); |
||||
|
} }; |
||||
|
|
||||
|
test1.run(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
#include "../src/PityUnit.hh" |
||||
|
#include "../../framework/utils.hh" |
||||
|
#include <iostream> |
||||
|
#include <algorithm> |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace pEp::PityTest11; |
||||
|
|
||||
|
void printHomeDir(const PityUnit<>& myself) |
||||
|
{ |
||||
|
// TESTLOG(string(myself.getFQName() + " - PID: " + to_string(getpid())));
|
||||
|
// cout << "[" << to_string(getpid()) << "/" << myself.getFQName() << "] - " << endl;
|
||||
|
setenv("HOME", myself.processDir().c_str(), 1); |
||||
|
myself.log("HOME=" + string(getenv("HOME"))); |
||||
|
} |
||||
|
|
||||
|
void ptAssert(bool condition) { |
||||
|
if(!condition) { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char* argv[]) |
||||
|
{ |
||||
|
PityUnit<>::debug_log_enabled = false; |
||||
|
PityUnit<>::setGlobalRootDir("./"); |
||||
|
PityUnit<> root = PityUnit<>{ nullptr, "rootnode" }; |
||||
|
|
||||
|
PityUnit<> test1 = PityUnit<>{ &root, "node 1", [](const PityUnit<>& mynode) { |
||||
|
assert(mynode.processDir() == "./rootnode/"); |
||||
|
} }; |
||||
|
|
||||
|
PityUnit<> test1_1 = PityUnit<>{ &test1, "node 1.1", [](const PityUnit<>& mynode) { |
||||
|
assert(mynode.processDir() == "./rootnode/"); |
||||
|
} }; |
||||
|
|
||||
|
PityUnit<> test2 = PityUnit<>{ &root, "node 2", [](const PityUnit<>& mynode) { |
||||
|
assert(mynode.processDir() == "./rootnode/"); |
||||
|
} }; |
||||
|
|
||||
|
PityUnit<> test2_1 = PityUnit<>{ &test2, |
||||
|
"node 2.1", |
||||
|
[](const PityUnit<>& mynode) { |
||||
|
assert(mynode.processDir() == "./rootnode/"); |
||||
|
}, |
||||
|
nullptr, |
||||
|
pEp::PityTest11::PityUnit<>::ExecutionMode::PROCESS_PARALLEL }; |
||||
|
|
||||
|
|
||||
|
PityUnit<> test2_1_1 = PityUnit<>{ &test2_1, "node 2.1.1", [](PityUnit<> mynode) { |
||||
|
assert(mynode.processDir() == "./rootnode/"); |
||||
|
} }; |
||||
|
|
||||
|
root.run(); |
||||
|
} |
Loading…
Reference in new issue