Commit f17d6738 by amir

add testing to microservice and run them from rest/http

parent 3901676c
...@@ -43,7 +43,7 @@ set (3PARTY_SOURCES ../3party/civetweb/src/civetweb.c ../3party/civetweb/src/Civ ...@@ -43,7 +43,7 @@ set (3PARTY_SOURCES ../3party/civetweb/src/civetweb.c ../3party/civetweb/src/Civ
#Generate the shared library from the sources #Generate the shared library from the sources
add_library(Microservice SHARED ${SOURCES} ${3PARTY_SOURCES} src/impl/servers/Microservice_IRestServerZmqImpl.cpp src/impl/servers/Microservice_IRestServerZmqImpl.h src/common/Microservice_Iface.cpp src/impl/clients/MSICommandClientZmqImpl.cpp src/impl/clients/MSICommandClientZmqImpl.h src/impl/Microservice_ICacheClientPocoImpl.h) add_library(Microservice SHARED ${SOURCES} ${3PARTY_SOURCES} src/impl/servers/Microservice_IRestServerZmqImpl.cpp src/impl/servers/Microservice_IRestServerZmqImpl.h src/common/Microservice_Iface.cpp src/impl/clients/MSICommandClientZmqImpl.cpp src/impl/clients/MSICommandClientZmqImpl.h src/impl/Microservice_ICacheClientPocoImpl.h src/handlers/Microservice_TestHandler.cpp src/handlers/Microservice_TestHandler.h)
target_link_libraries(Microservice ${PROJECT_LINK_LIBS} ) target_link_libraries(Microservice ${PROJECT_LINK_LIBS} )
set_target_properties(Microservice PROPERTIES VERSION ${Microservice_VERSION_STRING} set_target_properties(Microservice PROPERTIES VERSION ${Microservice_VERSION_STRING}
SOVERSION ${Microservice_VERSION_MAJOR}) SOVERSION ${Microservice_VERSION_MAJOR})
......
...@@ -20,8 +20,8 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ...@@ -20,8 +20,8 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# app # app
COPY ./tmp/* /usr/lib/x86_64-linux-gnu/ COPY ./tmp/* /usr/lib/x86_64-linux-gnu/
COPY ./bin/test_Microservice /usr/ COPY ./bin/test_MicroserviceClient /usr/
WORKDIR /usr WORKDIR /usr
ENTRYPOINT ["./test_Microservice"] ENTRYPOINT ["./test_MicroserviceClient"]
...@@ -38,6 +38,7 @@ Microservice_App::Microservice_App(const char* appName) { ...@@ -38,6 +38,7 @@ Microservice_App::Microservice_App(const char* appName) {
mpc_Configuration = nullptr; mpc_Configuration = nullptr;
mpc_Logger = nullptr; mpc_Logger = nullptr;
mpc_MonitorHandler = nullptr; mpc_MonitorHandler = nullptr;
p_testHandler_ = nullptr;
mpc_PubSubClient = nullptr; mpc_PubSubClient = nullptr;
mpc_ServiceDiscovery = nullptr; mpc_ServiceDiscovery = nullptr;
enableMetrics = false; enableMetrics = false;
...@@ -79,7 +80,12 @@ Microservice_App::Microservice_App(const char* appName) { ...@@ -79,7 +80,12 @@ Microservice_App::Microservice_App(const char* appName) {
Microservice_App& Microservice_App::withMonitoring() { Microservice_App& Microservice_App::withMonitoring() {
this->mpc_MonitorHandler = new cMicroservice_MonitorHandler(); this->mpc_MonitorHandler = new cMicroservice_MonitorHandler();
return addHandler(nsMicroservice_Constants::MON_PREFIX, (Microservice_RestHandler*)mpc_MonitorHandler); return addHandler(cMicroservice_MonitorHandler::PREFIX, (Microservice_RestHandler*)mpc_MonitorHandler);
}
Microservice_App &Microservice_App::withTesting() {
p_testHandler_ = new Microservice_TestHandler();
return addHandler(Microservice_TestHandler::PREFIX, (Microservice_RestHandler*)p_testHandler_);
} }
...@@ -174,6 +180,21 @@ Microservice_App& Microservice_App::addHandler(const char* pba_Prefix, IHandler* ...@@ -174,6 +180,21 @@ Microservice_App& Microservice_App::addHandler(const char* pba_Prefix, IHandler*
return *this; return *this;
} }
Microservice_App &Microservice_App::addTest(const char *testName, nsMicroservice_Iface::TestFunction testFunction) {
if (p_testHandler_ == nullptr)
withTesting();
p_testHandler_->addTest(testName,testFunction);
return *this;
}
Microservice_App &Microservice_App::addTest(nsMicroservice_Iface::ITest *p_testClass) {
if (p_testHandler_ == nullptr)
withTesting();
p_testHandler_->addTest(p_testClass);
return *this;
}
/** /**
* *
* @return init ok * @return init ok
...@@ -288,7 +309,8 @@ Microservice_App& Microservice_App::build() { ...@@ -288,7 +309,8 @@ Microservice_App& Microservice_App::build() {
handler->Init(); handler->Init();
// add handler to monitoring // add handler to monitoring
if(this->mpc_MonitorHandler && if(this->mpc_MonitorHandler &&
prfxHandler.first.compare(nsMicroservice_Constants::MON_PREFIX) != 0) ( prfxHandler.first.compare(cMicroservice_MonitorHandler::PREFIX) != 0) ||
prfxHandler.first.compare(Microservice_TestHandler::PREFIX) != 0)
{ {
this->mpc_MonitorHandler->AddHandler(handler); this->mpc_MonitorHandler->AddHandler(handler);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <mutex> // std::mutex, std::unique_lock #include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable #include <condition_variable> // std::condition_variable
#include <handlers/Microservice_Reactor.h> #include <handlers/Microservice_Reactor.h>
#include <handlers/Microservice_TestHandler.h>
#include "Microservice_Client.h" #include "Microservice_Client.h"
...@@ -28,6 +29,7 @@ class Microservice_RestHandler; ...@@ -28,6 +29,7 @@ class Microservice_RestHandler;
//class cMicroservice_RestServer; //class cMicroservice_RestServer;
//class cMicroservice_RMQServer; //class cMicroservice_RMQServer;
class cMicroservice_MonitorHandler; class cMicroservice_MonitorHandler;
class Microservice_TestHandler;
using namespace nsMicroservice_Iface; using namespace nsMicroservice_Iface;
...@@ -56,6 +58,7 @@ private: ...@@ -56,6 +58,7 @@ private:
IPubSub* mpc_PubSubClient; IPubSub* mpc_PubSubClient;
IConfiguration* mpc_Configuration; IConfiguration* mpc_Configuration;
cMicroservice_MonitorHandler* mpc_MonitorHandler; cMicroservice_MonitorHandler* mpc_MonitorHandler;
Microservice_TestHandler* p_testHandler_;
IMetricsFactory* p_metricsFactory_; IMetricsFactory* p_metricsFactory_;
// servers // servers
// cMicroservice_RestServer* mpc_RestServer; // cMicroservice_RestServer* mpc_RestServer;
...@@ -120,7 +123,7 @@ public: ...@@ -120,7 +123,7 @@ public:
} }
Microservice_App& withMonitoring(); Microservice_App& withMonitoring();
Microservice_App& withTesting();
/************************************************* /*************************************************
* ADD SECTION * ADD SECTION
**************************************************/ **************************************************/
...@@ -129,7 +132,8 @@ public: ...@@ -129,7 +132,8 @@ public:
Microservice_App& addServer(IServer* p_server); Microservice_App& addServer(IServer* p_server);
Microservice_App& addClient(cMicroservice_Client *pc_client); Microservice_App& addClient(cMicroservice_Client *pc_client);
Microservice_App& addHandler(const char* pba_Prefix, IHandler* p_handler); Microservice_App& addHandler(const char* pba_Prefix, IHandler* p_handler);
Microservice_App& addTest(const char* testName, nsMicroservice_Iface::TestFunction testFunction);
Microservice_App& addTest(nsMicroservice_Iface::ITest* p_testClass);
/**************************************************************/ /**************************************************************/
//void AddHandler(const char* pba_Prefix, cMicroservice_BaseHandler* pc_Handler); //void AddHandler(const char* pba_Prefix, cMicroservice_BaseHandler* pc_Handler);
......
...@@ -49,7 +49,6 @@ namespace nsMicroservice_Constants ...@@ -49,7 +49,6 @@ namespace nsMicroservice_Constants
static const char* ERROR_REST_RESPONSE_TEMPLATE_PREFIX = "{ \"success\": false, \"error\": \""; static const char* ERROR_REST_RESPONSE_TEMPLATE_PREFIX = "{ \"success\": false, \"error\": \"";
static const char* ERROR_REST_RESPONSE_TEMPLATE_SUFFIX = "\", \"objectNode\": null "; static const char* ERROR_REST_RESPONSE_TEMPLATE_SUFFIX = "\", \"objectNode\": null ";
static const char* COMMAND_ERROR = "Command Error: "; static const char* COMMAND_ERROR = "Command Error: ";
static const char* MON_PREFIX = "/_mon";
static const char* LOG_FILE_PATH = "/var/log/mcx/msApp.log"; static const char* LOG_FILE_PATH = "/var/log/mcx/msApp.log";
static const int LOG_FILE_SIZE = 50*1024*1024; static const int LOG_FILE_SIZE = 50*1024*1024;
static const char* LOCALHOST = "localhost"; static const char* LOCALHOST = "localhost";
...@@ -59,7 +58,7 @@ namespace nsMicroservice_Constants ...@@ -59,7 +58,7 @@ namespace nsMicroservice_Constants
static const char *const EXIT_MSG = "exit"; static const char *const EXIT_MSG = "exit";
static const int EXIT_MSG_LEN = strlen(EXIT_MSG); static const int EXIT_MSG_LEN = strlen(EXIT_MSG);
static const int REQUEST_MSG_INITIAL_SIZE = 1024; static const int REQUEST_MSG_INITIAL_SIZE = 1024;
static const char *const NOT_IMPLEMENTED = "Not Implemented";
} }
/* /*
......
...@@ -29,6 +29,7 @@ class Microservice_MsgQContext; ...@@ -29,6 +29,7 @@ class Microservice_MsgQContext;
class Microservice_PubSubContext; class Microservice_PubSubContext;
typedef std::map<std::string, std::deque<std::string> > DequeStringMap;
namespace nsMicroservice_Iface namespace nsMicroservice_Iface
{ {
...@@ -157,13 +158,6 @@ namespace nsMicroservice_Iface ...@@ -157,13 +158,6 @@ namespace nsMicroservice_Iface
virtual const char* getType() final { return TYPE; } virtual const char* getType() final { return TYPE; }
/** /**
* does it support async internally, if not
* the MSClient will have to provide the async capability
* @return
*/
//virtual bool supportAsync() = 0;
/**
* the create/post of CRUD * the create/post of CRUD
* @param p_cmd_params * @param p_cmd_params
* @param p_response * @param p_response
...@@ -468,6 +462,12 @@ namespace nsMicroservice_Iface ...@@ -468,6 +462,12 @@ namespace nsMicroservice_Iface
virtual void Init() {} virtual void Init() {}
}; };
using TestFunction = std::function<MSRetStat(std::stringstream& output,DequeStringMap& queryParams)>;
using TestsMap = std::map<std::string,TestFunction>;
struct ITest
{
virtual void getAllTests(TestsMap & testsMap) = 0;
};
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <common/Microservice_Iface.h> #include <common/Microservice_Iface.h>
typedef rapidjson::Writer<rapidjson::StringBuffer> JsonStringWriter; typedef rapidjson::Writer<rapidjson::StringBuffer> JsonStringWriter;
typedef std::map<std::string, std::deque<std::string> > DequeStringMap;
typedef cMicroservice_Enums::eCrudMethod eCrudMethod; typedef cMicroservice_Enums::eCrudMethod eCrudMethod;
/** /**
* *
......
...@@ -35,6 +35,7 @@ class Microservice_App; ...@@ -35,6 +35,7 @@ class Microservice_App;
*/ */
class cMicroservice_MonitorHandler: public virtual Microservice_RestHandler { class cMicroservice_MonitorHandler: public virtual Microservice_RestHandler {
public: public:
static constexpr const char* PREFIX = "/_mon";
cMicroservice_MonitorHandler(); cMicroservice_MonitorHandler();
cMicroservice_MonitorHandler(const cMicroservice_MonitorHandler& orig); cMicroservice_MonitorHandler(const cMicroservice_MonitorHandler& orig);
virtual ~cMicroservice_MonitorHandler(); virtual ~cMicroservice_MonitorHandler();
......
//
// Created by amir on 19/04/17.
//
#include <Microservice_BaseRestResponse.h>
#include "Microservice_TestHandler.h"
void Microservice_TestHandler::DoCreate(cMicroservice_RequestContext *pc_reqCtx) {
SendErrorResp(pc_reqCtx,nsMicroservice_Constants::NOT_IMPLEMENTED);
}
void Microservice_TestHandler::DoRead(cMicroservice_RequestContext *pc_reqCtx) {
cMicroservice_BaseRestResponse brr;
if(pc_reqCtx->mc_Params.empty()) {
/**
* return all test and names
*/
if (!testsMap_.empty()){
rapidjson::Document& doc = brr.GetObjectNode();
rapidjson::Document::AllocatorType& rpj_Alloc = doc.GetAllocator();
doc.SetArray();
for (auto entry : testsMap_){
doc.PushBack(rapidjson::StringRef(entry.first.c_str()),rpj_Alloc);
}
} else {
brr.SetError("NO TESTS FOR YOU (;-)");
}
} else {
/**
* running specific test
*/
auto funcIterator = testsMap_.find(pc_reqCtx->mc_Params[0]);
if (funcIterator != testsMap_.end()){
std::stringstream ss;
MSRetStat retStat = funcIterator->second(ss,pc_reqCtx->mc_QueryParameters);
if (retStat.IsSuccess()){
rapidjson::Document& doc = brr.GetObjectNode();
rapidjson::Document::AllocatorType& rpj_Alloc = doc.GetAllocator();
doc.SetObject();
doc.AddMember(rapidjson::StringRef(funcIterator->first.c_str()),rapidjson::StringRef(ss.str().c_str()),rpj_Alloc);
} else {
ss.clear();
ss << "Test Failed: " << retStat.GetError().c_str();
brr.SetError(ss.str().c_str());
}
}
}
WriteObjectToResponse(pc_reqCtx,brr);
}
void Microservice_TestHandler::DoUpdate(cMicroservice_RequestContext *pc_reqCtx) {
SendErrorResp(pc_reqCtx,nsMicroservice_Constants::NOT_IMPLEMENTED);
}
void Microservice_TestHandler::DoDelete(cMicroservice_RequestContext *pc_reqCtx) {
SendErrorResp(pc_reqCtx,nsMicroservice_Constants::NOT_IMPLEMENTED);
}
void Microservice_TestHandler::Init() {
}
void Microservice_TestHandler::addTest(nsMicroservice_Iface::ITest *p_testClass) {
if (p_testClass)
p_testClass->getAllTests(testsMap_);
}
void Microservice_TestHandler::addTest(std::string testName, nsMicroservice_Iface::TestFunction &testFunction) {
if (!testName.empty() && testFunction != nullptr)
testsMap_[testName] = testFunction;
}
//
// Created by amir on 19/04/17.
//
#ifndef MICROSERVICE_MICROSERVICE_TESTHANDLER_H
#define MICROSERVICE_MICROSERVICE_TESTHANDLER_H
#include "Microservice_RestHandler.h"
/**
* @author amir
* @brief handler used to perform test when the microservice is running with
* it's rest interface
*/
class Microservice_TestHandler : public virtual Microservice_RestHandler{
public:
static constexpr const char* PREFIX = "/_tests";
void DoCreate(cMicroservice_RequestContext *pc_reqCtx) override;
void DoRead(cMicroservice_RequestContext *pc_reqCtx) override;
void DoUpdate(cMicroservice_RequestContext *pc_reqCtx) override;
void DoDelete(cMicroservice_RequestContext *pc_reqCtx) override;
void Init() override;
void addTest(nsMicroservice_Iface::ITest* p_testClass);
void addTest(std::string testName,nsMicroservice_Iface::TestFunction& testFunction);
private:
nsMicroservice_Iface::TestsMap testsMap_;
};
#endif //MICROSERVICE_MICROSERVICE_TESTHANDLER_H
...@@ -21,7 +21,15 @@ using namespace nsMicroservice_Iface; ...@@ -21,7 +21,15 @@ using namespace nsMicroservice_Iface;
using OnResponseFunc = std::function<void(const char* p_response, int len, std::uint32_t cmndId)>; using OnResponseFunc = std::function<void(const char* p_response, int len, std::uint32_t cmndId)>;
/**
* @brief RestCleient over ZMQ:
* Impelmenting by using 2 zmq sockets, one for send and one for receive
* also using a cache for storing the callbacks for the requests
* because the async mechanism of the microservice client is build upon an
* async task over a blocking operation.
* to achieve that i used a conditional with mutex to create a blocking operation
* that orchestrate the send/receive sockets
*/
class MSICommandClientZmqImpl : public ICommandClient { class MSICommandClientZmqImpl : public ICommandClient {
struct RcidParts { struct RcidParts {
...@@ -85,8 +93,6 @@ private: ...@@ -85,8 +93,6 @@ private:
void DelegateRestResponse(cMicroservice_BaseRestResponse *p_RestResponse, uint32_t cmndId); void DelegateRestResponse(cMicroservice_BaseRestResponse *p_RestResponse, uint32_t cmndId);
void HandleCommandAndCallback(ICommandClient::HttpCommandDataPtr &cmdDataPtr,common::context::CrudMethod crudMethod); void HandleCommandAndCallback(ICommandClient::HttpCommandDataPtr &cmdDataPtr,common::context::CrudMethod crudMethod);
//public:
// bool supportAsync() override { return true; }
}; };
......
...@@ -191,7 +191,7 @@ void Microservice_IRestServerZmqImpl::HandleNewRequest(Microservice_IRestServerZ ...@@ -191,7 +191,7 @@ void Microservice_IRestServerZmqImpl::HandleNewRequest(Microservice_IRestServerZ
void Microservice_IRestServerZmqImpl::SendNotImplemented(Microservice_IRestServerZmqImpl::RequestWorkParams *p_rwp) { void Microservice_IRestServerZmqImpl::SendNotImplemented(Microservice_IRestServerZmqImpl::RequestWorkParams *p_rwp) {
SendErrorResp(&p_rwp->restResponseImpl_,"Not Implemented"); SendErrorResp(&p_rwp->restResponseImpl_, nsMicroservice_Constants::NOT_IMPLEMENTED);
} }
MSRetStat Microservice_IRestServerZmqImpl::ParseRequest(Microservice_IRestServerZmqImpl::RequestWorkParams *p_rwp, MSRetStat Microservice_IRestServerZmqImpl::ParseRequest(Microservice_IRestServerZmqImpl::RequestWorkParams *p_rwp,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
static const int HIGH_WATER_MARK = 10000; static const int HIGH_WATER_MARK = 10000;
#include <common/Microservice_Iface.h> #include <common/Microservice_Iface.h>
#include <zmqpp/socket.hpp> #include <zmqpp/socket.hpp>
#include <params/Microservice_Params.h> #include <params/Microservice_Params.h>
......
...@@ -335,7 +335,6 @@ void runRestZmqTest(){ ...@@ -335,7 +335,6 @@ void runRestZmqTest(){
std::string appName("myZmqService"); std::string appName("myZmqService");
Microservice_App msApp(appName.c_str()); Microservice_App msApp(appName.c_str());
/** /**
* Start server * Start server
*/ */
...@@ -344,19 +343,25 @@ void runRestZmqTest(){ ...@@ -344,19 +343,25 @@ void runRestZmqTest(){
.withMonitoring() // need to add reload .withMonitoring() // need to add reload
.withPubSub(NULL) .withPubSub(NULL)
.withServiceDiscovery(NULL) .withServiceDiscovery(NULL)
.addServer(ServerFactory::createIRestServerCivetWebImpl("", 50010, 1))
.addServer(ServerFactory::createIRestServerZmqImpl("serverApp",0,Microservice_ZMQServerParams::eProtocol::eIpc)) .addServer(ServerFactory::createIRestServerZmqImpl("serverApp",0,Microservice_ZMQServerParams::eProtocol::eIpc))
.addTest("SendZmqRestRequests", [&msApp,&appName](std::stringstream& output,DequeStringMap& queryParams) -> MSRetStat {
auto p_zmqClient = ClientFactory::createZmqCommandImpl(appName,"clientApp", 0,"serverApp", 0,Microservice_ZMQServerParams::eProtocol::eIpc);
output <<" Testing " << ITERATIONS << " SendZmqRestRequests took: " << CommonUtils::measureFunc<>(SendZmqRestRequests,msApp, p_zmqClient) << "msec" << '\n';
return MSRetStat();
})
.addTest("testCaches",[&msApp,&appName](std::stringstream& output,DequeStringMap& queryParams) -> MSRetStat {
Poco::ExpireCache<uint64_t , string> cache;
output<<" Testing " << ITERATIONS << " testCaches took: " << CommonUtils::measureFunc<>(testPoco,cache) << "msec" << '\n';
output <<" Testing " << ITERATIONS << " testMap took: " << CommonUtils::measureFunc<>(testMap) << "msec" << '\n';
return MSRetStat();
})
.build(); .build();
/** /**
* start client * start client
*/ */
msApp.GetLogger()->setLevel(cMicroservice_Enums::eError); msApp.GetLogger()->setLevel(cMicroservice_Enums::eError);
auto p_zmqClient = ClientFactory::createZmqCommandImpl(appName,"clientApp", 0,"serverApp", 0,Microservice_ZMQServerParams::eProtocol::eIpc);
auto p_clientSendThread_ = new std::thread(std::bind([p_zmqClient,&msApp](){
std::cout <<" Testing " << ITERATIONS << " testCaches took: " << CommonUtils::measureFunc<>(SendZmqRestRequests,msApp, p_zmqClient) << "msec" << '\n';
}));
msApp.run(); msApp.run();
getchar(); getchar();
} }
...@@ -402,7 +407,7 @@ void SendZmqRestRequests(const Microservice_App &msApp, cMicroservice_Client *p_ ...@@ -402,7 +407,7 @@ void SendZmqRestRequests(const Microservice_App &msApp, cMicroservice_Client *p_
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
runRestZmqTest(); runRestZmqTest();
//testCaches(); // testCaches();
// testJsons(); // testJsons();
//runTest(); //runTest();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment