Browse Source

Test: pEpTest fix execution model

LIB-11
heck 4 years ago
parent
commit
af276f6f70
  1. 9
      test/pEpTest/src/pEpTestModel.cc
  2. 6
      test/pEpTest/src/pEpTestModel.hh
  3. 136
      test/pEpTest/src/pEpTestUnit.cc
  4. 33
      test/pEpTest/src/pEpTestUnit.hh

9
test/pEpTest/src/pEpTestModel.cc

@ -1,9 +1,16 @@
#include "pEpTestModel.hh" #include "pEpTestModel.hh"
#include "iostream"
//using namespace std; using namespace std;
namespace pEp { namespace pEp {
namespace Test { namespace Test {
bool pEpTestModel::log_enabled = true; bool pEpTestModel::log_enabled = true;
pEpTestModel::pEpTestModel(const string& name) : name(name) {}
const std::string& pEpTestModel::getName() const
{
return name;
}
} // namespace Test } // namespace Test
} // namespace pEp } // namespace pEp

6
test/pEpTest/src/pEpTestModel.hh

@ -9,9 +9,13 @@
namespace pEp { namespace pEp {
namespace Test { namespace Test {
class pEpTestModel { class pEpTestModel {
public: public:
pEpTestModel() = delete;
pEpTestModel(const std::string& name);
const std::string& getName() const;
private: private:
const std::string name;
static bool log_enabled; static bool log_enabled;
Adapter::pEpLog::pEpLogger logger{ "pEpTestModel", log_enabled }; Adapter::pEpLog::pEpLogger logger{ "pEpTestModel", log_enabled };
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger; Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;

136
test/pEpTest/src/pEpTestUnit.cc

@ -13,18 +13,17 @@ namespace pEp {
namespace Test { namespace Test {
bool pEpTestUnit::log_enabled = true; bool pEpTestUnit::log_enabled = true;
string pEpTestUnit::data_dir = "./"; string pEpTestUnit::data_dir = "./";
pEpTestUnit::ExecutionMode pEpTestUnit::exec_mode_default = pEpTestUnit::ExecutionMode::FUNCTION; pEpTestUnit::ExecutionMode pEpTestUnit::emode_default = pEpTestUnit::ExecutionMode::FUNCTION;
// RootNode factory // RootNode factory
//static //static
pEpTestUnit pEpTestUnit::createRootNode( pEpTestUnit pEpTestUnit::createRootNode(
pEpTestModel& model, pEpTestModel& model,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode) ExecutionMode emode_children)
{ {
pEpLog("called"); pEpTestUnit ret(nullptr, &model, name, main_f, emode_children);
pEpTestUnit ret(nullptr, &model, name, main_f, emode);
return ret; return ret;
} }
@ -33,11 +32,10 @@ namespace pEp {
pEpTestUnit pEpTestUnit::createChildNode( pEpTestUnit pEpTestUnit::createChildNode(
pEpTestUnit& parent, pEpTestUnit& parent,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode) ExecutionMode emode_children)
{ {
pEpLog("called"); pEpTestUnit ret(&parent, nullptr, name, main_f, emode_children);
pEpTestUnit ret(&parent, nullptr, name, main_f, emode);
return ret; return ret;
} }
@ -46,19 +44,18 @@ namespace pEp {
pEpTestUnit* const parent, pEpTestUnit* const parent,
pEpTestModel* model, pEpTestModel* model,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode) : ExecutionMode emode_children) :
parent(parent), parent(parent),
model(model), name(name), main_func(main_f), exec_mode(emode) model(model), name(name), main_func(main_f), emode_chld(emode_children)
{ {
logger.set_instancename(getFQName());
if (parent != nullptr) { if (parent != nullptr) {
parent->addChildNode(*this); parent->addChildNode(*this);
} }
logger.set_instancename(getFQName());
// data_dir_recreate(); // data_dir_recreate();
} }
//static //static
void pEpTestUnit::setDefaultDataDir(const std::string& dir) void pEpTestUnit::setDefaultDataDir(const std::string& dir)
{ {
@ -84,18 +81,20 @@ namespace pEp {
void pEpTestUnit::waitChildProcesses() const void pEpTestUnit::waitChildProcesses() const
{ {
pEpLogClass("called"); pEpLogClass("Waiting for child processes to terminate...");
int status; int status;
pid_t pid; pid_t pid;
while ((pid = wait(&status)) > 0) { while ((pid = wait(&status)) > 0) {
pEpLogClass( pEpLogClass(
"PID: " + std::to_string((int)pid) + " exit status: " + std::to_string(status)); "process[" + std::to_string((int)pid) +
"] terminated with status: " + std::to_string(status));
} }
pEpLogClass("All child processes terminated");
} }
void pEpTestUnit::addChildNode(const pEpTestUnit& node) void pEpTestUnit::addChildNode(const pEpTestUnit& node)
{ {
children.insert(pair<string, pEpTestUnit>(node.getName(), node)); children.insert(pair<string, const pEpTestUnit&>(node.getName(), node));
} }
string pEpTestUnit::getName() const string pEpTestUnit::getName() const
@ -105,62 +104,60 @@ namespace pEp {
void pEpTestUnit::run(const pEpTestUnit* caller) const void pEpTestUnit::run(const pEpTestUnit* caller) const
{ {
// pEpLogClass("called"); pEpLogClass("called");
// init(); // caller is never nullptr if called by another pEpTestUnit
executeSelf(); if(caller == nullptr) {
executeChildren(); pEpLogClass("\n" + to_string());
// if called by another TestNode, caller will not be nullptr, so caller will clean up
// if caller is mullptr, there is nobody who will do the cleanup, so we have to.
if (caller == nullptr) {
waitChildProcesses();
}
} }
//private
void pEpTestUnit::executeSelf() const
{
// pEpLogClass("called");
if (main_func) { if (main_func) {
pEpLogClass(string("Starting as: " + to_string(getEffectiveExecutionMode())));
// Execute in fork and go on, wait for process execution in the edn
if (getEffectiveExecutionMode() == ExecutionMode::PROCESS_PARALLEL) { // fork
executeTestFuncInFork(false);
// Execute in fork and wait here until process ends
} else if (getEffectiveExecutionMode() == ExecutionMode::PROCESS_SERIAL) {
executeTestFuncInFork(true);
// Execute as normal funciton
} else if (getEffectiveExecutionMode() == ExecutionMode::FUNCTION) {
// pEpLogClass("Executing in same process and thread");
main_func(*this); main_func(*this);
// pEpLogClass("Execution ended");
} else if (getEffectiveExecutionMode() == ExecutionMode::THREAD_PARALLEL) {
throw runtime_error(to_string(getEffectiveExecutionMode()) + " - not implemented");
} else if (getEffectiveExecutionMode() == ExecutionMode::THREAD_SERIAL) {
throw runtime_error(to_string(getEffectiveExecutionMode()) + " - not implemented");
}
} else { } else {
pEpLogClass("No function to execute"); pEpLogClass("No function to execute");
} }
executeChildren();
} }
//private //private
void pEpTestUnit::executeChildren() const void pEpTestUnit::executeChildren() const
{ {
pEpLogClass("called"); if (!children.empty()) {
for (const pair<string, pEpTestUnit> elem : children) { const ExecutionMode& emode = getEffectiveExecutionMode();
pEpLogClass(string("Executing children as: " + to_string(emode)));
for (const pair<string, const pEpTestUnit&> elem : children) {
// Execute in fork and go on, wait for process execution in the end
if (emode == ExecutionMode::PROCESS_PARALLEL) { // fork
executeForked(elem.second, false);
// Execute in fork and wait here until process ends
} else if (emode == ExecutionMode::PROCESS_SERIAL) {
executeForked(elem.second, true);
// Execute as normal funciton
} else if (emode == ExecutionMode::FUNCTION) {
pEpLogClass("Executing in same process and thread");
elem.second.run(this); elem.second.run(this);
pEpLogClass("Execution ended");
} else if (emode == ExecutionMode::THREAD_PARALLEL) {
throw runtime_error(to_string(emode) + " - not implemented");
} else if (emode == ExecutionMode::THREAD_SERIAL) {
throw runtime_error(to_string(emode) + " - not implemented");
}
}
if (emode == ExecutionMode::PROCESS_PARALLEL) {
waitChildProcesses();
}
} }
} }
//private //private
void pEpTestUnit::executeTestFuncInFork(bool wait) const void pEpTestUnit::executeForked(const pEpTestUnit& unit, bool wait) const
{ {
pid_t pid; pid_t pid;
pid = fork(); pid = fork();
if (pid == pid_t(0)) { if (pid == pid_t(0)) {
pEpLogClass(string("pid: [" + std::to_string(getpid()) + "] - starting...")); pEpLogClass(string("In pid: [" + std::to_string(getpid()) + "] - starting..."));
setenv("HOME", getHomeDir().c_str(), 1); setenv("HOME", getHomeDir().c_str(), 1);
main_func(*this); unit.run(this);
pEpLogClass(string("pid: [" + std::to_string(getpid()) + "] - ended.")); pEpLogClass(string("In pid: [" + std::to_string(getpid()) + "] - ended."));
exit(0); exit(0);
} else if (pid < pid_t(0)) { } else if (pid < pid_t(0)) {
pEpLogClass("Error forking"); pEpLogClass("Error forking");
@ -172,7 +169,7 @@ namespace pEp {
pEpTestModel& pEpTestUnit::getModel() const pEpTestModel& pEpTestUnit::getModel() const
{ {
pEpLogClass("called"); // pEpLogClass("called");
pEpTestModel* ret = nullptr; pEpTestModel* ret = nullptr;
if (model == nullptr) { if (model == nullptr) {
ret = &parent->getModel(); ret = &parent->getModel();
@ -187,7 +184,7 @@ namespace pEp {
const pEpTestUnit& pEpTestUnit::getRoot() const const pEpTestUnit& pEpTestUnit::getRoot() const
{ {
pEpLogClass("called"); // pEpLogClass("called");
const pEpTestUnit* ret = nullptr; const pEpTestUnit* ret = nullptr;
if (parent != nullptr) { if (parent != nullptr) {
ret = &parent->getRoot(); ret = &parent->getRoot();
@ -238,27 +235,24 @@ namespace pEp {
data_dir_create(); data_dir_create();
}; };
//static
void pEpTestUnit::setDefaultExecutionMode(ExecutionMode emode) void pEpTestUnit::setDefaultExecutionMode(ExecutionMode emode)
{ {
pEpTestUnit::exec_mode_default = emode; pEpTestUnit::emode_default = emode;
} }
pEpTestUnit::ExecutionMode pEpTestUnit::getExecutionMode() const pEpTestUnit::ExecutionMode pEpTestUnit::getExecutionMode() const
{ {
return exec_mode; return emode_chld;
} }
pEpTestUnit::ExecutionMode pEpTestUnit::getEffectiveExecutionMode() const pEpTestUnit::ExecutionMode pEpTestUnit::getEffectiveExecutionMode() const
{ {
ExecutionMode ret; ExecutionMode ret{ emode_default };
if (getExecutionMode() == ExecutionMode::INHERIT) { if (getExecutionMode() == ExecutionMode::INHERIT) {
if (parent != nullptr) { if (parent != nullptr) {
// get from parent until not inherit // get from parent until not inherit
ret = parent->getEffectiveExecutionMode(); ret = parent->getEffectiveExecutionMode();
} else {
// get from static class config
ret = pEpTestUnit::exec_mode_default;
} }
} else { } else {
ret = getExecutionMode(); ret = getExecutionMode();
@ -285,5 +279,25 @@ namespace pEp {
return "UNDEFINED EXECUTION MODE"; return "UNDEFINED EXECUTION MODE";
} }
} }
std::string pEpTestUnit::to_string(bool recursive, int indent) const
{
string ret;
stringstream builder;
builder << string(indent, '\t') << getName();
builder << "[children=" << to_string(getEffectiveExecutionMode()) + "]";
// builder << "/" << getModel().getName();
builder << endl;
ret = builder.str();
if (recursive) {
indent++;
for (const pair<string, const pEpTestUnit&> elem : children) {
ret += elem.second.to_string(true, indent);
}
indent--;
}
return ret;
}
} // namespace Test } // namespace Test
} // namespace pEp } // namespace pEp

33
test/pEpTest/src/pEpTestUnit.hh

@ -14,7 +14,8 @@ namespace pEp {
namespace Test { namespace Test {
class pEpTestUnit { class pEpTestUnit {
public: public:
using TestEntryFunc = std::function<void(const pEpTestUnit&)>; using TestUnitFunction = std::function<void(const pEpTestUnit&)>;
enum class ExecutionMode enum class ExecutionMode
{ {
FUNCTION, FUNCTION,
@ -33,14 +34,14 @@ namespace pEp {
static pEpTestUnit createRootNode( static pEpTestUnit createRootNode(
pEpTestModel& model, pEpTestModel& model,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode = ExecutionMode::INHERIT); ExecutionMode emode_children = emode_default);
static pEpTestUnit createChildNode( static pEpTestUnit createChildNode(
pEpTestUnit& parent, pEpTestUnit& parent,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode = ExecutionMode::INHERIT); ExecutionMode emode_children = emode_default);
static void setDefaultDataDir(const std::string& dir); static void setDefaultDataDir(const std::string& dir);
@ -51,9 +52,8 @@ namespace pEp {
std::string getFQName() const; std::string getFQName() const;
pEpTestModel& getModel() const; pEpTestModel& getModel() const;
std::string getHomeDir() const; std::string getHomeDir() const;
std::string to_string(bool recursive = true, int indent = 0) const;
static void setDefaultExecutionMode(ExecutionMode emode); static void setDefaultExecutionMode(ExecutionMode emode);
ExecutionMode getExecutionMode() const;
ExecutionMode getEffectiveExecutionMode() const;
private: private:
// Constructors // Constructors
@ -61,17 +61,18 @@ namespace pEp {
pEpTestUnit* parent, pEpTestUnit* parent,
pEpTestModel* model, pEpTestModel* model,
const std::string& name, const std::string& name,
const TestEntryFunc& main_f, const TestUnitFunction& main_f,
ExecutionMode emode); ExecutionMode emode_children);
// Methods // Methods
void init() const; void init() const;
const pEpTestUnit& getRoot() const; const pEpTestUnit& getRoot() const;
void executeSelf() const;
void executeChildren() const;
void executeTestFuncInFork(bool wait) const; void executeChildren() const;
void executeForked(const pEpTestUnit& unit, bool wait) const;
void waitChildProcesses() const; void waitChildProcesses() const;
ExecutionMode getExecutionMode() const;
ExecutionMode getEffectiveExecutionMode() const;
void data_dir_delete(); void data_dir_delete();
void data_dir_create(); void data_dir_create();
void data_dir_recreate(); void data_dir_recreate();
@ -80,10 +81,10 @@ namespace pEp {
const pEpTestUnit* parent; //nullptr if rootnode const pEpTestUnit* parent; //nullptr if rootnode
const std::string name; const std::string name;
pEpTestModel* model; //nullptr if inherited pEpTestModel* model; //nullptr if inherited
const TestEntryFunc& main_func; const TestUnitFunction& main_func;
ExecutionMode exec_mode; const ExecutionMode emode_chld;
static ExecutionMode exec_mode_default; static ExecutionMode emode_default;
std::map<const std::string, pEpTestUnit> children; std::map<const std::string, const pEpTestUnit&> children;
static std::string data_dir; static std::string data_dir;
// logger // logger

Loading…
Cancel
Save