Browse Source

PityTest11: EXTRACT TestFramework PitTest11 into own repo. Is a test-dependency now.

LIB-18
heck 4 years ago
parent
commit
a6ecab9602
  1. 14
      test/Makefile
  2. 270
      test/framework/test_utils.cc
  3. 132
      test/framework/test_utils.hh
  4. 39
      test/pitytest11/Makefile
  5. 456
      test/pitytest11/src/AbstractPityUnit.cc
  6. 135
      test/pitytest11/src/AbstractPityUnit.hh
  7. 32
      test/pitytest11/src/PityModel.cc
  8. 53
      test/pitytest11/src/PityModel.hh
  9. 63
      test/pitytest11/src/PityNode.cc
  10. 55
      test/pitytest11/src/PityNode.hh
  11. 48
      test/pitytest11/src/PityPerspective.cc
  12. 59
      test/pitytest11/src/PityPerspective.hh
  13. 146
      test/pitytest11/src/PitySwarm.cc
  14. 59
      test/pitytest11/src/PitySwarm.hh
  15. 32
      test/pitytest11/src/PityTest.hh
  16. 97
      test/pitytest11/src/PityTransport.cc
  17. 45
      test/pitytest11/src/PityTransport.hh
  18. 89
      test/pitytest11/src/PityTree.hh
  19. 221
      test/pitytest11/src/PityTree.hxx
  20. 75
      test/pitytest11/src/PityUnit.hh
  21. 136
      test/pitytest11/src/PityUnit.hxx
  22. 41
      test/pitytest11/src/fs_mutex.cc
  23. 25
      test/pitytest11/src/fs_mutex.hh
  24. 32
      test/pitytest11/test/test_assert.cc
  25. 94
      test/pitytest11/test/test_execmodes.cc
  26. 68
      test/pitytest11/test/test_linear.cc
  27. 161
      test/pitytest11/test/test_pitytree.cc
  28. 98
      test/pitytest11/test/test_processdirs.cc
  29. 88
      test/pitytest11/test/test_swarm.cc
  30. 4
      test/test_adapter.cc
  31. 2
      test/test_adapter_cxx.cc
  32. 2
      test/test_group.cc
  33. 2
      test/test_listmanager_dummy.cc
  34. 2
      test/test_pEpSQLite.cc
  35. 4
      test/test_swarm_group.cc
  36. 4
      test/test_swarm_tofu.cc
  37. 2
      test/test_sync_init.cc
  38. 4
      test/test_template_swarm_multi.cc
  39. 4
      test/test_template_swarm_single.cc
  40. 4
      test/test_tofu.cc

14
test/Makefile

@ -1,7 +1,7 @@
include ../Makefile.conf
LDFLAGS:=-L../src $(LDFLAGS) -L./pitytest11/src
LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter -lPityTest -lpthread -ldl
LDFLAGS:=-L../src $(LDFLAGS)
LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter -lPityTest11 -lpthread -ldl
CXXFLAGS:=-I../src -DENGINE_TEST=$(ENGINE_TEST) $(CXXFLAGS)
# Test
@ -22,16 +22,13 @@ OBJ_FRAMEWORK=$(subst .cc,.o,$(SRC_FRAMEWORK))
# -include $(DEPENDS)
#endif
.PHONY: all clean rmtestdata pitytest pitytest-clean
.PHONY: all clean rmtestdata
.DEFAULT_GOAL := all
all: pitytest $(BIN_TEST)
all: $(BIN_TEST)
$(BIN_TEST): $(OBJ_FRAMEWORK)
pitytest:
$(MAKE) -C pitytest11
clean:
rm -f $(BIN_TEST)
rm -f $(OBJ_FRAMEWORK)
@ -40,8 +37,5 @@ clean:
rm -f *.o
rm -Rf /tmp/test_pEp.*
pitytest-clean:
$(MAKE) -C pitytest11 clean
rmtestdata:
rm -Rf /tmp/test_pEp.*

270
test/framework/test_utils.cc

@ -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

132
test/framework/test_utils.hh

@ -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

39
test/pitytest11/Makefile

@ -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

456
test/pitytest11/src/AbstractPityUnit.cc

@ -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

135
test/pitytest11/src/AbstractPityUnit.hh

@ -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

32
test/pitytest11/src/PityModel.cc

@ -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

53
test/pitytest11/src/PityModel.hh

@ -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

63
test/pitytest11/src/PityNode.cc

@ -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

55
test/pitytest11/src/PityNode.hh

@ -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

48
test/pitytest11/src/PityPerspective.cc

@ -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

59
test/pitytest11/src/PityPerspective.hh

@ -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

146
test/pitytest11/src/PitySwarm.cc

@ -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

59
test/pitytest11/src/PitySwarm.hh

@ -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

32
test/pitytest11/src/PityTest.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

97
test/pitytest11/src/PityTransport.cc

@ -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

45
test/pitytest11/src/PityTransport.hh

@ -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

89
test/pitytest11/src/PityTree.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

221
test/pitytest11/src/PityTree.hxx

@ -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

75
test/pitytest11/src/PityUnit.hh

@ -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

136
test/pitytest11/src/PityUnit.hxx

@ -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

41
test/pitytest11/src/fs_mutex.cc

@ -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

25
test/pitytest11/src/fs_mutex.hh

@ -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

32
test/pitytest11/test/test_assert.cc

@ -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) {
}
}

94
test/pitytest11/test/test_execmodes.cc

@ -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();
}
}

68
test/pitytest11/test/test_linear.cc

@ -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();
}

161
test/pitytest11/test/test_pitytree.cc

@ -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;
}

98
test/pitytest11/test/test_processdirs.cc

@ -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();
}

88
test/pitytest11/test/test_swarm.cc

@ -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();
}

4
test/test_adapter.cc

@ -2,9 +2,9 @@
// see LICENSE.txt
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <iostream>
#include <assert.h>
#include <cassert>
#include <pEp/sync_api.h>
#include <pEp/keymanagement.h>

2
test/test_adapter_cxx.cc

@ -2,7 +2,7 @@
// see LICENSE.txt
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <iostream>
#include <assert.h>

2
test/test_group.cc

@ -2,7 +2,7 @@
// see LICENSE.txt
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
//#include <iostream>

2
test/test_listmanager_dummy.cc

@ -1,6 +1,6 @@
#include "../src/listmanager_dummy.hh"
#include "../src/utils.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <exception>
#include <map>
#include <cassert>

2
test/test_pEpSQLite.cc

@ -2,7 +2,7 @@
#include "../src/pEpSQLite.hh"
#include "../src/utils.hh"
#include "../src/std_utils.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <fstream>
#include <cassert>

4
test/test_swarm_group.cc

@ -1,7 +1,7 @@
#include "pitytest11/src/PityTest.hh"
#include <pEp/pitytest11/PityTest.hh>
#include "../src/utils.hh"
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
// libpEpAdapter
#include "../src/Adapter.hh"

4
test/test_swarm_tofu.cc

@ -1,7 +1,7 @@
#include "pitytest11/src/PityTest.hh"
#include <pEp/pitytest11/PityTest.hh>
#include "../src/utils.hh"
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
// libpEpAdapter
#include "../src/Adapter.hh"

2
test/test_sync_init.cc

@ -2,7 +2,7 @@
// see LICENSE.txt
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <iostream>
#include <assert.h>

4
test/test_template_swarm_multi.cc

@ -1,7 +1,7 @@
#include "pitytest11/src/PityTest.hh"
#include <pEp/pitytest11/PityTest.hh>
#include "../src/utils.hh"
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <pEp/pEpEngine.h>
#include <pEp/message_api.h>

4
test/test_template_swarm_single.cc

@ -1,7 +1,7 @@
#include "pitytest11/src/PityTest.hh"
#include <pEp/pitytest11/PityTest.hh>
#include "../src/utils.hh"
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <pEp/pEpEngine.h>
#include <pEp/message_api.h>

4
test/test_tofu.cc

@ -1,7 +1,7 @@
#include "pitytest11/src/PityTest.hh"
#include <pEp/pitytest11/PityTest.hh>
#include "../src/utils.hh"
#include "framework/framework.hh"
#include "framework/test_utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <pEp/pEpEngine.h>
#include <pEp/keymanagement.h>

Loading…
Cancel
Save