
40 changed files with 21 additions and 2876 deletions
@ -1,270 +0,0 @@ |
|||
#include "test_utils.hh" |
|||
|
|||
#include <pEp/pEpEngine.h> |
|||
#include <pEp/message_api.h> |
|||
#include <pEp/keymanagement.h> |
|||
#include <pEp/identity_list.h> |
|||
#include <pEp/Adapter.hh> |
|||
#include <pEp/status_to_string.hh> |
|||
#include <pEp/mime.h> |
|||
#include <tuple> |
|||
|
|||
namespace pEp { |
|||
namespace Test { |
|||
namespace Utils { |
|||
|
|||
//Ident
|
|||
pEpIdent wrap(::pEp_identity *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdent(ident, [](::pEp_identity *) {}); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdent appropriate(::pEp_identity *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdent(ident, ::free_identity); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdent dup(const ::pEp_identity *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdent(::identity_dup(ident), ::free_identity); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdent kill(::pEp_identity *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdent(::identity_dup(ident), ::free_identity); |
|||
::free_identity(ident); |
|||
return ret; |
|||
} |
|||
|
|||
//IdentityList
|
|||
pEpIdentList wrap(::identity_list *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdentList(ident, [](::identity_list *) {}); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdentList appropriate(::identity_list *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdentList(ident, ::free_identity_list); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdentList dup(const ::identity_list *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdentList(::identity_list_dup(ident), ::free_identity_list); |
|||
return ret; |
|||
} |
|||
|
|||
pEpIdentList kill(::identity_list *const ident) |
|||
{ |
|||
assert(ident); |
|||
auto ret = pEpIdentList(::identity_list_dup(ident), ::free_identity_list); |
|||
::free_identity_list(ident); |
|||
return ret; |
|||
} |
|||
|
|||
//Message
|
|||
pEpMessage wrap(::message *const msg) |
|||
{ |
|||
assert(msg); |
|||
auto ret = pEpMessage(msg, [](::message *) {}); |
|||
return ret; |
|||
} |
|||
|
|||
pEpMessage appropriate(::message *const msg) |
|||
{ |
|||
assert(msg); |
|||
auto ret = pEpMessage(msg, ::free_message); |
|||
return ret; |
|||
} |
|||
|
|||
pEpMessage dup(const ::message *const msg) |
|||
{ |
|||
assert(msg); |
|||
auto ret = pEpMessage(::message_dup(msg), ::free_message); |
|||
return ret; |
|||
} |
|||
|
|||
pEpMessage kill(::message *const msg) |
|||
{ |
|||
assert(msg); |
|||
auto ret = pEpMessage(::message_dup(msg), ::free_message); |
|||
::free_message(msg); |
|||
return ret; |
|||
} |
|||
|
|||
// helpers
|
|||
pEpIdent createOwnIdent(const std::string &address) |
|||
{ |
|||
std::string name; |
|||
::pEp_identity *ident = nullptr; |
|||
ident = ::new_identity( |
|||
strdup(address.c_str()), |
|||
"", |
|||
PEP_OWN_USERID, |
|||
("myself " + address).c_str()); |
|||
ident->me = true; |
|||
|
|||
return appropriate(ident); |
|||
} |
|||
|
|||
pEpIdent createCptIdent(const std::string &address) |
|||
{ |
|||
std::string name; |
|||
::pEp_identity *ident = nullptr; |
|||
ident = ::new_identity( |
|||
strdup(address.c_str()), |
|||
"", |
|||
"", |
|||
("partner " + address).c_str()); |
|||
ident->me = false; |
|||
|
|||
return appropriate(ident); |
|||
} |
|||
|
|||
pEpIdent createRawIdent(const std::string &address) |
|||
{ |
|||
std::string name; |
|||
::pEp_identity *ident = nullptr; |
|||
ident = ::new_identity(strdup(address.c_str()), "", "", ""); |
|||
ident->me = false; |
|||
|
|||
return appropriate(ident); |
|||
} |
|||
|
|||
pEpIdentList createIdentityList(const std::vector<std::string> &addresses) |
|||
{ |
|||
::identity_list *list; |
|||
list = ::new_identity_list(nullptr); |
|||
for (std::string addr : addresses) { |
|||
::identity_list_add(list, ::identity_dup(createCptIdent(addr).get())); |
|||
} |
|||
return appropriate(list); |
|||
} |
|||
|
|||
pEpMessage createMessage(pEpIdent from, pEpIdent to, const std::string &longmsg) |
|||
{ |
|||
// create and fill in msg
|
|||
::message *msg = ::new_message(PEP_dir_outgoing); |
|||
msg->from = ::identity_dup(from.get()); |
|||
msg->to = ::new_identity_list(::identity_dup(to.get())); |
|||
msg->longmsg = strdup(longmsg.c_str()); |
|||
|
|||
pEpMessage ret = appropriate(msg); |
|||
return ret; |
|||
} |
|||
|
|||
pEpMessage createMessage(pEpIdent from, const std::string &to_addr, const std::string &longmsg) |
|||
{ |
|||
pEpIdent to_ident = createCptIdent(to_addr); |
|||
return createMessage(from, to_ident, longmsg); |
|||
} |
|||
|
|||
std::string mimeEncode(const pEpMessage msg) |
|||
{ |
|||
char *mimetext; |
|||
PEP_STATUS status = ::mime_encode_message(msg.get(), false, &mimetext, false); |
|||
throw_status(status); |
|||
std::string text{ mimetext }; |
|||
free(mimetext); |
|||
return text; |
|||
} |
|||
|
|||
pEpMessage mimeDecode(const std::string &mime_text) |
|||
{ |
|||
::message *msg; |
|||
bool has_possible_pEp_msg; |
|||
::PEP_STATUS status = ::mime_decode_message( |
|||
mime_text.c_str(), |
|||
mime_text.length(), |
|||
&msg, |
|||
&has_possible_pEp_msg); |
|||
throw_status(status); |
|||
return pEpMessage(msg, ::free_message); |
|||
} |
|||
|
|||
EncryptResult encryptMessage(const pEpMessage msg) |
|||
{ |
|||
pEpMessage msg_out; |
|||
bool could_encrypt = false; |
|||
::message *msgenc = nullptr; |
|||
PEP_STATUS status = ::encrypt_message( |
|||
Adapter::session(), |
|||
msg.get(), |
|||
nullptr, |
|||
&msgenc, |
|||
PEP_enc_PEP, |
|||
0); |
|||
throw_status(status); |
|||
::message *msg_out_p = nullptr; |
|||
if (msgenc != nullptr) { |
|||
could_encrypt = true; |
|||
msg_out = appropriate(msgenc); |
|||
} else { |
|||
could_encrypt = false; |
|||
msg_out = msg; |
|||
} |
|||
return EncryptResult(msg_out, "", could_encrypt); |
|||
} |
|||
|
|||
|
|||
DecryptResult decryptMessage(const pEpMessage msg, ::PEP_decrypt_flags_t *flags) |
|||
{ |
|||
pEpMessage msg_out; |
|||
bool was_encrypted = false; |
|||
|
|||
::message *dec{ nullptr }; |
|||
::stringlist_t *kl = ::new_stringlist(""); |
|||
::PEP_rating rating; |
|||
PEP_STATUS status = ::decrypt_message( |
|||
Adapter::session(), |
|||
msg.get(), |
|||
&dec, |
|||
&kl, |
|||
&rating, |
|||
flags); |
|||
throw_status(status); |
|||
if (dec != nullptr) { |
|||
was_encrypted = true; |
|||
msg_out = appropriate(dec); |
|||
} else { |
|||
was_encrypted = false; |
|||
msg_out = msg; |
|||
} |
|||
return DecryptResult(msg_out, rating, kl, flags, was_encrypted); |
|||
} |
|||
|
|||
DecryptResult decryptMessage(const pEpMessage msg) |
|||
{ |
|||
::PEP_decrypt_flags_t dummy{ 0 }; |
|||
return decryptMessage(msg, &dummy); |
|||
} |
|||
|
|||
EncryptResult encryptAndEncode(const pEpMessage msg) |
|||
{ |
|||
EncryptResult ret = encryptMessage(msg); |
|||
std::string mime_text = mimeEncode(std::get<0>(ret)); |
|||
std::get<1>(ret) = mime_text; |
|||
return ret; |
|||
} |
|||
|
|||
DecryptResult decryptAndDecode(const std::string &mime_data) |
|||
{ |
|||
DecryptResult ret; |
|||
pEpMessage rx_msg = mimeDecode(mime_data); |
|||
ret = decryptMessage(rx_msg); |
|||
return ret; |
|||
} |
|||
} // namespace Utils
|
|||
} // namespace Test
|
|||
} // namespace pEp
|
@ -1,132 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef LIBPEPADAPTER_TEST_UTILS_HH |
|||
#define LIBPEPADAPTER_TEST_UTILS_HH |
|||
|
|||
#include "../../src/pEpLog.hh" |
|||
#include <string> |
|||
#include <exception> |
|||
#include <chrono> |
|||
#include <thread> |
|||
#include <cstring> |
|||
#include <tuple> |
|||
#include <pEp/pEpEngine.h> |
|||
#include <pEp/identity_list.h> |
|||
#include <pEp/message.h> |
|||
#include <pEp/message_api.h> |
|||
|
|||
// ------------------------------------------------------------------------------------------------
|
|||
|
|||
#ifndef ASSERT_EXCEPT |
|||
#define ASSERT_EXCEPT(func) \ |
|||
do { \ |
|||
try { \ |
|||
(func); \ |
|||
assert(false); \ |
|||
} catch (const exception &e) { \ |
|||
pEp::Adapter::pEpLog::log(nested_exception_to_string(e)); \ |
|||
} \ |
|||
} while (0) |
|||
#endif |
|||
|
|||
// ------------------------------------------------------------------------------------------------
|
|||
// Logging macros for testing
|
|||
// ------------------------------------------------------------------------------------------------
|
|||
// Use the macros if you need the message to be prefixed with "thread - __FILE__::__FUNTION__"
|
|||
// OTHERWISE, just use the logging functions from pEp::Adapter::pEpLog
|
|||
|
|||
// TESTLOG - logformat "thread - __FILE__::__FUNTION__ - <message>"
|
|||
// To be used in a non-class/object context
|
|||
#ifndef TESTLOG |
|||
#define TESTLOG(msg) \ |
|||
do { \ |
|||
std::stringstream msg_; \ |
|||
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]"; \ |
|||
msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \ |
|||
msg_ << " - " << msg; \ |
|||
pEp::Adapter::pEpLog::log(msg_.str()); \ |
|||
} while (0) |
|||
#endif // TESTLOG
|
|||
|
|||
// TESTLOGH1 - logformat "Thread - __FILE__::__FUNTION__ - <=============== message ==============>"
|
|||
#ifndef TESTLOGH1 |
|||
#define TESTLOGH1(msg) \ |
|||
do { \ |
|||
std::stringstream msg_; \ |
|||
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]"; \ |
|||
msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \ |
|||
msg_ << " - " << pEp::Adapter::pEpLog::decorateH1(msg); \ |
|||
pEp::Adapter::pEpLog::log(msg_.str()); \ |
|||
} while (0) |
|||
#endif // TESTLOGH1
|
|||
|
|||
// TESTLOGH2 - logformat "Thread - __FILE__::__FUNTION__ - <--------------- message -------------->"
|
|||
#ifndef TESTLOGH2 |
|||
#define TESTLOGH2(msg) \ |
|||
do { \ |
|||
std::stringstream msg_; \ |
|||
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]"; \ |
|||
msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \ |
|||
msg_ << " - " << pEp::Adapter::pEpLog::decorateH2(msg); \ |
|||
pEp::Adapter::pEpLog::log(msg_.str()); \ |
|||
} while (0) |
|||
#endif // TESTLOGH2
|
|||
|
|||
// ------------------------------------------------------------------------------------------------
|
|||
|
|||
namespace pEp { |
|||
namespace Test { |
|||
namespace Utils { |
|||
using pEpIdent = std::shared_ptr<::pEp_identity>; |
|||
using pEpIdentList = std::shared_ptr<::identity_list>; |
|||
using pEpMessage = std::shared_ptr<::message>; |
|||
// [ DecryptedMessage, Rating, KeyList, Flags, WasEncrypted ]
|
|||
using DecryptResult = std:: |
|||
tuple<pEpMessage, ::PEP_rating, ::stringlist_t *, ::PEP_decrypt_flags_t *, bool>; |
|||
// [ EncryptedMessage, MimeText, couldEncrypt ]
|
|||
using EncryptResult = std::tuple<pEpMessage, std::string, bool>; |
|||
|
|||
// Datatypes
|
|||
//Ident
|
|||
pEpIdent wrap(::pEp_identity *const ident); |
|||
pEpIdent appropriate(::pEp_identity *const ident); |
|||
pEpIdent dup(const ::pEp_identity *const ident); |
|||
pEpIdent kill(::pEp_identity *const ident); |
|||
|
|||
//IdentityList
|
|||
pEpIdentList wrap(::identity_list *const ident); |
|||
pEpIdentList appropriate(::identity_list *const ident); |
|||
pEpIdentList dup(const ::identity_list *const ident); |
|||
pEpIdentList kill(::identity_list *const ident); |
|||
|
|||
//Message
|
|||
pEpMessage wrap(::message *const msg); |
|||
pEpMessage appropriate(::message *const msg); |
|||
pEpMessage dup(const ::message *const msg); |
|||
pEpMessage kill(::message *const msg); |
|||
|
|||
// helpers
|
|||
pEpIdent createOwnIdent(const std::string &address); |
|||
pEpIdent createCptIdent(const std::string &address); |
|||
pEpIdent createRawIdent(const std::string &address); |
|||
pEpIdentList createIdentityList(const std::vector<std::string> &addresses); |
|||
pEpMessage createMessage(pEpIdent from, pEpIdent to, const std::string &longmsg); |
|||
pEpMessage createMessage(pEpIdent from, const std::string &to_addr, const std::string &longmsg); |
|||
|
|||
|
|||
std::string mimeEncode(const pEpMessage msg); |
|||
pEpMessage mimeDecode(const std::string &mime_text); |
|||
|
|||
EncryptResult encryptMessage(const pEpMessage msg); |
|||
DecryptResult decryptMessage(const pEpMessage msg, ::PEP_decrypt_flags_t *flags); |
|||
DecryptResult decryptMessage(const pEpMessage msg); |
|||
|
|||
EncryptResult encryptAndEncode(const pEpMessage msg); |
|||
DecryptResult decryptAndDecode(const std::string &mime_data); |
|||
|
|||
} // namespace Utils
|
|||
} // namespace Test
|
|||
} // namespace pEp
|
|||
|
|||
#endif // LIBPEPADAPTER_TEST_UTILS_HH
|
@ -1,39 +0,0 @@ |
|||
include ../../Makefile.conf |
|||
|
|||
TARGET=src/libPityTest.a |
|||
LDFLAGS:=-L../../src/ $(LDFLAGS) -L../framework/ |
|||
LDLIBS=-lstdc++ -lpEpAdapter -lpEpEngine -lpthread -ldl |
|||
CXXFLAGS:=-std=c++11 -g -I./src $(CXXFLAGS) |
|||
TEST_EXTRA_OBJS=../framework/test_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: $(TARGET) test |
|||
|
|||
$(TARGET): $(OBJ) $(TEST_EXTRA_OBJS) |
|||
$(AR) -rc $@ $^ |
|||
|
|||
|
|||
test : $(TEST_OBJ) |
|||
|
|||
$(TEST_OBJ): $(OBJ) $(TEST_EXTRA_OBJS) |
|||
|
|||
|
|||
clean: |
|||
rm -f $(TARGET) |
|||
rm -f $(OBJ) |
|||
rm -f $(TEST_OBJ) |
|||
rm -rf src/*.dSYM |
|||
rm -rf test/*.dSYM |
|||
|
@ -1,456 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#include "AbstractPityUnit.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include <iostream> |
|||
#include <unistd.h> |
|||
#include <cstdlib> |
|||
#include <sys/stat.h> |
|||
#include <exception> |
|||
#include <memory> |
|||
#include <sys/wait.h> |
|||
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
// static
|
|||
std::string AbstractPityUnit::_global_root_dir = "./pitytest_data/"; |
|||
// static
|
|||
bool AbstractPityUnit::debug_log_enabled = false; |
|||
// static
|
|||
int AbstractPityUnit::_procUnitsCount = 0; |
|||
|
|||
AbstractPityUnit::AbstractPityUnit(const std::string &name, ExecutionMode exec_mode) : |
|||
PityTree<AbstractPityUnit>(*this, name), _exec_mode{ exec_mode }, _procUnitNr{ 0 } |
|||
{ |
|||
_init(); |
|||
} |
|||
|
|||
AbstractPityUnit::AbstractPityUnit( |
|||
AbstractPityUnit &parent, |
|||
const std::string &name, |
|||
ExecutionMode exec_mode) : |
|||
PityTree<AbstractPityUnit>(*this, name, parent), |
|||
_exec_mode{ exec_mode }, _procUnitNr{ 0 } |
|||
{ |
|||
_init(); |
|||
} |
|||
|
|||
AbstractPityUnit::AbstractPityUnit(const AbstractPityUnit &rhs, AbstractPityUnit &self) : |
|||
PityTree<AbstractPityUnit>(rhs, self) |
|||
{ |
|||
_procUnitNr = rhs._procUnitNr; |
|||
_exec_mode = rhs._exec_mode; |
|||
_transport = rhs._transport; // Will re-initialized in run()
|
|||
_transport_endpoints = rhs._transport_endpoints; // Will re-initialized in run()
|
|||
_init(); |
|||
} |
|||
|
|||
AbstractPityUnit &AbstractPityUnit::operator=(const AbstractPityUnit &rhs) |
|||
{ |
|||
_procUnitNr = rhs._procUnitNr; |
|||
_exec_mode = rhs._exec_mode; |
|||
_transport = rhs._transport; |
|||
_transport_endpoints = rhs._transport_endpoints; |
|||
return *this; |
|||
} |
|||
|
|||
|
|||
void AbstractPityUnit::_init() |
|||
{ |
|||
_log_mutex = std::make_shared<fs_mutex>("log.mutex"); |
|||
_log_mutex->release(); |
|||
} |
|||
|
|||
// 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::setExecMode(AbstractPityUnit::ExecutionMode execMode) |
|||
{ |
|||
_exec_mode = execMode; |
|||
} |
|||
|
|||
// For:
|
|||
// RootUnit - "<name>"
|
|||
// ProcessUnit - ".../<proc>"
|
|||
// When Process as dir. parent - ".../<proc>/name"
|
|||
// When no process as dir. parent - ".../<proc>/.../name"
|
|||
std::string AbstractPityUnit::getPathShort() const |
|||
{ |
|||
std::string ret; |
|||
if (isRoot()) { |
|||
ret = getName(); |
|||
} else { |
|||
if (isProcessUnit()) { |
|||
ret += ".../" + getName(); |
|||
} else { |
|||
if (&(getParentProcessUnit()) == (getParent())) { |
|||
ret = getParentProcessUnit().getPathShort() + "/" + getName(); |
|||
} else { |
|||
ret = getParentProcessUnit().getPathShort() + "/.../" + getName(); |
|||
} |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
// Every process has its own dir inside its rootUnitDir
|
|||
// All other units inherit processDir from their Root/ProcessUnit
|
|||
std::string AbstractPityUnit::getProcessDir() |
|||
{ |
|||
if (isRoot()) { |
|||
return getRootUnitDir(); |
|||
} else { |
|||
if (isProcessUnit()) { |
|||
return getGlobalRootDir() + _normalizeName(getPath()) + "/"; |
|||
} else { |
|||
return getParent()->getProcessDir(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Every RootUnit has its own dir
|
|||
std::string AbstractPityUnit::getRootUnitDir() |
|||
{ |
|||
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::getTransportDir() |
|||
{ |
|||
return getProcessDir() + "inbox/"; |
|||
} |
|||
|
|||
void AbstractPityUnit::_initProcUnitNrRecurse() |
|||
{ |
|||
if (!isRoot()) { |
|||
// Inherit
|
|||
_procUnitNr = getParent()->_procUnitNr; |
|||
//Or update if procUnit
|
|||
if (isProcessUnit()) { |
|||
_procUnitsCount++; |
|||
_procUnitNr = _procUnitsCount; |
|||
} |
|||
} else { |
|||
_procUnitNr = _procUnitsCount; |
|||
} |
|||
|
|||
// Recurse
|
|||
for (const auto &chld : getChildRefs()) { |
|||
chld.second._initProcUnitNrRecurse(); |
|||
} |
|||
} |
|||
|
|||
void AbstractPityUnit::_initTransportRecurse() |
|||
{ |
|||
|
|||
if (!isRoot()) { |
|||
if (isProcessUnit()) { |
|||
_createTransport(); |
|||
} |
|||
} |
|||
|
|||
// Recurse
|
|||
for (const auto &chld : getChildRefs()) { |
|||
chld.second._initTransportRecurse(); |
|||
} |
|||
} |
|||
|
|||
void AbstractPityUnit::_initDirsRecursive() |
|||
{ |
|||
Utils::dir_recreate(getProcessDir()); |
|||
|
|||
// Recurse
|
|||
for (const auto &child : getChildRefs()) { |
|||
child.second._initDirsRecursive(); |
|||
} |
|||
} |
|||
|
|||
|
|||
void AbstractPityUnit::run(bool init_tree) |
|||
{ |
|||
pEpLogClass("called"); |
|||
|
|||
if (init_tree) { |
|||
logH1("PityTest Starting..."); |
|||
_logRaw("RootUnit: " + getPath()); |
|||
_logRaw("GlobalRootDir: " + getGlobalRootDir()); |
|||
|
|||
_logRaw("Ensuring GlobalRootDir..."); |
|||
Utils::dir_ensure(getGlobalRootDir()); |
|||
|
|||
_logRaw("Recreating process dirs recursively..."); |
|||
_initDirsRecursive(); |
|||
//TODO:HACK wait for dir
|
|||
Utils::sleep_millis(500); |
|||
|
|||
_logRaw("Initializing Transport recursively..."); |
|||
_initTransportRecurse(); |
|||
|
|||
_logRaw("\n\nTestTree"); |
|||
_logRaw("--------"); |
|||
_logRaw(to_string() + "\n"); |
|||
_procUnitsCount = 0; |
|||
_initProcUnitNrRecurse(); |
|||
} |
|||
|
|||
|
|||
// TODO: hack
|
|||
setenv("HOME", getProcessDir().c_str(), true); |
|||
|
|||
// Execute in fork and wait here until process ends
|
|||
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL) { // fork
|
|||
_executeInFork(std::bind(&AbstractPityUnit::_runRecurse, this), true); |
|||
// Execute in fork and go on, wait for process execution in the end
|
|||
} else if (_exec_mode == ExecutionMode::PROCESS_PARALLEL) { |
|||
_executeInFork(std::bind(&AbstractPityUnit::_runRecurse, this), false); |
|||
// Execute as normal function
|
|||
} else if (_exec_mode == ExecutionMode::FUNCTION) { |
|||
_runRecurse(); |
|||
} 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 (init_tree) { |
|||
_waitChildProcesses(); |
|||
} |
|||
} |
|||
|
|||
std::string AbstractPityUnit::to_string(bool recursive, int indent) |
|||
{ |
|||
std::string ret; |
|||
std::stringstream builder; |
|||
builder << std::string(indent * 4, ' '); |
|||
|
|||
builder << getName(); |
|||
builder << " [ "; |
|||
builder << to_string(_exec_mode) << " - "; |
|||
builder << "\"" << getProcessDir() << "\""; |
|||
builder << " ]"; |
|||
builder << std::endl; |
|||
ret = builder.str(); |
|||
|
|||
if (recursive) { |
|||
if (!getChildRefs().empty()) { |
|||
indent++; |
|||
for (const auto child : getChildRefs()) { |
|||
ret += child.second.to_string(true, indent); |
|||
} |
|||
indent--; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
std::string AbstractPityUnit::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"; |
|||
} |
|||
} |
|||
|
|||
|
|||
void AbstractPityUnit::registerAsTransportEndpoint() |
|||
{ |
|||
transportEndpoints().insert({ getName(), getTransportDir() }); |
|||
} |
|||
|
|||
Endpoints &AbstractPityUnit::transportEndpoints() |
|||
{ |
|||
if (isRoot()) { |
|||
return _transport_endpoints; |
|||
} else { |
|||
return getRoot().transportEndpoints(); |
|||
} |
|||
} |
|||
|
|||
void AbstractPityUnit::log(const std::string &msg) const |
|||
{ |
|||
std::stringstream builder; |
|||
builder << "[ "; |
|||
builder << std::to_string(getpid()); |
|||
builder << " - "; |
|||
builder << getPathShort(); |
|||
builder << " ] - "; |
|||
builder << msg; |
|||
|
|||
_logRaw(builder.str()); |
|||
} |
|||
|
|||
void AbstractPityUnit::logH1(const std::string &msg) const |
|||
{ |
|||
Adapter::pEpLog::logH1(msg, _color()); |
|||
} |
|||
|
|||
void AbstractPityUnit::logH2(const std::string &msg) const |
|||
{ |
|||
Adapter::pEpLog::logH2(msg, _color()); |
|||
} |
|||
|
|||
void AbstractPityUnit::logH3(const std::string &msg) const |
|||
{ |
|||
Adapter::pEpLog::logH3(msg, _color()); |
|||
} |
|||
|
|||
// PRIVATE ---------------------------------------------------------------------------------
|
|||
void AbstractPityUnit::_runRecurse() |
|||
{ |
|||
logH2(_status_string("STARTING")); |
|||
_runSelf(); |
|||
if (!getChildRefs().empty()) { |
|||
for (const auto child : getChildRefs()) { |
|||
child.second.run(false); |
|||
} |
|||
} |
|||
|
|||
// This should be fine
|
|||
_waitChildProcesses(); |
|||
} |
|||
|
|||
void AbstractPityUnit::_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(); |
|||
} |
|||
} |
|||
|
|||
void AbstractPityUnit::_waitChildProcesses() const |
|||
{ |
|||
int status; |
|||
pid_t pid; |
|||
while ((pid = wait(&status)) > 0) { |
|||
std::string color; |
|||
if (status == 0) { |
|||
color = "\033[1m\033[32m"; // Green
|
|||
} else { |
|||
color = "\033[1m\033[31m"; // Red
|
|||
} |
|||
logH3( |
|||
color + "PROCESS [ " + std::to_string((int)pid) + |
|||
" ] EXITED with status code: " + std::to_string(status) + |
|||
Utils::to_termcol(_color())); |
|||
} |
|||
} |
|||
|
|||
bool AbstractPityUnit::isProcessUnit() const |
|||
{ |
|||
bool ret = false; |
|||
if (_exec_mode == ExecutionMode::PROCESS_SEQUENTIAL || |
|||
_exec_mode == ExecutionMode::PROCESS_PARALLEL) { |
|||
ret = true; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
const AbstractPityUnit &AbstractPityUnit::getParentProcessUnit() const |
|||
{ |
|||
if (isRoot() || isProcessUnit()) { |
|||
return *this; |
|||
} else { |
|||
return getParent()->getParentProcessUnit(); |
|||
} |
|||
} |
|||
|
|||
|
|||
// Inherited (if null see parent recursively)
|
|||
void AbstractPityUnit::_createTransport() |
|||
{ |
|||
registerAsTransportEndpoint(); |
|||
_transport = std::make_shared<PityTransport>(getTransportDir(), transportEndpoints()); |
|||
} |
|||
|
|||
// Inherited (if null see parent recursively)
|
|||
PityTransport *AbstractPityUnit::transport() const |
|||
{ |
|||
// pEpLogClass("called");
|
|||
PityTransport *ret = nullptr; |
|||
|
|||
if (_transport != nullptr) { |
|||
ret = _transport.get(); |
|||
} else { |
|||
if (!isRoot()) { |
|||
ret = getParent()->transport(); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
std::string AbstractPityUnit::_status_string(const std::string &msg) const |
|||
{ |
|||
std::string ret; |
|||
ret = "[ " + to_string(_exec_mode) + ": " + std::to_string(getpid()) + " ] [ " + |
|||
getPathShort() + " ] [ " + msg + " ]"; |
|||
return ret; |
|||
} |
|||
|
|||
//static
|
|||
Utils::Color AbstractPityUnit::_colForProcUnitNr(int procUnitNr) |
|||
{ |
|||
int nrColors = 6; |
|||
switch (procUnitNr % nrColors) { |
|||
case 0: |
|||
return Utils::Color::WHITE; |
|||
case 1: |
|||
return Utils::Color::GREEN; |
|||
case 2: |
|||
return Utils::Color::YELLOW; |
|||
case 3: |
|||
return Utils::Color::CYAN; |
|||
case 4: |
|||
return Utils::Color::BLUE; |
|||
case 5: |
|||
return Utils::Color::MAGENTA; |
|||
default: |
|||
return Utils::Color::WHITE; |
|||
} |
|||
} |
|||
|
|||
Utils::Color AbstractPityUnit::_color() const |
|||
{ |
|||
return _colForProcUnitNr(_procUnitNr); |
|||
} |
|||
|
|||
void AbstractPityUnit::_logRaw(const std::string &msg) const |
|||
{ |
|||
// fs-mutex to sync across processes
|
|||
_log_mutex->aquire(); |
|||
Adapter::pEpLog::log(msg, _color()); |
|||
_log_mutex->release(); |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,135 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_ABSTRACTPITYUNIT_HH |
|||
#define PITYTEST_ABSTRACTPITYUNIT_HH |
|||
|
|||
#include "../../../src/pEpLog.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include "fs_mutex.hh" |
|||
#include "PityTree.hh" |
|||
#include "PityTransport.hh" |
|||
#include <string> |
|||
#include <memory> |
|||
#include <functional> |
|||
|
|||
// Yes, the mem mgmt is purely static on purpose (so far)
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
class AbstractPityUnit : public PityTree<AbstractPityUnit> { |
|||
public: |
|||
enum class ExecutionMode |
|||
{ |
|||
FUNCTION, |
|||
PROCESS_SEQUENTIAL, |
|||
PROCESS_PARALLEL, |
|||
THREAD_SEQUENTIAL, // unimplemented
|
|||
THREAD_PARALLEL, // unimplemented
|
|||
INHERIT |
|||
}; |
|||
|
|||
// Constructors
|
|||
// ------------
|
|||
// RootNode
|
|||
explicit AbstractPityUnit( |
|||
const std::string& name, |
|||
ExecutionMode exec_mode = ExecutionMode::FUNCTION); |
|||
|
|||
// LeafNode
|
|||
explicit AbstractPityUnit( |
|||
AbstractPityUnit& parent, |
|||
const std::string& name, |
|||
ExecutionMode exec_mode = ExecutionMode::FUNCTION); |
|||
|
|||
// Copy
|
|||
explicit AbstractPityUnit(const AbstractPityUnit& rhs, AbstractPityUnit& self); |
|||
|
|||
// copy-assign
|
|||
AbstractPityUnit& operator=(const AbstractPityUnit& rhs); |
|||
|
|||
AbstractPityUnit* clone() override = 0; |
|||
|
|||
// Read-Write
|
|||
static void setGlobalRootDir(const std::string& dir); |
|||
static std::string getGlobalRootDir(); |
|||
void setExecMode(ExecutionMode execMode); |
|||
|
|||
// Read-Only
|
|||
std::string getPathShort() const; |
|||
std::string getProcessDir(); // own process dir
|
|||
std::string getTransportDir(); |
|||
std::string getRootUnitDir(); |
|||
bool isProcessUnit() const; // true if it forks
|
|||
const AbstractPityUnit& getParentProcessUnit() const; |
|||
|
|||
|
|||
// Main funcs
|
|||
void run(bool init_tree = true); |
|||
|
|||
std::string to_string(bool recursive = true, int indent = 0); |
|||
static std::string to_string(const ExecutionMode& emode); |
|||
|
|||
// logging service
|
|||
void log(const std::string& msg) const; |
|||
void logH1(const std::string& msg) const; |
|||
void logH2(const std::string& msg) const; |
|||
void logH3(const std::string& msg) const; |
|||
|
|||
//Transport
|
|||
PityTransport* transport() const; |
|||
void registerAsTransportEndpoint(); |
|||
Endpoints& transportEndpoints(); |
|||
|
|||
// internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PityUnit", debug_log_enabled }; |
|||
|
|||
protected: |
|||
std::string _status_string(const std::string& msg) const; |
|||
static Utils::Color _colForProcUnitNr(int procUnitNr); |
|||
Utils::Color _color() const; |
|||
void _logRaw(const std::string& msg) const; |
|||
|
|||
// internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
|
|||
private: |
|||
// METHODS
|
|||
void _init(); |
|||
// Execution
|
|||
void _initProcUnitNrRecurse(); |
|||
void _initTransportRecurse(); |
|||
void _initDirsRecursive(); |
|||
void _runRecurse(); |
|||
virtual void _runSelf() = 0; |
|||
void _executeInFork(std::function<void(void)> func, bool wait_child) const; |
|||
void _waitChildProcesses() const; |
|||
|
|||
// Transport
|
|||
void _createTransport(); |
|||
|
|||
// Fields
|
|||
// ------
|
|||
static std::string _global_root_dir; |
|||
ExecutionMode _exec_mode; |
|||
int _procUnitNr; |
|||
static int _procUnitsCount; // will be increased in every constructor
|
|||
|
|||
// transport
|
|||
std::shared_ptr<PityTransport> _transport; //only ever read via transport()
|
|||
// TODO move endpoints into PityTransport
|
|||
Endpoints _transport_endpoints; // only ever access via transportEndpoints()
|
|||
|
|||
// fs-mutex to sync across processes
|
|||
std::shared_ptr<fs_mutex> _log_mutex = nullptr; |
|||
}; |
|||
|
|||
class PityAssertException : public std::runtime_error { |
|||
public: |
|||
PityAssertException(const std::string& string) : runtime_error(string) {} |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#endif |
@ -1,32 +0,0 @@ |
|||
#include "PityModel.hh" |
|||
#include "PityNode.hh" |
|||
#include <random> |
|||
#include <memory> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
bool PityModel::debug_log_enabled = false; |
|||
|
|||
PityModel::PityModel(const std::string& name, int nodeCount) : _name{ name } |
|||
{ |
|||
for (int i = 0; i < nodeCount; i++) { |
|||
_nodes.emplace_back(std::make_shared<PityNode>(i)); |
|||
} |
|||
} |
|||
|
|||
std::string PityModel::getName() const |
|||
{ |
|||
return _name; |
|||
} |
|||
|
|||
std::vector<std::shared_ptr<PityNode>> PityModel::nodes() const |
|||
{ |
|||
return _nodes; |
|||
} |
|||
|
|||
PityNode* PityModel::nodeNr(int nr) const |
|||
{ |
|||
return nodes().at(nr).get(); |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,53 +0,0 @@ |
|||
// 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" |
|||
#include "PityNode.hh" |
|||
#include <vector> |
|||
#include <memory> |
|||
|
|||
// The Model currently is as follows:
|
|||
// The Model creates the TestTree using PityUnits.
|
|||
// When creating the model you specify how many nodes you want
|
|||
//
|
|||
// ATTENTION - TODO:
|
|||
// Currently there is a strict 1-1 relationship of nodes and identities.
|
|||
// One Node has exactly one identity, and this identity is only on this node.
|
|||
// This needs to be enhanced to be a n-n relationship
|
|||
// The Transport only addresses nodes, not idents, therefore
|
|||
// If you have one ident on n nodes, the transport needs to check the model for all nodes the
|
|||
// ident is on and send the message to all these nodes.
|
|||
// If you have a node that has n identities, the persepective needs to specify node AND ident.
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
class PityModel { |
|||
public: |
|||
// Constructors
|
|||
PityModel() = delete; |
|||
PityModel(const std::string& name, int nodeCount); |
|||
|
|||
// Getters
|
|||
std::string getName() const; |
|||
std::vector<std::shared_ptr<PityNode>> nodes() const; |
|||
PityNode* nodeNr(int nr) const; |
|||
|
|||
//internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PityModel", debug_log_enabled }; |
|||
|
|||
private: |
|||
std::vector<std::shared_ptr<PityNode>> _nodes; |
|||
std::string _name; |
|||
|
|||
//internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
|
|||
}; // namespace pEp
|
|||
|
|||
#endif // PITYTEST_PITYMODEL_HH
|
@ -1,63 +0,0 @@ |
|||
#include "PityNode.hh" |
|||
#include <memory> |
|||
#include <sstream> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
TestIdent::TestIdent(const std::string& addr) : |
|||
addr{ addr }, did_rx_encrypted{ false }, did_tx_encrypted{ false } |
|||
{ |
|||
ident = Test::Utils::createCptIdent(addr); |
|||
} |
|||
|
|||
TestIdent::TestIdent(const TestIdent& rhs) |
|||
{ |
|||
did_rx_encrypted = rhs.did_rx_encrypted; |
|||
did_tx_encrypted = rhs.did_tx_encrypted; |
|||
addr = rhs.addr; |
|||
ident = Test::Utils::dup(rhs.ident.get()); |
|||
} |
|||
|
|||
bool TestIdent::tofu_done() const |
|||
{ |
|||
return did_tx_encrypted && did_rx_encrypted; |
|||
} |
|||
|
|||
|
|||
// ---------------------------------------------------------------------------------
|
|||
|
|||
bool PityNode::debug_log_enabled = false; |
|||
|
|||
PityNode::PityNode(int nodeNr) : _node_nr{ nodeNr } |
|||
{ |
|||
logger_debug.set_instancename(getName()); |
|||
std::stringstream ss; |
|||
ss << this; |
|||
pEpLogClass(std::string("called with: " + std::to_string(_node_nr) + "AT: " + ss.str())); |
|||
ident = std::make_shared<TestIdent>(TestIdent(getName())); |
|||
} |
|||
|
|||
TestIdent& PityNode::getIdent() { |
|||
return *ident.get(); |
|||
} |
|||
|
|||
int PityNode::getNr() const |
|||
{ |
|||
return _node_nr; |
|||
} |
|||
|
|||
std::string PityNode::getName() const |
|||
{ |
|||
std::string ret; |
|||
ret += "node_" + std::to_string(_node_nr) + "@peptest.org"; |
|||
return ret; |
|||
} |
|||
|
|||
std::string PityNode::to_string() const |
|||
{ |
|||
std::string ret; |
|||
ret += "name: " + getName(); |
|||
return ret; |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,55 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYNODE_HH |
|||
#define PITYTEST_PITYNODE_HH |
|||
|
|||
#include "../../../src/pEpLog.hh" |
|||
#include "../../framework/test_utils.hh" |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
class TestIdent { |
|||
public: |
|||
TestIdent() = delete; |
|||
explicit TestIdent(const std::string& addr); |
|||
TestIdent(const TestIdent& rhs); |
|||
bool tofu_done() const; |
|||
|
|||
std::string addr; |
|||
pEp::Test::Utils::pEpIdent ident{}; |
|||
|
|||
// state
|
|||
bool did_tx_encrypted; |
|||
bool did_rx_encrypted; |
|||
}; |
|||
|
|||
|
|||
class PityNode { |
|||
public: |
|||
// Constructors
|
|||
PityNode() = delete; |
|||
explicit PityNode(int nodeNr); |
|||
|
|||
// Getters
|
|||
TestIdent& getIdent(); |
|||
int getNr() const; |
|||
std::string getName() const; |
|||
std::string to_string() const; |
|||
|
|||
//internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PityNode", debug_log_enabled }; |
|||
|
|||
private: |
|||
//fields
|
|||
const int _node_nr; |
|||
std::shared_ptr<TestIdent> ident; |
|||
|
|||
//internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#endif // PITYTEST_PITYNODE_HH
|
@ -1,48 +0,0 @@ |
|||
#include "PityPerspective.hh" |
|||
#include "PityModel.hh" |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
bool PityPerspective::debug_log_enabled = false; |
|||
|
|||
PityPerspective::PityPerspective(const PityModel& model) : model{ model }, peerNrAsCpt{ 0 } |
|||
{ |
|||
pEpLogClass("called"); |
|||
} |
|||
|
|||
TestIdent* PityPerspective::getPeer(const std::string& addr) |
|||
{ |
|||
for (int i = 0; i < peers.size(); i++) { |
|||
if (peers.at(i).addr == addr) { |
|||
return &peers.at(i); |
|||
} |
|||
} |
|||
throw std::invalid_argument("getPeer(+" + addr + ") - not found"); |
|||
} |
|||
|
|||
void PityPerspective::setPeerNrAsCpt(int nr) |
|||
{ |
|||
if (nr < peers.size()) { |
|||
peerNrAsCpt = nr; |
|||
} else { |
|||
throw std::invalid_argument("setPeerNrAsCpt(" + std::to_string(nr) + ") - out of range"); |
|||
} |
|||
} |
|||
|
|||
TestIdent& PityPerspective::getCpt() |
|||
{ |
|||
return peers.at(peerNrAsCpt); |
|||
} |
|||
|
|||
Group* PityPerspective::getGroup(const std::string& addr) |
|||
{ |
|||
for (int i = 0; i < groups.size(); i++) { |
|||
if (groups.at(i).addr == addr) { |
|||
return &groups.at(i); |
|||
} |
|||
} |
|||
throw std::invalid_argument("getGroup(" + addr + ") - not found"); |
|||
} |
|||
|
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,59 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYPERSPECTIVE_HH |
|||
#define PITYTEST_PITYPERSPECTIVE_HH |
|||
|
|||
#include "../../../src/pEpLog.hh" |
|||
#include "../../framework/test_utils.hh" |
|||
#include "PityModel.hh" |
|||
#include <map> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
|
|||
// Group
|
|||
struct Group { |
|||
std::string addr; |
|||
std::string moderator; |
|||
std::vector<TestIdent> members; |
|||
|
|||
}; |
|||
|
|||
class PityPerspective { |
|||
public: |
|||
// Constructors
|
|||
PityPerspective(const PityModel& model); |
|||
|
|||
// Lets grant access to the whole model too
|
|||
const PityModel& model; |
|||
|
|||
TestIdent* getPeer(const std::string& addr); |
|||
// Perspective
|
|||
std::string own_name; |
|||
// TestIdent* cpt = nullptr;
|
|||
void setPeerNrAsCpt(int nr); |
|||
TestIdent& getCpt(); |
|||
std::vector<TestIdent> peers; |
|||
|
|||
Test::Utils::pEpIdent own_ident; |
|||
// Test::Utils::pEpIdent cpt_ident;
|
|||
|
|||
// Groups
|
|||
Group* getGroup(const std::string& addr); |
|||
std::vector<Group> groups; |
|||
|
|||
//Callbacks
|
|||
//internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PityNode", debug_log_enabled }; |
|||
|
|||
private: |
|||
int peerNrAsCpt; |
|||
//internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#endif // PITYTEST_PITYPERSPECTIVE_HH
|
@ -1,146 +0,0 @@ |
|||
#include "PitySwarm.hh" |
|||
#include "PityModel.hh" |
|||
#include "PityPerspective.hh" |
|||
#include "PityUnit.hh" |
|||
|
|||
#include <iostream> |
|||
#include <vector> |
|||
#include <functional> |
|||
#include <memory> |
|||
#include <stdlib.h> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
bool PitySwarm::debug_log_enabled = false; |
|||
|
|||
PitySwarm::PitySwarm(const std::string& name, PityModel& model) : |
|||
_model{ model }, _swarmUnit{ name, |
|||
nullptr, |
|||
nullptr, |
|||
PityUnit<>::ExecutionMode::PROCESS_SEQUENTIAL } |
|||
{ |
|||
logger_debug.set_instancename(name); |
|||
pEpLogClass("called"); |
|||
|
|||
for (auto n : _model.nodes()) { |
|||
TestUnit* tmp = &_swarmUnit.addNew<TestUnit>( |
|||
n->getName(), |
|||
std::bind( |
|||
&PitySwarm::_init_process, |
|||
this, |
|||
std::placeholders::_1, |
|||
std::placeholders::_2), |
|||
nullptr, |
|||
TestUnit::ExecutionMode::PROCESS_PARALLEL); |
|||
// By value copies the context into the TestUnit
|
|||
tmp->setContext(_createPerspective(_model, n->getNr())); |
|||
_nodeUnits.insert(std::pair<int, TestUnit*>(n->getNr(), tmp)); |
|||
} |
|||
} |
|||
|
|||
PitySwarm::PitySwarm(const PitySwarm& rhs, const std::string& new_name) : |
|||
_model{ rhs._model }, _swarmUnit{ new_name } |
|||
{ |
|||
logger_debug.set_instancename(new_name); |
|||
_swarmUnit = TestUnit(rhs._swarmUnit); |
|||
// TODO: Hack for some reason ExecMode is getting copied,
|
|||
// Copy of Swarm is _b0rken
|
|||
_swarmUnit.setExecMode(PityUnit<>::ExecutionMode::PROCESS_SEQUENTIAL); |
|||
_swarmUnit.setName(new_name); |
|||
for (auto n : rhs._nodeUnits) { |
|||
TestUnit* tmp = &_swarmUnit.addCopy(TestUnit(*n.second)); |
|||
_nodeUnits.insert(std::pair<int, TestUnit*>(n.first, tmp)); |
|||
} |
|||
} |
|||
|
|||
PitySwarm::TestUnit& PitySwarm::getSwarmUnit() |
|||
{ |
|||
return _swarmUnit; |
|||
} |
|||
|
|||
PitySwarm::TestUnit& PitySwarm::getLeafUnit(int nodeNr) |
|||
{ |
|||
TestUnit* ret = nullptr; |
|||
TestUnit* current = _nodeUnits.at(nodeNr); |
|||
do { |
|||
if (current == nullptr) { |
|||
throw std::runtime_error("bad fatal cast in the ugly hack"); |
|||
} |
|||
if (current->getChildCount() == 0) { |
|||
ret = current; |
|||
} else { |
|||
current = dynamic_cast<TestUnit*>( |
|||
&(current->getChildRefs().begin()->second)); // random child
|
|||
} |
|||
} while (ret == nullptr); |
|||
return *ret; |
|||
} |
|||
|
|||
PitySwarm::TestUnit& PitySwarm::addTestUnit(int nodeNr, const TestUnit& unit) |
|||
{ |
|||
TestUnit& ret = getLeafUnit(nodeNr).addCopy(std::move(unit)); |
|||
return ret; |
|||
} |
|||
|
|||
void PitySwarm::run() |
|||
{ |
|||
_swarmUnit.run(); |
|||
} |
|||
|
|||
// The perspective currently is completely defined by specifying a node,
|
|||
// since there is a 1-1 node/ident relationship currently
|
|||
PityPerspective PitySwarm::_createPerspective(const PityModel& model, int node_nr) |
|||
{ |
|||
PityPerspective psp{ model }; |
|||
psp.own_name = model.nodeNr(node_nr)->getName(); |
|||
|
|||
// Create peers, everyone but me
|
|||
for (int i = 0; i < model.nodes().size(); i++) { |
|||
if (i != node_nr) { |
|||
psp.peers.push_back(TestIdent(model.nodes().at(i)->getIdent())); |
|||
} |
|||
} |
|||
|
|||
// Default partner is next node, its a circle
|
|||
// int partner_node_index = (node_nr + 1) % model.nodes().size();
|
|||
// psp.cpt_name = model.nodes().at(partner_node_index)->getName();
|
|||
|
|||
//Default partner is node 0
|
|||
if(model.nodes().size() > 1) { |
|||
if (node_nr == 0) { |
|||
psp.setPeerNrAsCpt(0); |
|||
} else { |
|||
for (int i = 0; i < psp.peers.size(); i++) { |
|||
if (psp.peers.at(i).addr == model.nodeNr(0)->getIdent().addr) { |
|||
psp.setPeerNrAsCpt(i); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Groups
|
|||
int grpOwneNode = 0; |
|||
Group grp1 = Group{}; |
|||
grp1.addr = "grp_" + model.nodeNr(grpOwneNode)->getName(); |
|||
grp1.moderator = model.nodeNr(grpOwneNode)->getName(); |
|||
// Create peers, everyone but me
|
|||
for (int i = 0; i < model.nodes().size(); i++) { |
|||
if (i != grpOwneNode) { |
|||
grp1.members.push_back(TestIdent(model.nodes().at(i)->getIdent())); |
|||
} |
|||
} |
|||
psp.groups.push_back(grp1); |
|||
|
|||
return psp; |
|||
} |
|||
|
|||
int PitySwarm::_init_process(TestUnit& unit, PityPerspective* ctx) |
|||
{ |
|||
// This should not be needed
|
|||
// std::cout << "Node _initProcUnitNrRecurse, setting $HOME" << std::endl;
|
|||
// std::string home = unit.processDir();
|
|||
// setenv("HOME", home.c_str(), true);
|
|||
return 0; |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,59 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYSWARM_HH |
|||
#define PITYTEST_PITYSWARM_HH |
|||
|
|||
#include "PityModel.hh" |
|||
#include "PityUnit.hh" |
|||
#include "PityPerspective.hh" |
|||
#include "../../../src/pEpLog.hh" |
|||
#include <vector> |
|||
#include <memory> |
|||
#include <functional> |
|||
|
|||
// PitySwarm creates a swarm of independent process nodes.
|
|||
// Each node has its own perspective
|
|||
// The perspective is a derivative of the model
|
|||
// The model is the objective reality
|
|||
// The perspective is the subjective reality
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
class PitySwarm { |
|||
public: |
|||
using TestUnit = PityUnit<PityPerspective>; |
|||
// Constructors
|
|||
explicit PitySwarm(const std::string& name, PityModel& model); |
|||
|
|||
PitySwarm(const PitySwarm& rhs, const std::string& new_name); |
|||
|
|||
TestUnit& addTestUnit(int nodeNr, const TestUnit& unit); |
|||
|
|||
TestUnit& getSwarmUnit(); |
|||
PitySwarm::TestUnit& getLeafUnit(int nodeNr); |
|||
void run(); |
|||
|
|||
|
|||
|
|||
//internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PitySwarm", debug_log_enabled }; |
|||
|
|||
private: |
|||
// methods
|
|||
PityPerspective _createPerspective(const PityModel& model, int node_nr); |
|||
int _init_process(TestUnit& unit, PityPerspective* ctx); |
|||
|
|||
// fields
|
|||
PityModel& _model; |
|||
TestUnit _swarmUnit; |
|||
// each node has
|
|||
std::map<int, TestUnit*> _nodeUnits; |
|||
//internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#endif // PITYTEST_PITYSWARM_HH
|
@ -1,32 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYTEST_HH |
|||
#define PITYTEST_PITYTEST_HH |
|||
|
|||
#include "PityUnit.hh" |
|||
#include "PityModel.hh" |
|||
#include "PitySwarm.hh" |
|||
#include "PityPerspective.hh" |
|||
|
|||
#ifndef PITYASSERT |
|||
#define PITYASSERT(condition, msg) \ |
|||
do { \ |
|||
if (!(condition)) { \ |
|||
throw PityAssertException(msg); \ |
|||
} \ |
|||
} while (0); |
|||
#endif |
|||
|
|||
#define PITYASSERT_THROWS(func, msg) \ |
|||
do { \ |
|||
try { \ |
|||
(func); \ |
|||
PITYASSERT(false, msg); \ |
|||
} catch (const PityAssertException& pae) { \ |
|||
throw(pae); \ |
|||
} catch (const std::exception& e) { \ |
|||
} catch (...) { \ |
|||
} \ |
|||
} while (0); |
|||
#endif |
@ -1,97 +0,0 @@ |
|||
#include "PityTransport.hh" |
|||
#include "PityUnit.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include "iostream" |
|||
#include <random> |
|||
#include <fstream> |
|||
#include <memory> |
|||
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
bool PityTransport::debug_log_enabled = false; |
|||
|
|||
PityTransport::PityTransport(std::string inboxDir, Endpoints& endpoints) : |
|||
_inboxDir{ inboxDir }, _endpoints{ endpoints } |
|||
{ |
|||
} |
|||
|
|||
void PityTransport::sendMsg(const std::string nodename, const std::string& msg) const |
|||
{ |
|||
pEpLogClass("Address: " + nodename + " msg: " + msg); |
|||
|
|||
// HACK TODO
|
|||
std::string nodename_normalized = AbstractPityUnit::_normalizeName(nodename); |
|||
|
|||
bool found = false; |
|||
std::string dir; |
|||
try { |
|||
dir = _endpoints.at(nodename_normalized); |
|||
} catch (std::out_of_range&) { |
|||
throw std::runtime_error("no such nodename: " + nodename_normalized); |
|||
} |
|||
Utils::dir_ensure(dir); |
|||
std::stringstream filename; |
|||
// collision detect
|
|||
do { |
|||
filename << dir << Utils::random_string(97, 122, 16) << ".pitymsg"; |
|||
} while (Utils::path_exists(filename.str())); |
|||
// create
|
|||
std::ofstream msgfile = Utils::file_create(filename.str()); |
|||
// write
|
|||
msgfile << msg; |
|||
} |
|||
|
|||
bool PityTransport::hasMsg() const |
|||
{ |
|||
bool ret = false; |
|||
pEpLogClass("called"); |
|||
Utils::dir_ensure(_inboxDir); |
|||
auto msg_filenames = Utils::dir_list_files(_inboxDir); |
|||
ret = msg_filenames.size() > 0; |
|||
return ret; |
|||
} |
|||
|
|||
// Non-blocking
|
|||
// throws underflow_error if inbox empty
|
|||
std::string PityTransport::pollMsg() const |
|||
{ |
|||
pEpLogClass("called"); |
|||
std::string ret; |
|||
Utils::dir_ensure(_inboxDir); |
|||
auto msg_filenames = Utils::dir_list_files(_inboxDir); |
|||
if (!msg_filenames.empty()) { |
|||
std::string msg_filename = msg_filenames.at(0); |
|||
std::string msg_path = _inboxDir + "/" + msg_filename; |
|||
pEpLogClass("Reading file: " + msg_filename); |
|||
ret = Utils::file_read(msg_path); |
|||
Utils::path_delete(msg_path); |
|||
} else { |
|||
throw std::underflow_error("inbox empty: " + _inboxDir); |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
// Blocking
|
|||
// Returns when a msg has been received
|
|||
std::string PityTransport::receiveMsg(int poll_interval) const |
|||
{ |
|||
pEpLogClass("called"); |
|||
std::string ret; |
|||
bool retry = false; |
|||
do { |
|||
try { |
|||
ret = pollMsg(); |
|||
retry = false; |
|||
} catch (const std::underflow_error&) { |
|||
pEpLogClass("polling again in [ms]: " + std::to_string(poll_interval) + "..."); |
|||
Utils::sleep_millis(poll_interval); |
|||
retry = true; |
|||
} |
|||
} while (retry); |
|||
return ret; |
|||
} |
|||
|
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
@ -1,45 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYTRANSPORT_HH |
|||
#define PITYTEST_PITYTRANSPORT_HH |
|||
|
|||
#include "../../../src/pEpLog.hh" |
|||
#include <vector> |
|||
#include <memory> |
|||
#include <unordered_map> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
// Address - Dir
|
|||
using Endpoints = std::unordered_map<std::string, std::string>; |
|||
|
|||
class PityTransport { |
|||
public: |
|||
// Constructors
|
|||
PityTransport() = delete; |
|||
explicit PityTransport(std::string inboxDir, Endpoints& endpoints); |
|||
|
|||
// Getters
|
|||
//Transport
|
|||
bool hasMsg() const; |
|||
void sendMsg(const std::string nodename, const std::string& msg) const; |
|||
std::string pollMsg() const; |
|||
std::string receiveMsg(int poll_interval = 100) const; |
|||
|
|||
//internal logging
|
|||
static bool debug_log_enabled; |
|||
Adapter::pEpLog::pEpLogger logger_debug{ "PityTransport", debug_log_enabled }; |
|||
|
|||
private: |
|||
std::string _inboxDir; |
|||
Endpoints& _endpoints; |
|||
|
|||
//internal logging
|
|||
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
|
|||
}; // namespace pEp
|
|||
|
|||
#endif // PITYTEST_PITYTRANSPORT_HH
|
@ -1,89 +0,0 @@ |
|||
// 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 <functional> |
|||
#include <type_traits> |
|||
#include <vector> |
|||
|
|||
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 ChildObj = std::shared_ptr<T>; |
|||
using ChildObjs = std::vector<ChildObj>; |
|||
using ChildRef = std::pair<const std::string, T&>; |
|||
using ChildRefs = std::map<const std::string, T&>; |
|||
|
|||
// Constructors
|
|||
explicit PityTree(T& self, const std::string& name); |
|||
explicit PityTree(T& self, const std::string& name, T& parent); |
|||
explicit PityTree(const PityTree& rhs, T& owner); |
|||
|
|||
// copy-assign
|
|||
// PityTree& operator=(const PityTree<T>& rhs);
|
|||
|
|||
// clone
|
|||
virtual PityTree* clone() = 0; |
|||
|
|||
// Append
|
|||
// creates a new instance of CT, add the new instance as child and returns a ref to it
|
|||
template<typename CT, typename... Args> |
|||
CT& addNew(Args&&... args); |
|||
|
|||
// Creates a copy, adds the copy as child and returns a ref to it
|
|||
template<typename CT> |
|||
CT& addCopy(const CT&& child, const std::string& new_name = ""); |
|||
|
|||
template<typename CT> |
|||
CT& addCopy(const CT& child, const std::string& new_name = ""); |
|||
|
|||
// Just adds child as a non-owned reference.
|
|||
T& addRef(T& child); |
|||
|
|||
// Query
|
|||
virtual T& getSelf() = 0; |
|||
T* getParent() const; |
|||
ChildRefs getChildRefs() const; |
|||
int getChildCount() const; |
|||
T& getChild(const std::string& name); |
|||
T& getRoot(); |
|||
|
|||
void setName(const std::string& name); |
|||
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: |
|||
void _copyChildRefs(const PityTree<T>& rhs); |
|||
// Fields
|
|||
std::string _nodename; |
|||
T& _self; |
|||
T* _parent; //nullptr if RootUnit
|
|||
ChildRefs _childrefs; // map to guarantee uniqueness of sibling-names
|
|||
ChildObjs _childobjs; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#include "PityTree.hxx" |
|||
#endif |
@ -1,221 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYTREE_HXX |
|||
#define PITYTEST_PITYTREE_HXX |
|||
|
|||
#include "PityTree.hh" |
|||
#include <memory> |
|||
#include <sstream> |
|||
#include <algorithm> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
|
|||
// RootNode
|
|||
template<class T> |
|||
PityTree<T>::PityTree(T& self, const std::string& name) : |
|||
_self{ self }, _parent{ nullptr }, _nodename{ _normalizeName(name) }, _childrefs{}, |
|||
_childobjs{} |
|||
{ |
|||
} |
|||
|
|||
// LeafNode
|
|||
template<class T> |
|||
PityTree<T>::PityTree(T& self, const std::string& name, T& parent) : |
|||
_self(self), _parent{ nullptr }, _nodename{ _normalizeName(name) }, _childrefs{}, |
|||
_childobjs{} |
|||
{ |
|||
parent.addRef(_self); |
|||
} |
|||
|
|||
// Copy
|
|||
template<class T> |
|||
PityTree<T>::PityTree(const PityTree<T>& rhs, T& owner) : _self{ owner } |
|||
{ |
|||
_nodename = rhs._nodename; |
|||
_parent = nullptr; |
|||
_copyChildRefs(rhs); |
|||
} |
|||
|
|||
// template<class T>
|
|||
// PityTree<T>& PityTree<T>::operator=(const PityTree<T>& rhs)
|
|||
// {
|
|||
// _nodename = rhs._nodename;
|
|||
// _parent = nullptr;
|
|||
// _copyChildRefs(rhs);
|
|||
// return *this;
|
|||
// }
|
|||
//
|
|||
template<typename T> |
|||
template<typename CT, typename... Args> |
|||
CT& PityTree<T>::addNew(Args&&... args) |
|||
{ |
|||
static_assert(std::is_base_of<T, CT>::value, "T must be base of CT"); |
|||
std::shared_ptr<CT> tmp = std::make_shared<CT>(std::forward<Args>(args)...); |
|||
_childobjs.push_back(tmp); |
|||
addRef(*tmp.get()); |
|||
return *tmp.get(); |
|||
} |
|||
|
|||
template<typename T> |
|||
template<typename CT> |
|||
CT& PityTree<T>::addCopy(const CT&& child, const std::string& new_name) |
|||
{ |
|||
static_assert(std::is_base_of<T, CT>::value, "PityTree<T> must be a base of T"); |
|||
CT* tmpraw = new CT(child); |
|||
_childobjs.push_back(ChildObj(tmpraw)); |
|||
if (new_name != "") { |
|||
tmpraw->setName(new_name); |
|||
} |
|||
addRef(*tmpraw); |
|||
return *tmpraw; |
|||
} |
|||
|
|||
template<typename T> |
|||
template<typename CT> |
|||
CT& PityTree<T>::addCopy(const CT& child, const std::string& new_name) |
|||
{ |
|||
return addCopy(std::move(child)); |
|||
} |
|||
|
|||
template<class T> |
|||
T& PityTree<T>::addRef(T& child) |
|||
{ |
|||
child.setParent(&_self); |
|||
_childrefs.insert(ChildRef(child.getName(), child)); |
|||
return child; |
|||
} |
|||
|
|||
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> |
|||
void PityTree<T>::setName(const std::string& name) |
|||
{ |
|||
_nodename = name; |
|||
} |
|||
|
|||
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 (!getChildRefs().empty()) { |
|||
indent++; |
|||
for (ChildRef child : getChildRefs()) { |
|||
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>::ChildRefs PityTree<T>::getChildRefs() const |
|||
{ |
|||
return _childrefs; |
|||
} |
|||
|
|||
template<class T> |
|||
T& PityTree<T>::getChild(const std::string& name) |
|||
{ |
|||
T* ret = nullptr; |
|||
try { |
|||
ret = &getChildRefs().at(name); |
|||
} catch (const std::exception& e) { |
|||
throw std::invalid_argument("PityNode not found: '" + name + "'"); |
|||
} |
|||
return *ret; |
|||
} |
|||
|
|||
// 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; |
|||
} |
|||
|
|||
// When you copy a treenode, you need to create a copy of all children
|
|||
// and take ownership
|
|||
template<class T> |
|||
void PityTree<T>::_copyChildRefs(const PityTree<T>& rhs) |
|||
{ |
|||
for (const ChildRef& cr : rhs.getChildRefs()) { |
|||
_childobjs.push_back(ChildObj(cr.second.clone())); |
|||
T& ret = *_childobjs.back().get(); |
|||
addRef(ret); |
|||
} |
|||
} |
|||
|
|||
template<class T> |
|||
int PityTree<T>::getChildCount() const |
|||
{ |
|||
return _childrefs.size(); |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
|||
|
|||
#endif |
@ -1,75 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef PITYTEST_PITYUNIT_HH |
|||
#define PITYTEST_PITYUNIT_HH |
|||
|
|||
#include "../../../src/pEpLog.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include "AbstractPityUnit.hh" |
|||
#include "fs_mutex.hh" |
|||
#include "PityTransport.hh" |
|||
#include <string> |
|||
#include <memory> |
|||
#include <functional> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
//TODO We need a context basetype
|
|||
class PityBaseCTX { |
|||
}; |
|||
|
|||
template<class TestContext = PityBaseCTX> |
|||
class PityUnit : public AbstractPityUnit { |
|||
public: |
|||
// Test success if TestFunction:
|
|||
// * does not throw
|
|||
// * returns 0
|
|||
using TestFunction = std::function<int(PityUnit<TestContext>&, TestContext*)>; |
|||
|
|||
// Constructors
|
|||
PityUnit() = delete; |
|||
explicit PityUnit<TestContext>( |
|||
const std::string& name, |
|||
TestFunction test_func = nullptr, |
|||
TestContext* ctx = nullptr, |
|||
ExecutionMode exec_mode = ExecutionMode::FUNCTION); |
|||
|
|||
explicit PityUnit<TestContext>( |
|||
AbstractPityUnit& parent, |
|||
const std::string& name, |
|||
TestFunction test_func = nullptr, |
|||
TestContext* ctx = nullptr, |
|||
ExecutionMode exec_mode = ExecutionMode::FUNCTION); |
|||
|
|||
PityUnit<TestContext>(const PityUnit<TestContext>& rhs); |
|||
|
|||
// copy-assign
|
|||
PityUnit<TestContext>& operator=(const PityUnit<TestContext>& rhs); |
|||
|
|||
PityUnit<TestContext>& getSelf() override; |
|||
// clone
|
|||
PityUnit<TestContext>* clone() override; |
|||
|
|||
void setContext(TestContext* ctx); |
|||
void setContext(TestContext ctx); |
|||
TestContext* getContext() const; |
|||
|
|||
protected: |
|||
void _runSelf() override; |
|||
|
|||
private: |
|||
void _copyContext(const PityUnit<TestContext>& rhs); |
|||
|
|||
// Fields
|
|||
// nullptr if inherited
|
|||
TestContext* _ctx; |
|||
std::shared_ptr<TestContext> _owned_ctx; // if you copy
|
|||
TestFunction _test_func; |
|||
}; |
|||
}; // namespace PityTest11
|
|||
}; // namespace pEp
|
|||
|
|||
#include "PityUnit.hxx" |
|||
|
|||
#endif // PITYTEST_PITYUNIT_HH
|
@ -1,136 +0,0 @@ |
|||
// 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 "PityUnit.hh" |
|||
|
|||
#include <iostream> |
|||
#include <unistd.h> |
|||
#include <cstdlib> |
|||
#include <sys/stat.h> |
|||
#include <functional> |
|||
#include <algorithm> |
|||
#include <exception> |
|||
#include <memory> |
|||
#include <sys/wait.h> |
|||
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext>::PityUnit( |
|||
const std::string &name, |
|||
TestFunction test_func, |
|||
TestContext *ctx, |
|||
ExecutionMode exec_mode) : |
|||
AbstractPityUnit(name, exec_mode), |
|||
_ctx{ ctx }, _test_func{ test_func } |
|||
{ |
|||
} |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext>::PityUnit( |
|||
AbstractPityUnit &parent, |
|||
const std::string &name, |
|||
TestFunction test_func, |
|||
TestContext *ctx, |
|||
ExecutionMode exec_mode) : |
|||
AbstractPityUnit(parent, name, exec_mode), |
|||
_ctx{ ctx }, _test_func{ test_func } |
|||
{ |
|||
} |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext>::PityUnit(const PityUnit<TestContext> &rhs) : |
|||
AbstractPityUnit(rhs, *this) |
|||
{ |
|||
_copyContext(rhs); |
|||
_test_func = TestFunction(rhs._test_func); |
|||
} |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext> &PityUnit<TestContext>::operator=(const PityUnit<TestContext> &rhs) |
|||
{ |
|||
_copyContext(rhs); |
|||
_test_func = TestFunction(rhs._test_func); |
|||
return *this; |
|||
} |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext> &PityUnit<TestContext>::getSelf() |
|||
{ |
|||
return *this; |
|||
} |
|||
|
|||
template<class TestContext> |
|||
PityUnit<TestContext> *PityUnit<TestContext>::clone() |
|||
{ |
|||
return new PityUnit<TestContext>(*this); |
|||
} |
|||
|
|||
template<class TestContext> |
|||
void PityUnit<TestContext>::_runSelf() |
|||
{ |
|||
if (_test_func != nullptr) { |
|||
try { |
|||
_test_func(*this, getContext()); |
|||
logH3(_status_string("\033[1m\033[32mSUCCESS" + Utils::to_termcol(_color()))); |
|||
} catch (const std::exception &e) { |
|||
_logRaw("reason: " + std::string(e.what())); |
|||
logH3(_status_string("\033[1m\033[31mFAILED" + Utils::to_termcol(_color()))); |
|||
} |
|||
} else { |
|||
_logRaw("No function to execute"); |
|||
} |
|||
} |
|||
|
|||
// Inherited (if null see parent recursively)
|
|||
template<class TestContext> |
|||
TestContext *PityUnit<TestContext>::getContext() const |
|||
{ |
|||
pEpLogClass("called"); |
|||
TestContext *ret = nullptr; |
|||
|
|||
if (_ctx != nullptr) { |
|||
ret = _ctx; |
|||
} else { |
|||
if (!isRoot()) { |
|||
ret = (dynamic_cast<PityUnit<TestContext> *>(getParent()))->getContext(); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
template<class TestContext> |
|||
void PityUnit<TestContext>::_copyContext(const PityUnit<TestContext> &rhs) |
|||
{ |
|||
auto *tmp = rhs.getContext(); |
|||
if (tmp != nullptr) { |
|||
_owned_ctx = std::shared_ptr<TestContext>(new TestContext(*tmp)); |
|||
_ctx = tmp; |
|||
} else { |
|||
_ctx = nullptr; |
|||
} |
|||
} |
|||
|
|||
template<class TestContext> |
|||
void PityUnit<TestContext>::setContext(TestContext *ctx) |
|||
{ |
|||
_ctx = ctx; |
|||
} |
|||
|
|||
template<class TestContext> |
|||
void PityUnit<TestContext>::setContext(TestContext ctx) |
|||
{ |
|||
_owned_ctx = std::shared_ptr<TestContext>(new TestContext(ctx)); |
|||
_ctx = _owned_ctx.get(); |
|||
} |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
|||
|
|||
|
|||
#endif // PITYTEST_PITYUNIT_HXX
|
@ -1,41 +0,0 @@ |
|||
#include "fs_mutex.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include<fstream> |
|||
|
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
fs_mutex::fs_mutex(std::string mutexpath) : mutexpath{ mutexpath } {} |
|||
|
|||
void fs_mutex::aquire() const |
|||
{ |
|||
if (mutexpath.empty()) { |
|||
throw std::runtime_error("no mutexpath set"); |
|||
} else { |
|||
std::string mutex_file = mutexpath; |
|||
while (Utils::path_exists(mutex_file)) { |
|||
Utils::sleep_millis(2); |
|||
} |
|||
std::ofstream msgfile = Utils::file_create(mutexpath); |
|||
} |
|||
} |
|||
|
|||
void fs_mutex::release() const |
|||
{ |
|||
if (mutexpath.empty()) { |
|||
throw std::runtime_error("no mutexpath set"); |
|||
} else { |
|||
|
|||
try { |
|||
Utils::path_delete(mutexpath); |
|||
// Give others a chance to pickup
|
|||
Utils::sleep_millis(4); |
|||
} catch (...) { |
|||
// pEpLogClass("Error releasing fsmutex");
|
|||
} |
|||
} |
|||
} |
|||
|
|||
} // namespace PityTest
|
|||
} // namespace pEp
|
|||
|
@ -1,25 +0,0 @@ |
|||
#ifndef FS_MUTEX |
|||
#define FS_MUTEX |
|||
|
|||
#include <iostream> |
|||
|
|||
namespace pEp { |
|||
namespace PityTest11 { |
|||
// a very primitive IPC sync method
|
|||
// also unreliable
|
|||
// but good enough for what i just needed it for
|
|||
class fs_mutex { |
|||
public: |
|||
fs_mutex() = delete; |
|||
fs_mutex(std::string mutexpath); |
|||
|
|||
void aquire() const; |
|||
void release() const; |
|||
|
|||
private: |
|||
const std::string mutexpath; |
|||
}; |
|||
} // namespace PityTest11
|
|||
} // namespace pEp
|
|||
|
|||
#endif // FS_MUTEX
|
@ -1,32 +0,0 @@ |
|||
#include "../src/PityTest.hh" |
|||
#include <iostream> |
|||
#include <exception> |
|||
|
|||
using namespace pEp::PityTest11; |
|||
void not_throwing() {} |
|||
|
|||
void throwing() |
|||
{ |
|||
throw std::runtime_error{ "Fsd" }; |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
|
|||
PITYASSERT(true, "thats wrong"); |
|||
try { |
|||
PITYASSERT(false, "thats correct"); |
|||
throw std::runtime_error("PITYASSERT(false) does not throw"); |
|||
} catch (const PityAssertException& pae) { |
|||
} |
|||
|
|||
PITYASSERT(true, "thats wrong"); |
|||
|
|||
PITYASSERT_THROWS(throwing(), "is actually throwing "); |
|||
|
|||
try { |
|||
PITYASSERT_THROWS(not_throwing(), "is actually not throwing"); |
|||
throw std::runtime_error("PITYASSERT(false) does not throw"); |
|||
} catch (const PityAssertException& pae) { |
|||
} |
|||
} |
@ -1,94 +0,0 @@ |
|||
#include "../src/PityTest.hh" |
|||
#include "../../../src/utils.hh" |
|||
#include <iostream> |
|||
|
|||
using namespace std; |
|||
using namespace pEp; |
|||
using namespace pEp::PityTest11; |
|||
|
|||
|
|||
struct CTXExecmodes { |
|||
int sleepmilis; |
|||
int rep_count; |
|||
}; |
|||
|
|||
using TestContext = CTXExecmodes; |
|||
using TestUnit = PityUnit<TestContext>; |
|||
|
|||
int do_some_work(TestUnit& pity, TestContext* ctx) |
|||
{ |
|||
int i = 0; |
|||
while (i < ctx->rep_count) { |
|||
pity.log(pity.getName() + " - " + to_string(i)); |
|||
Utils::sleep_millis(ctx->sleepmilis); |
|||
i++; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
// DEBUG Logging of PityTestUnit itself
|
|||
TestUnit::debug_log_enabled = false; |
|||
CTXExecmodes ctxe; |
|||
ctxe.sleepmilis = 100; |
|||
ctxe.rep_count = 10; |
|||
|
|||
// NEW API
|
|||
{ |
|||
// Suite
|
|||
TestUnit suite = TestUnit("Test Execution Model"); |
|||
|
|||
// Groups
|
|||
auto grp1 = suite.addNew<TestUnit>( |
|||
"grp1", |
|||
do_some_work, |
|||
&ctxe, |
|||
TestUnit::ExecutionMode::PROCESS_PARALLEL); |
|||
|
|||
auto grp2 = suite.addNew<TestUnit>( |
|||
"grp2", |
|||
do_some_work, |
|||
&ctxe, |
|||
TestUnit::ExecutionMode::PROCESS_PARALLEL); |
|||
|
|||
// Units
|
|||
grp1.addNew<TestUnit>("test1.1", do_some_work); |
|||
grp1.addNew<TestUnit>("test1.2", do_some_work); |
|||
|
|||
// Units
|
|||
grp2.addNew<TestUnit>("unit_2.1", do_some_work); |
|||
grp2.addNew<TestUnit>("unit_2.2", do_some_work); |
|||
|
|||
suite.run(); |
|||
} |
|||
// Old API
|
|||
{ |
|||
// The RootNode is the
|
|||
TestUnit root_old = TestUnit{ "Test Execution Model" }; |
|||
|
|||
// Subprocess 1
|
|||
TestUnit test1 = TestUnit{ root_old, |
|||
"node1", |
|||
do_some_work, |
|||
&ctxe, |
|||
TestUnit::ExecutionMode::PROCESS_PARALLEL }; |
|||
|
|||
TestUnit test1_1 = TestUnit{ test1, "test1.1", do_some_work }; |
|||
|
|||
TestUnit test1_2 = TestUnit{ test1, "test1.2", do_some_work }; |
|||
|
|||
// Subprocess 2
|
|||
TestUnit test2 = TestUnit{ root_old, |
|||
"node2", |
|||
do_some_work, |
|||
&ctxe, |
|||
TestUnit::ExecutionMode::PROCESS_PARALLEL }; |
|||
|
|||
TestUnit test2_1 = TestUnit{ test2, "test2.1", do_some_work }; |
|||
|
|||
TestUnit test2_2 = TestUnit{ test2, "test2.2", do_some_work }; |
|||
|
|||
root_old.run(); |
|||
} |
|||
} |
@ -1,68 +0,0 @@ |
|||
#include "../src/PityTest.hh" |
|||
#include <iostream> |
|||
#include <algorithm> |
|||
|
|||
using namespace std; |
|||
using namespace pEp; |
|||
using namespace pEp::PityTest11; |
|||
|
|||
// eeks-test
|
|||
// The test framework for geeks without the g
|
|||
|
|||
|
|||
class Car { |
|||
private: |
|||
int gear_nr = 0; |
|||
|
|||
public: |
|||
void setGear(int nr) |
|||
{ |
|||
gear_nr = nr; |
|||
} |
|||
|
|||
void drive() |
|||
{ |
|||
if (gear_nr > 0 && gear_nr <= 6) { |
|||
cout << "cruising" << endl; |
|||
} else { |
|||
throw runtime_error{ "invalid gear" }; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
class CarTestModel { |
|||
public: |
|||
CarTestModel(const string& name) : name{ name }, car{} {} |
|||
|
|||
string name{}; |
|||
Car car; |
|||
}; |
|||
|
|||
int test_setGear(PityUnit<CarTestModel>& node, CarTestModel* ctx) |
|||
{ |
|||
int gear = 1; |
|||
node.log("Setting gear to: " + to_string(gear)); |
|||
ctx->car.setGear(gear); |
|||
return 0; |
|||
} |
|||
|
|||
int test_drive(PityUnit<CarTestModel>& node, CarTestModel* ctx) |
|||
{ |
|||
ctx->car.drive(); |
|||
return 0; |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
// Linear Test
|
|||
CarTestModel model{ "CarTestModel" }; |
|||
PityUnit<CarTestModel> testnode_car{ "test car", nullptr, &model }; |
|||
PityUnit<CarTestModel> testnode_setGear{ testnode_car, "test car setGear()", test_setGear }; |
|||
PityUnit<CarTestModel> testnode_driv{ testnode_setGear, "test car drive()", &test_drive }; |
|||
|
|||
PityUnit<CarTestModel> testnode_driv_before_gear{ testnode_car, |
|||
"testnode_driv_before_gear", |
|||
&test_drive }; |
|||
|
|||
testnode_car.run(); |
|||
} |
@ -1,161 +0,0 @@ |
|||
#include "../src/PityTree.hh" |
|||
#include "../src/PityTest.hh" |
|||
#include "../../../src/std_utils.hh" |
|||
#include "../../../src/utils.hh" |
|||
#include <iostream> |
|||
#include <exception> |
|||
using namespace pEp; |
|||
using namespace pEp::PityTest11; |
|||
|
|||
// -----------------------------------------------------------------------------------------------
|
|||
|
|||
class AbstractNode : public PityTree<AbstractNode> { |
|||
public: |
|||
// Constructors
|
|||
AbstractNode() = delete; |
|||
explicit AbstractNode(const std::string &name); |
|||
explicit AbstractNode(const std::string &name, AbstractNode &parent); |
|||
AbstractNode(const AbstractNode &rhs, AbstractNode &self); |
|||
|
|||
// methods
|
|||
virtual int implMe(int magic_nr) = 0; |
|||
AbstractNode& getSelf() override = 0; |
|||
AbstractNode *clone() override = 0; |
|||
|
|||
// fields
|
|||
std::string color; |
|||
int age{}; |
|||
}; |
|||
|
|||
AbstractNode::AbstractNode(const std::string &name) : PityTree<AbstractNode>(*this, name) {} |
|||
|
|||
AbstractNode::AbstractNode(const std::string &name, AbstractNode &parent) : |
|||
PityTree<AbstractNode>(*this, name, parent) |
|||
{ |
|||
} |
|||
|
|||
AbstractNode::AbstractNode(const AbstractNode &rhs, AbstractNode &self) : |
|||
PityTree<AbstractNode>(rhs, self) |
|||
{ |
|||
color = rhs.color; |
|||
age = rhs.age; |
|||
} |
|||
|
|||
|
|||
// -----------------------------------------------------------------------------------------------
|
|||
|
|||
class ANode : public AbstractNode { |
|||
public: |
|||
explicit ANode(const std::string &name); |
|||
explicit ANode(const std::string &name, AbstractNode &parent); |
|||
ANode(const ANode &rhs); |
|||
ANode &getSelf() override; |
|||
ANode *clone() override; |
|||
int implMe(int magic_nr) override; |
|||
}; |
|||
|
|||
ANode::ANode(const std::string &name) : AbstractNode(name) {} |
|||
ANode::ANode(const std::string &name, AbstractNode &parent) : AbstractNode(name, parent) {} |
|||
ANode::ANode(const ANode &rhs) : AbstractNode(rhs, *this) {} |
|||
|
|||
int ANode::implMe(int magic_nr) |
|||
{ |
|||
return 23; |
|||
} |
|||
|
|||
ANode &ANode::getSelf() |
|||
{ |
|||
return *this; |
|||
} |
|||
|
|||
ANode *ANode::clone() |
|||
{ |
|||
return new ANode(*this); |
|||
} |
|||
|
|||
// -----------------------------------------------------------------------------------------------
|
|||
|
|||
class BNode : public AbstractNode { |
|||
public: |
|||
explicit BNode(const std::string &name); |
|||
explicit BNode(const std::string &name, AbstractNode &parent); |
|||
BNode(const BNode &rhs); |
|||
BNode &getSelf() override; |
|||
BNode *clone() override; |
|||
int implMe(int magic_nr) override; |
|||
}; |
|||
|
|||
BNode::BNode(const std::string &name) : AbstractNode(name) {} |
|||
BNode::BNode(const std::string &name, AbstractNode &parent) : AbstractNode(name, parent) {} |
|||
BNode::BNode(const BNode &rhs) : AbstractNode(rhs, *this) {} |
|||
|
|||
int BNode::implMe(int magic_nr) |
|||
{ |
|||
return 42; |
|||
} |
|||
|
|||
BNode &BNode::getSelf() |
|||
{ |
|||
return *this; |
|||
} |
|||
|
|||
BNode *BNode::clone() |
|||
{ |
|||
return new BNode(*this); |
|||
} |
|||
|
|||
// -----------------------------------------------------------------------------------------------
|
|||
|
|||
void not_throwing() |
|||
{ |
|||
throw std::runtime_error{ "Fsd" }; |
|||
} |
|||
|
|||
void throwing() |
|||
{ |
|||
throw std::runtime_error{ "Fsd" }; |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
// Create lone node
|
|||
ANode a{ "a" }; |
|||
std::cout << a.getPath() << std::endl; |
|||
PITYASSERT(a.isRoot() == true, "a"); |
|||
PITYASSERT(a.getName() == "a", "b"); |
|||
PITYASSERT(&(a.getRoot()) == &a, "c"); |
|||
PITYASSERT(a.getParent() == nullptr, "d"); |
|||
PITYASSERT(a.getChildRefs().size() == 0, "e"); |
|||
|
|||
// Create node here, and make it a child of another node
|
|||
BNode b{ "b", a }; |
|||
std::cout << b.getPath() << std::endl; |
|||
PITYASSERT(a.isRoot() == true, "f"); |
|||
PITYASSERT(&(a.getRoot()) == &a, "g"); |
|||
PITYASSERT(a.getParent() == nullptr, "1"); |
|||
PITYASSERT(a.getChildRefs().size() == 1, "2"); |
|||
|
|||
PITYASSERT(&b == &(a.getChild("b")), "3"); |
|||
PITYASSERT_THROWS(a.getChild("invalid"), "4"); |
|||
PITYASSERT(b.isRoot() == false, "5"); |
|||
PITYASSERT(&(b.getRoot()) == &a, "6"); |
|||
PITYASSERT(b.getParent() == &a, "7"); |
|||
PITYASSERT(b.getChildRefs().size() == 0, "8"); |
|||
|
|||
// Create a copy of the node in the parent node
|
|||
b.addNew<ANode>("c").addNew<ANode>("d"); |
|||
std::cout << a.to_string() << std::endl; |
|||
|
|||
b.addNew<BNode>("c1").addNew<BNode>("e"); |
|||
std::cout << a.to_string() << std::endl; |
|||
|
|||
b.getChild("c1").getChild("e").addCopy(ANode(a), "a1"); |
|||
std::cout << a.to_string() << std::endl; |
|||
|
|||
a.getChild("b").addCopy(ANode(a), a.getName() + "1"); |
|||
std::cout << a.to_string() << std::endl; |
|||
|
|||
ANode a2 = ANode(a); |
|||
a2.setName("a2"); |
|||
std::cout << a2.to_string() << std::endl; |
|||
} |
@ -1,98 +0,0 @@ |
|||
#include "../src/PityTest.hh" |
|||
#include <iostream> |
|||
#include <algorithm> |
|||
|
|||
using namespace std; |
|||
using namespace pEp::PityTest11; |
|||
|
|||
|
|||
using TestContext = void; |
|||
using TestUnit = PityUnit<>; |
|||
|
|||
//TODO: Add HOME testing
|
|||
void printHomeDir(TestUnit& myself) |
|||
{ |
|||
// TESTLOG(string(myself.getFQName() + " - PID: " + to_string(getpid())));
|
|||
// cout << "[" << to_string(getpid()) << "/" << myself.getFQName() << "] - " << endl;
|
|||
setenv("HOME", myself.getProcessDir().c_str(), 1); |
|||
myself.log("HOME=" + string(getenv("HOME"))); |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
PityUnit<>::debug_log_enabled = false; |
|||
// Suite
|
|||
TestUnit suite = TestUnit{ "test_processdirs" }; |
|||
|
|||
// 1
|
|||
suite |
|||
.addNew<TestUnit>( |
|||
"node 1", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/", "node 1"); |
|||
return 0; |
|||
}) |
|||
.addNew<TestUnit>("node 1.1", [](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/", "node 1.1"); |
|||
return 0; |
|||
}); |
|||
|
|||
// 2
|
|||
suite |
|||
.addNew<TestUnit>( |
|||
"node 2", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/", "node 2"); |
|||
return 0; |
|||
}) |
|||
.addNew<TestUnit>( |
|||
"node 2.1", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_2_1/", ""); |
|||
return 0; |
|||
}, |
|||
nullptr, |
|||
PityUnit<>::ExecutionMode::PROCESS_PARALLEL) |
|||
.addNew<TestUnit>("node 2.1.1", [](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_2_1/", ""); |
|||
return 0; |
|||
}); |
|||
|
|||
|
|||
// 3
|
|||
suite |
|||
.addNew<TestUnit>( |
|||
"node 3", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_3/", ""); |
|||
return 0; |
|||
}, |
|||
nullptr, |
|||
PityUnit<>::ExecutionMode::PROCESS_PARALLEL) |
|||
.addNew<TestUnit>( |
|||
"node 3.1", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_3/", ""); |
|||
return 0; |
|||
}) |
|||
.addNew<TestUnit>( |
|||
"node 3.1.1", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_3/", ""); |
|||
return 0; |
|||
}) |
|||
.addNew<TestUnit>( |
|||
"node 3.1.1", |
|||
[](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_3_1_1/", ""); |
|||
return 0; |
|||
}, |
|||
nullptr, |
|||
PityUnit<>::ExecutionMode::PROCESS_PARALLEL) |
|||
.addNew<TestUnit>("node 3.1.1.1", [](TestUnit& pity, TestContext* ctx) { |
|||
PITYASSERT(pity.getProcessDir() == "./pitytest_data/test_processdirs/node_3_1_1/", ""); |
|||
return 0; |
|||
}); |
|||
|
|||
suite.run(); |
|||
} |
@ -1,88 +0,0 @@ |
|||
#include "../src/PityTest.hh" |
|||
#include "../../../src/utils.hh" |
|||
using namespace pEp; |
|||
using namespace pEp::Adapter; |
|||
using namespace pEp::PityTest11; |
|||
|
|||
using TextCTX = PityModel; |
|||
using TestUnit = PityUnit<TextCTX>; |
|||
|
|||
using TextCTXSwarm = PityPerspective; |
|||
using TestUnitSwarm = PityUnit<TextCTXSwarm>; |
|||
|
|||
int test_init(PityUnit<PityPerspective>& unit, PityPerspective* ctx) |
|||
{ |
|||
unit.log("GlobalRoot:" + unit.getGlobalRootDir()); |
|||
unit.log("Path:" + unit.getPath()); |
|||
unit.log("ProcessDir:" + unit.getProcessDir()); |
|||
unit.log("TransportDir:" + unit.getTransportDir()); |
|||
|
|||
PITYASSERT( |
|||
unit.getProcessDir() == |
|||
unit.getGlobalRootDir() + |
|||
AbstractPityUnit::_normalizeName(unit.getParentProcessUnit().getPath()) + "/", |
|||
"ProcessDir"); |
|||
PITYASSERT(std::string(getenv("HOME")) == unit.getProcessDir(), "HOME"); |
|||
PITYASSERT(unit.getTransportDir() == unit.getProcessDir() + "inbox/", "TransportDir"); |
|||
return 0; |
|||
} |
|||
|
|||
int test_run(PityUnit<PityPerspective>& unit, PityPerspective* ctx) |
|||
{ |
|||
std::string msg = "Message from: " + unit.getPath(); |
|||
int throttle = 1000; |
|||
int cycles = 3; |
|||
for (int i = 0; i < cycles; i++) { |
|||
Utils::sleep_millis(throttle); |
|||
unit.log(std::to_string(ctx->peers.size())); |
|||
for (const auto& peer : ctx->peers) { |
|||
unit.log("sending to" + peer.addr); |
|||
unit.transport()->sendMsg(peer.addr, msg); |
|||
} |
|||
|
|||
while (unit.transport()->hasMsg()) { |
|||
unit.log(unit.getPath() + " - MSG RX:" + unit.transport()->receiveMsg()); |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int test_finish(PityUnit<PityPerspective>& unit, PityPerspective* ctx) |
|||
{ |
|||
unit.log(unit.getPath() + " - DONE"); |
|||
return 0; |
|||
} |
|||
|
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
int nodesCount = 3; |
|||
PityModel model{ "model_swarm", nodesCount }; |
|||
TestUnit suite{ "suite_swarm" }; |
|||
|
|||
PitySwarm swarm1{ "swarm1", model }; |
|||
for (int i = 0; i < nodesCount; i++) { |
|||
swarm1.addTestUnit(i, TestUnitSwarm("init", &test_init)); |
|||
swarm1.addTestUnit(i, TestUnitSwarm("run", &test_run)); |
|||
} |
|||
std::cout << swarm1.getSwarmUnit().to_string() << std::endl; |
|||
|
|||
// swarm2 copy of swarm1
|
|||
PitySwarm swarm2{ swarm1, "swarm2" }; |
|||
// modify
|
|||
for (int i = 0; i < nodesCount; i++) { |
|||
swarm2.addTestUnit(i, TestUnitSwarm("finish", &test_finish)); |
|||
} |
|||
// swarm2.getSwarmUnit().getChildRefs().begin()->second.setName("FDAGAFG");
|
|||
// swarm2.getSwarmUnit().getChildRefs().begin()->second.getChildRefs().begin()->second.setName("fsadAG");
|
|||
std::cout << swarm1.getSwarmUnit().to_string() << std::endl; |
|||
std::cout << swarm2.getSwarmUnit().to_string() << std::endl; |
|||
|
|||
suite.addRef(swarm1.getSwarmUnit()); |
|||
// TODO this is broken, will not be run
|
|||
suite.addRef(swarm2.getSwarmUnit()); |
|||
suite.run(); |
|||
|
|||
// swarm1.run();
|
|||
// Utils::readKey();
|
|||
// swarm2.run();
|
|||
} |
Loading…
Reference in new issue