Browse Source

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

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

+ 4
- 10
test/Makefile View File

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

+ 0
- 270
test/framework/test_utils.cc View File

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

+ 0
- 132
test/framework/test_utils.hh View File

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

+ 0
- 39
test/pitytest11/Makefile View File

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

+ 0
- 456
test/pitytest11/src/AbstractPityUnit.cc View File

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

+ 0
- 135
test/pitytest11/src/AbstractPityUnit.hh View File

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

+ 0
- 32
test/pitytest11/src/PityModel.cc View File

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

+ 0
- 53
test/pitytest11/src/PityModel.hh View File

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

+ 0
- 63
test/pitytest11/src/PityNode.cc View File

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

+ 0
- 55
test/pitytest11/src/PityNode.hh View File

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

+ 0
- 48
test/pitytest11/src/PityPerspective.cc View File

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

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

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

+ 0
- 146
test/pitytest11/src/PitySwarm.cc View File

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

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

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