Browse Source

Tests: PityTest - Separation of concerns

LIB-11
heck 4 years ago
parent
commit
717dd5acd2
  1. 169
      test/pitytest11/src/PityModel.cc
  2. 16
      test/pitytest11/src/PityModel.hh
  3. 45
      test/pitytest11/src/PityNode.cc
  4. 17
      test/pitytest11/src/PityNode.hh
  5. 83
      test/pitytest11/src/PitySwarm.cc
  6. 46
      test/pitytest11/src/PitySwarm.hh

169
test/pitytest11/src/PityModel.cc

@ -10,13 +10,11 @@ namespace pEp {
namespace PityTest11 { namespace PityTest11 {
bool PityModel::debug_log_enabled = false; bool PityModel::debug_log_enabled = false;
PityModel::PityModel(const std::string& name, int nodeCount) : PityModel::PityModel(const std::string& name, int nodeCount) : _name{ name }
_name{ name }, _unit{ nullptr, name, nullptr, this }
{ {
for (int i = 0; i < nodeCount; i++) { for (int i = 0; i < nodeCount; i++) {
_nodes.emplace_back(std::make_shared<PityNode>(*this, i)); _nodes.emplace_back(std::make_shared<PityNode>(i));
} }
} }
std::string PityModel::getName() const std::string PityModel::getName() const
@ -24,105 +22,96 @@ namespace pEp {
return _name; return _name;
} }
void PityModel::setName(std::string name) // void PityModel::setName(std::string name)
{ // {
_name = name; // _name = name;
} // }
std::vector<std::shared_ptr<PityNode>> PityModel::nodes() const std::vector<std::shared_ptr<PityNode>> PityModel::nodes() const
{ {
return _nodes; return _nodes;
} }
PityUnit<PityModel>& PityModel::unit() // PityUnit<PityModel>* PityModel::unitOfNodeNr(int nr) const
{ // {
return _unit; // return nodes().at(nr)->unit().get();
} // }
PityUnit<PityModel>* PityModel::unitOfNodeNr(int nr) const
{
return nodes().at(nr)->unit().get();
}
PityNode* PityModel::nodeNr(int nr) const PityNode* PityModel::nodeNr(int nr) const
{ {
return nodes().at(nr).get(); return nodes().at(nr).get();
} }
void PityModel::run()
{
unit().run();
}
void PityModel::sendMsg(const std::string nodename, const std::string& msg) const
{
pEpLogClass("Address: " + nodename + " msg: " + msg);
bool found = false;
for (auto n : _nodes) {
if (n->getName() == nodename) {
found = true;
Utils::dir_ensure(n->inboxDir());
std::stringstream filename;
// collision detect
do {
filename << n->inboxDir() << Utils::random_string(97, 122, 16) << ".pitymsg";
} while (Utils::path_exists(filename.str()));
std::ofstream msgfile = Utils::file_create(filename.str());
msgfile << msg;
}
}
if (!found) {
throw std::runtime_error("no such nodename: " + nodename);
}
}
bool PityModel::hasMsg() const{
bool ret = false;
pEpLogClass("called");
Utils::dir_ensure(own_node->inboxDir());
auto msg_filenames = Utils::dir_list_files(own_node->inboxDir());
ret = msg_filenames.size() > 0;
return ret;
}
// Non-blocking // void PityModel::sendMsg(const std::string nodename, const std::string& msg) const
// throws underflow_error if inbox empty // {
std::string PityModel::pollMsg() const // pEpLogClass("Address: " + nodename + " msg: " + msg);
{ // bool found = false;
pEpLogClass("called"); // for (auto n : _nodes) {
std::string ret; // if (n->getName() == nodename) {
Utils::dir_ensure(own_node->inboxDir()); // found = true;
auto msg_filenames = Utils::dir_list_files(own_node->inboxDir()); // Utils::dir_ensure(n->inboxDir());
if (!msg_filenames.empty()) { // std::stringstream filename;
std::string msg_filename = msg_filenames.at(0); // // collision detect
std::string msg_path = own_node->inboxDir() + "/" + msg_filename; // do {
pEpLogClass("Reading file: " + msg_filename); // filename << n->inboxDir() << Utils::random_string(97, 122, 16) << ".pitymsg";
ret = Utils::file_read(msg_path); // } while (Utils::path_exists(filename.str()));
Utils::path_delete(msg_path); // std::ofstream msgfile = Utils::file_create(filename.str());
} else { // msgfile << msg;
throw std::underflow_error("inbox empty: " + own_node->inboxDir()); // }
} // }
// if (!found) {
return ret; // throw std::runtime_error("no such nodename: " + nodename);
} // }
// }
std::string PityModel::receiveMsg(int timeout_msec) const //
{ // bool PityModel::hasMsg() const{
pEpLogClass("called"); // bool ret = false;
std::string ret; // pEpLogClass("called");
bool retry = false; // Utils::dir_ensure(own_node->inboxDir());
do { // auto msg_filenames = Utils::dir_list_files(own_node->inboxDir());
try { // ret = msg_filenames.size() > 0;
ret = pollMsg(); // return ret;
retry = false; // }
} catch (const std::underflow_error&) { //
pEpLogClass("polling again in [ms]: " + std::to_string(timeout_msec) + "..."); // // Non-blocking
Utils::sleep_millis(timeout_msec); // // throws underflow_error if inbox empty
retry = true; // std::string PityModel::pollMsg() const
} // {
} while (retry); // pEpLogClass("called");
return ret; // std::string ret;
} // Utils::dir_ensure(own_node->inboxDir());
// auto msg_filenames = Utils::dir_list_files(own_node->inboxDir());
// if (!msg_filenames.empty()) {
// std::string msg_filename = msg_filenames.at(0);
// std::string msg_path = own_node->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: " + own_node->inboxDir());
// }
//
// return ret;
// }
//
// std::string PityModel::receiveMsg(int timeout_msec) 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(timeout_msec) + "...");
// Utils::sleep_millis(timeout_msec);
// retry = true;
// }
// } while (retry);
// return ret;
// }
} // namespace PityTest11 } // namespace PityTest11
} // namespace pEp } // namespace pEp

16
test/pitytest11/src/PityModel.hh

@ -38,8 +38,8 @@ namespace pEp {
// Getters // Getters
std::string getName() const; std::string getName() const;
std::vector<std::shared_ptr<PityNode>> nodes() const; std::vector<std::shared_ptr<PityNode>> nodes() const;
PityUnit<PityModel>& unit(); // PityUnit<PityModel>& unit();
PityUnit<PityModel>* unitOfNodeNr(int nr) const; // PityUnit<PityModel>* unitOfNodeNr(int nr) const;
PityNode* nodeNr(int nr) const; PityNode* nodeNr(int nr) const;
// Setter // Setter
@ -48,21 +48,17 @@ namespace pEp {
// Perspective // Perspective
PityNode* own_node = nullptr; PityNode* own_node = nullptr;
//Run
void run();
//Transport //Transport
bool hasMsg() const; // bool hasMsg() const;
void sendMsg(const std::string nodename, const std::string& msg) const; // void sendMsg(const std::string nodename, const std::string& msg) const;
std::string pollMsg() const; // std::string pollMsg() const;
std::string receiveMsg(int timeout_msec = 100) const; // std::string receiveMsg(int timeout_msec = 100) const;
//internal logging //internal logging
static bool debug_log_enabled; static bool debug_log_enabled;
Adapter::pEpLog::pEpLogger logger_debug{ "PityModel", debug_log_enabled }; Adapter::pEpLog::pEpLogger logger_debug{ "PityModel", debug_log_enabled };
private: private:
PityUnit<PityModel> _unit;
std::vector<std::shared_ptr<PityNode>> _nodes; std::vector<std::shared_ptr<PityNode>> _nodes;
std::string _name; std::string _name;

45
test/pitytest11/src/PityNode.cc

@ -1,6 +1,7 @@
#include "PityModel.hh" #include "PityModel.hh"
#include "PityNode.hh" #include "PityNode.hh"
#include "PityUnit.hh" #include "PityUnit.hh"
#include "PityPerspective.hh"
#include "iostream" #include "iostream"
#include <memory> #include <memory>
#include <functional> #include <functional>
@ -11,39 +12,17 @@ namespace pEp {
namespace PityTest11 { namespace PityTest11 {
bool PityNode::debug_log_enabled = false; bool PityNode::debug_log_enabled = false;
PityNode::PityNode(PityModel& model, int nodeNr) : _node_nr{ nodeNr } PityNode::PityNode(int nodeNr) : _node_nr{ nodeNr }
{ {
logger_debug.set_instancename(getName()); logger_debug.set_instancename(getName());
std::stringstream ss{}; std::stringstream ss{};
ss << this; ss << this;
pEpLogClass(std::string("called with: " + std::to_string(_node_nr) + "AT: " + ss.str())); pEpLogClass(std::string("called with: " + std::to_string(_node_nr) + "AT: " + ss.str()));
_unit = std::make_shared<PityUnit<PityModel>>(
&(model.unit()),
getName(),
std::bind(&PityNode::_init, this, std::placeholders::_1),
&model,
PityUnit<PityModel>::ExecutionMode::PROCESS_PARALLEL);
} }
// We NEED to customize (perspective) the model here int PityNode::getNr() const
// This will be executed in the new process
void PityNode::_init(const PityUnit<PityModel>& unit)
{ {
unit.log("NODE INIT - " + getName()); return _node_nr;
unit.getModel()->own_node = this;
unit.getModel()->setName("Copy for:" + getName());
_partnerAlgo_NextCircle();
// Create peers, everyone but me
auto nodes = _unit->getModel()->nodes();
for (int i = 0; i < nodes.size(); i++) {
if (i != _node_nr) {
peers.push_back(nodes.at(i)->getName());
}
}
unit.log("NODE INIT DONE");
} }
std::string PityNode::getName() const std::string PityNode::getName() const
@ -59,21 +38,5 @@ namespace pEp {
ret += "name: " + getName(); ret += "name: " + getName();
return ret; return ret;
} }
const std::shared_ptr<PityUnit<PityModel>>& PityNode::unit() const
{
return _unit;
}
std::string PityNode::inboxDir() const
{
return unit()->processDir() + "inbox/";
}
void PityNode::_partnerAlgo_NextCircle() {
// Default partner is next node, its a circle
int partner_node_index = (_node_nr+1) % _unit->getModel()->nodes().size();
partner = unit()->getModel()->nodes().at(partner_node_index)->getName();
}
} // namespace PityTest11 } // namespace PityTest11
} // namespace pEp } // namespace pEp

17
test/pitytest11/src/PityNode.hh

@ -7,6 +7,7 @@
#include "../../../src/pEpLog.hh" #include "../../../src/pEpLog.hh"
#include "PityUnit.hh" #include "PityUnit.hh"
#include "PityModel.hh" #include "PityModel.hh"
#include "PityPerspective.hh"
namespace pEp { namespace pEp {
namespace PityTest11 { namespace PityTest11 {
@ -15,18 +16,12 @@ namespace pEp {
public: public:
// Constructors // Constructors
PityNode() = delete; PityNode() = delete;
explicit PityNode(PityModel& model, int nodeNr); explicit PityNode(int nodeNr);
// Getters // Getters
int getNr() const;
std::string getName() const; std::string getName() const;
std::string to_string() const; std::string to_string() const;
const std::shared_ptr<PityUnit<PityModel>>& unit() const;
std::string inboxDir() const;
// Perspective
std::string partner;
std::vector<std::string> peers;
//internal logging //internal logging
static bool debug_log_enabled; static bool debug_log_enabled;
@ -35,12 +30,6 @@ namespace pEp {
private: private:
//fields //fields
const int _node_nr; const int _node_nr;
std::shared_ptr<PityUnit<PityModel>> _unit;
// methods
void _init(const PityUnit<PityModel>& unit);
void _partnerAlgo_NextCircle();
//internal logging //internal logging
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug; Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug;

83
test/pitytest11/src/PitySwarm.cc

@ -0,0 +1,83 @@
#include "PityModel.hh"
#include "PityUnit.hh"
#include "PitySwarm.hh"
#include <vector>
#include <functional>
#include <memory>
namespace pEp {
namespace PityTest11 {
bool PitySwarm::debug_log_enabled = false;
void createPerspective(const PityModel& model, PityPerspective* psp, int node_nr)
{
psp->name = model.nodeNr(node_nr)->getName();
// Default partner is next node, its a circle
int partner_node_index = (node_nr + 1) % model.nodes().size();
psp->partner = model.nodes().at(partner_node_index)->getName();
// Create peers, everyone but me
auto nodes = model.nodes();
for (int i = 0; i < nodes.size(); i++) {
if (i != node_nr) {
psp->peers.push_back(nodes.at(i)->getName());
}
}
}
PitySwarm::PitySwarm(PityModel& model) : _model{ model }
{
pEpLogClass("called");
// Create perspective
for (auto n : _model.nodes()) {
auto tmp = std::make_shared<PityPerspective>();
createPerspective(_model, tmp.get(), n->getNr());
_perspectives.push_back(tmp);
}
// Construct Tree
_rootUnit = std::make_shared<PityUnit<PityModel, PityPerspective>>(
nullptr,
_model.getName(),
nullptr,
&_model);
for (auto n : _model.nodes()) {
_nodeUnits.push_back(std::make_shared<PityUnit<>>(
_rootUnit.get(),
n->getName(),
nullptr,
// std::bind(
// &PityNode::_init,
// this,
// std::placeholders::_1,
// std::placeholders::_2,
// std::placeholders::_3),
&_model,
_perspectives.at(n->getNr()).get(),
PityUnit<>::ExecutionMode::PROCESS_PARALLEL));
}
}
void PitySwarm::addTestUnit(
int nodeNr,
const std::string& name,
std::function<void(PityUnit<>&, PityModel*, PityPerspective*)> test_func)
{
auto tmp = std::make_shared <PityUnit<>>(_nodeUnits.at(nodeNr).get(), name, test_func);
_testUnits.push_back(tmp);
}
void PitySwarm::run()
{
_rootUnit->run();
}
} // namespace PityTest11
} // namespace pEp

46
test/pitytest11/src/PitySwarm.hh

@ -0,0 +1,46 @@
// 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 "../../../src/pEpLog.hh"
#include <vector>
#include <memory>
#include <functional>
namespace pEp {
namespace PityTest11 {
class PitySwarm {
public:
// Constructors
PitySwarm(PityModel& model);
void addTestUnit(
int nodeNr,
const std::string& name,
std::function<void(PityUnit<>&, PityModel*, PityPerspective*)> test_func);
//Run
void run();
//internal logging
static bool debug_log_enabled;
Adapter::pEpLog::pEpLogger logger_debug{ "PityNode", debug_log_enabled };
private:
PityModel& _model;
std::shared_ptr<PityUnit<>> _rootUnit;
std::vector<std::shared_ptr<PityUnit<>>> _nodeUnits;
std::vector<std::shared_ptr<PityUnit<>>> _testUnits;
std::vector<std::shared_ptr<PityPerspective>> _perspectives;
//internal logging
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger_debug;
};
}; // namespace PityTest11
}; // namespace pEp
#endif // PITYTEST_PITYSWARM_HH
Loading…
Cancel
Save