From d723d5bf571eb48c641b092058eaa38bb6c4fcc8 Mon Sep 17 00:00:00 2001 From: Eduardo Ramos Testillano Date: Wed, 15 Feb 2017 17:01:40 +0100 Subject: [PATCH] Testing library separation: now not in launcher but isolated --- SConstruct | 3 + dynamic/launcher/default/Procedure.cpp | 5 +- dynamic/launcher/default/Procedure.hpp | 9 +- dynamic/launcher/gx/00001/CCR-I.xml | 48 +++ dynamic/launcher/gx/00001/CCR-T.xml | 13 + dynamic/launcher/gx/00001/Procedure.cpp | 268 +++++++++++++- dynamic/launcher/gx/00001/Procedure.hpp | 9 +- dynamic/launcher/gx/00001/dynamic.suffix | 23 ++ example/diameter/launcher/DEPLOY.sh | 2 + example/diameter/launcher/Launcher.cpp | 107 ++++-- example/diameter/launcher/Launcher.hpp | 31 +- .../diameter/launcher/MyDiameterEngine.cpp | 49 --- .../diameter/launcher/MyDiameterEngine.hpp | 4 - .../diameter/launcher/MyDiameterEntity.cpp | 68 +--- .../diameter/launcher/MyDiameterEntity.hpp | 24 +- example/diameter/launcher/MyLocalServer.cpp | 28 +- example/diameter/launcher/MyLocalServer.hpp | 7 +- example/diameter/launcher/SConscript | 10 +- .../deployments/st-client/checkStatus.sh | 29 ++ .../deployments/st-client/configure.sh | 71 ++-- .../deployments/st-client/launchCPS.sh | 41 +++ .../deployments/st-client/operation_all.sh | 11 +- .../launcher/deployments/st-client/program.sh | 335 +++++++++++++----- .../launcher/deployments/st-client/run_all.sh | 42 ++- include/anna/diameter.comm/Engine.hpp | 23 +- include/anna/diameter.comm/Entity.hpp | 54 ++- .../anna/diameter.comm}/OriginHost.hpp | 56 ++- include/anna/diameter/codec/Message.hpp | 1 + .../anna/diameter/codec/MessagesDeque.hpp | 37 +- .../anna}/testing/TestCase.hpp | 29 +- .../anna}/testing/TestClock.hpp | 11 +- .../anna}/testing/TestCondition.hpp | 36 +- .../anna}/testing/TestManager.hpp | 29 +- .../anna}/testing/TestStep.hpp | 27 +- .../anna}/testing/TestTimer.hpp | 11 +- include/anna/testing/defines.hpp | 18 + source/diameter.comm/Engine.cpp | 50 ++- source/diameter.comm/Entity.cpp | 31 +- source/diameter.comm/LocalServer.cpp | 4 +- .../diameter.comm}/OriginHost.cpp | 51 ++- source/diameter.comm/Server.cpp | 4 +- .../diameter/codec/MessagesDeque.cpp | 36 +- source/testing/SConscript | 8 + source/testing/SConstruct | 12 + .../launcher => source}/testing/TestCase.cpp | 14 +- .../launcher => source}/testing/TestClock.cpp | 6 +- .../testing/TestCondition.cpp | 34 +- .../testing/TestManager.cpp | 52 +-- .../launcher => source}/testing/TestStep.cpp | 26 +- .../launcher => source}/testing/TestTimer.cpp | 10 +- 50 files changed, 1299 insertions(+), 608 deletions(-) create mode 100644 dynamic/launcher/gx/00001/CCR-I.xml create mode 100644 dynamic/launcher/gx/00001/CCR-T.xml create mode 100644 dynamic/launcher/gx/00001/dynamic.suffix delete mode 100644 example/diameter/launcher/MyDiameterEngine.cpp create mode 100755 example/diameter/launcher/deployments/st-client/checkStatus.sh create mode 100755 example/diameter/launcher/deployments/st-client/launchCPS.sh rename {example/diameter/launcher => include/anna/diameter.comm}/OriginHost.hpp (76%) rename example/diameter/launcher/ProgrammedAnswers.hpp => include/anna/diameter/codec/MessagesDeque.hpp (76%) rename {example/diameter/launcher => include/anna}/testing/TestCase.hpp (89%) rename {example/diameter/launcher => include/anna}/testing/TestClock.hpp (88%) rename {example/diameter/launcher => include/anna}/testing/TestCondition.hpp (78%) rename {example/diameter/launcher => include/anna}/testing/TestManager.hpp (89%) rename {example/diameter/launcher => include/anna}/testing/TestStep.hpp (95%) rename {example/diameter/launcher => include/anna}/testing/TestTimer.hpp (92%) create mode 100644 include/anna/testing/defines.hpp rename {example/diameter/launcher => source/diameter.comm}/OriginHost.cpp (89%) rename example/diameter/launcher/ProgrammedAnswers.cpp => source/diameter/codec/MessagesDeque.cpp (78%) create mode 100644 source/testing/SConscript create mode 100644 source/testing/SConstruct rename {example/diameter/launcher => source}/testing/TestCase.cpp (97%) rename {example/diameter/launcher => source}/testing/TestClock.cpp (82%) rename {example/diameter/launcher => source}/testing/TestCondition.cpp (86%) rename {example/diameter/launcher => source}/testing/TestManager.cpp (91%) rename {example/diameter/launcher => source}/testing/TestStep.cpp (97%) rename {example/diameter/launcher => source}/testing/TestTimer.cpp (93%) diff --git a/SConstruct b/SConstruct index e223dd8..a163297 100644 --- a/SConstruct +++ b/SConstruct @@ -64,6 +64,9 @@ env.Append (CPPPATH = [source_include, usr_local_include, usr_include ]) #env.Append (CCFLAGS = '-std=c++0x') # C++11 support: env.Append (CXXFLAGS = '-std=c++11') +# Shared libraries using static ones: +env.Append (CXXFLAGS = '-fPIC') +#env.Append (CXXFLAGS = '-export-dynamic') env.Append (LIBS = ['']) # scons -Q release=1 diff --git a/dynamic/launcher/default/Procedure.cpp b/dynamic/launcher/default/Procedure.cpp index 57bb7e0..62b0ce2 100644 --- a/dynamic/launcher/default/Procedure.cpp +++ b/dynamic/launcher/default/Procedure.cpp @@ -9,11 +9,14 @@ #include #include +// Project +#include + // Local #include "Procedure.hpp" -void Procedure::execute(const std::string &args, std::string &response) throw() { +void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException) { response = "Empty default implementation. Make dynamic library and reimplement this method."; if (args != "" ) { response += " Provided argument(s) ignored: "; diff --git a/dynamic/launcher/default/Procedure.hpp b/dynamic/launcher/default/Procedure.hpp index 91247a3..c96ab07 100644 --- a/dynamic/launcher/default/Procedure.hpp +++ b/dynamic/launcher/default/Procedure.hpp @@ -13,6 +13,13 @@ #include +namespace anna { + namespace diameter { + namespace comm { + class OriginHost; + } + } +} class Procedure { anna::comm::Application *a_app; @@ -20,7 +27,7 @@ class Procedure { public: Procedure(anna::comm::Application *app) : a_app(app) {;} - virtual void execute(const std::string &args, std::string &response) throw(); + virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException); }; #endif diff --git a/dynamic/launcher/gx/00001/CCR-I.xml b/dynamic/launcher/gx/00001/CCR-I.xml new file mode 100644 index 0000000..a57ef6d --- /dev/null +++ b/dynamic/launcher/gx/00001/CCR-I.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynamic/launcher/gx/00001/CCR-T.xml b/dynamic/launcher/gx/00001/CCR-T.xml new file mode 100644 index 0000000..ac44202 --- /dev/null +++ b/dynamic/launcher/gx/00001/CCR-T.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dynamic/launcher/gx/00001/Procedure.cpp b/dynamic/launcher/gx/00001/Procedure.cpp index 62975c1..63b4ef1 100644 --- a/dynamic/launcher/gx/00001/Procedure.cpp +++ b/dynamic/launcher/gx/00001/Procedure.cpp @@ -9,15 +9,273 @@ #include #include +// Project +#include +#include +#include +#include +#include +#include +#include +#include // Local #include "Procedure.hpp" -void Procedure::execute(const std::string &args, std::string &response) throw() { - response = "00001 Empty default implementation. Make dynamic library and reimplement this method."; - if (args != "" ) { - response += " Provided argument(s) ignored: "; - response += args; +namespace { + + void usage (std::string &response) { + response += "\n\nInvalid arguments. Provide these ones:"; + response += "\n"; + response += "\n|||[|CCR-T xml file]"; + response += "\n"; + response += "\nSequences are parsed when needed, over AVPs or internal values:"; + response += "\n"; + response += "\nSession-Id: ;;[;]"; + response += "\n \\_fixed_/\\_digits_/ \\_fixed_/\\_digits_/"; + response += "\n"; + response += "\nFor example, imagine a 13-digits diameter identity, and a 10-digits optional part."; + response += "\nThis procedure will sequence the range for 8 digits in this way:"; + response += "\n"; + response += "\n111111<7-digit-sequence>;BAT004;esmdx0900.gxrel10plusrealm.com;901<7-digit-sequence>"; + response += "\n"; + response += "\nThe same will be done in MSISDN and IMSI (Subscription-Data AVPs)."; + response += "\nFramed-IP-Address will be sequenced with a direct correspondence to hex value."; + response += "\n"; + response += "\nThen, you could provide these arguments: \"5000|2000000|9000000|7|CCR-I.xml|CCR-T.xml\""; + response += "\n"; + } +} + +void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException) { + + response = "Dynamic procedure failed to process '"; response += args; response += "': "; + + anna::Tokenizer targs; + targs.apply(args, "|"); + + if (targs.size() < 5) { + usage(response); + return; + } + + anna::Tokenizer::const_iterator tok_it = targs.begin(); + + std::string seq_i = anna::Tokenizer::data(tok_it); tok_it++; + std::string seq_f = anna::Tokenizer::data(tok_it); tok_it++; + std::string timeout = anna::Tokenizer::data(tok_it); tok_it++; + std::string digits = anna::Tokenizer::data(tok_it); tok_it++; + std::string ccr_i = anna::Tokenizer::data(tok_it); tok_it++; + std::string ccr_t = ((tok_it != targs.end()) ? anna::Tokenizer::data(tok_it):""); + bool haveTermination = (ccr_t != ""); + + // Test cases cycles: + int i_timeout = std::atoi(timeout.c_str()); + unsigned int ll_seq_i = std::atol(seq_i.c_str()); + unsigned int ll_seq_f = std::atol(seq_f.c_str()); + unsigned int ll_seq_size = ll_seq_f - ll_seq_i + 1; + int i_digits = std::atoi(digits.c_str()); + + if (ll_seq_i > ll_seq_f) { + response += " must be greater or equal than "; + return; + } + + if (seq_f.size() > i_digits) { + response += " must be lesser than number of "; + return; + } + + unsigned int ll_seq, ll_index; + anna::Millisecond timeoutMS(i_timeout); + + // Load xml messages: + anna::diameter::codec::Message ccri, ccrt; + anna::diameter::codec::Avp *ccri_sessionId, *ccrt_sessionId, *ccri_framedIPAddress, *ccrt_framedIPAddress, *ccri_msisdn, *ccri_imsi; + anna::diameter::codec::Avp *si1, *si2, *sidata1, *sidata2, *sitype1, *sitype2; + + try { + + ///////// CCR-Initial: + ccri.loadXML(ccr_i); + + // Session-Id & Framed-Ip-Address AVPs + ccri_sessionId = ccri.getAvp("Session-Id"); + ccri_framedIPAddress = ccri.getAvp("Framed-IP-Address"); + + // Subscription-Id AVPs + if (ccri.countAvp("Subscription-Id") != 2) { + response += "Both Subscription-Id MSISDN & IMSI Avps must be present in the CCR-Initial provided !"; + return; + } + + si1 = ccri.getAvp("Subscription-Id", 1, anna::Exception::Mode::Ignore); + si2 = ccri.getAvp("Subscription-Id", 2, anna::Exception::Mode::Ignore); + + if (!si1 || !si2) { + response += "Cannot found Subscription-Id MSISDN & IMSI Avps !" ; + return; + } + + sidata1 = si1->getAvp("Subscription-Id-Data"); + sidata2 = si2->getAvp("Subscription-Id-Data"); + sitype1 = si1->getAvp("Subscription-Id-Type"); + //sitype2 = si2->getAvp("Subscription-Id-Type"); + + if (sitype1->getEnumerated()->getValue() == anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164) { + ccri_msisdn = sidata1; + ccri_imsi = sidata2; + } + else { + ccri_msisdn = sidata2; + ccri_imsi = sidata1; + } + + ///////// CCR-Termination: + if (haveTermination) { + ccrt.loadXML(ccr_t); + + // Session-Id & Framed-Ip-Address AVPs + ccrt_sessionId = ccrt.getAvp("Session-Id"); + ccrt_framedIPAddress = ccrt.getAvp("Framed-IP-Address"); + } + } + catch(anna::RuntimeException &ex) { + ex.trace(); + } + + // Prepare session-id string: + std::string sessionId = ccri_sessionId->getUTF8String()->getValue(); + std::size_t last_semicolon = sessionId.rfind(";"); + anna::Tokenizer tsessionid; + tsessionid.apply(sessionId, ";"); + + if (tsessionid.size() < 4) { + response += "Session-Id must be in form ';;;'.\n\n"; + usage(response); + return; + } + + tok_it = tsessionid.begin(); + std::string d_identity = anna::Tokenizer::data(tok_it); tok_it++; tok_it++; tok_it++; + std::string o_part = anna::Tokenizer::data(tok_it); + int d_identity_len = d_identity.size(); + int left_di = d_identity_len - i_digits; + if (left_di < 0) { + response += "Session-Id diameter identity length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", d_identity_len, i_digits); + usage(response); + return; + } + int o_part_len = o_part.size(); + int left_op = o_part_len - i_digits; + if (left_op < 0) { + response += "Session-Id optional part length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", o_part_len, i_digits); + usage(response); + return; + } + + // Idem for MSISDN & IMSI Subscription-Data: + std::string msisdn = ccri_msisdn->getUTF8String()->getValue(); + int msisdn_len = msisdn.size(); + int left_msisdn = msisdn_len - i_digits; + if (left_msisdn < 0) { + response += "MSISDN Subscription-Data length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", left_msisdn, i_digits); + usage(response); + return; } + std::string imsi = ccri_imsi->getUTF8String()->getValue(); + int imsi_len = imsi.size(); + int left_imsi = imsi_len - i_digits; + if (left_imsi < 0) { + response += "IMSI Subscription-Data length is lower than selected number of digits "; + response += anna::functions::asString("(%d < %d).\n\n", left_imsi, i_digits); + usage(response); + return; + } + + + // Format strings: + char ndigit_format[32]; + sprintf(ndigit_format, "%s%d%s", "%0", i_digits, "u"); + + //response += "\nSession-Id original: "; response += sessionId; + //response += "\nMSISDN original: "; response += msisdn; + //response += "\nIMSI original: "; response += imsi; + + // TestManager: + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); + char cad_aux[16]; + char cad_framed[16]; + anna::testing::TestCase *tc; + + for (ll_index = 0; ll_index < ll_seq_size; ll_index++) { + + // Calculate next values //////////////////////////////////////////////////////////// + ll_seq = ll_seq_i + ll_index; + sprintf(cad_aux, ndigit_format, ll_seq); + sprintf(cad_framed, "%08x", ll_seq); + + // Activity indicator: + if (ll_seq % 10000 == 0) std::cout << "."; + + sessionId.replace(left_di, i_digits, cad_aux); + sessionId.replace(last_semicolon + left_op + 1, i_digits, cad_aux); + + msisdn.replace(left_msisdn, i_digits, cad_aux); + + imsi.replace(left_imsi, i_digits, cad_aux); + + //response += "\nSession-Id modified: "; response += sessionId; + //response += "\nMSISDN modified: "; response += msisdn; + //response += "\nIMSI modified: "; response += imsi; + //response += "\nFramedIP modified: "; response += cad_framed; + + // Update diameter messages ///////////////////////////////////////////////////////// + ccri_sessionId->getUTF8String()->setValue(sessionId); + ccri_framedIPAddress->getOctetString()->fromHexString(cad_framed); + ccri_msisdn->getUTF8String()->setValue(msisdn); + ccri_imsi->getUTF8String()->setValue(imsi); + + if (haveTermination) { + ccrt_sessionId->getUTF8String()->setValue(sessionId); + ccrt_framedIPAddress->getOctetString()->fromHexString(cad_framed); + } + + // Create testcase: + tc = testManager.getTestCase(ll_index+1); + // test|__TESTID__|timeout|6000 + // test|__TESTID__|sendxml2e|ccr-i.xml + // test|__TESTID__|waitfe|272|0|||11111__SEQ8__;BAT004;esmdx0900.gxrel10plusrealm.com;90__SEQ8__|2001 + // test|__TESTID__|sendxml2e|ccr-t.xml + // test|__TESTID__|waitfe|272|0|||11111__SEQ8__;BAT004;esmdx0900.gxrel10plusrealm.com;90__SEQ8__|2001 + + if (i_timeout != 0) { + // Step 1: timeout 5000 ms: + tc->addTimeout(timeoutMS); + } + + // Step 2: sendxml2e: CCR-Initial + tc->addSendxml2e(ccri.code(), originHost, -1 /* 'wait for request' step number for answers */); + + // Step 3: waitfe: CCA with same session id + // PARAM: 1 2 3 4 5 6 7 8 9 10 11 + // wait|[code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId] + tc->addWait(true /* from entity */, "272", "0", "", "", sessionId, "2001", "", "", ""); + + if (haveTermination) { + // Step 4: sendxml2e: CCR-Termination + tc->addSendxml2e(ccrt.code(), originHost, -1 /* 'wait for request' step number for answers */); + + // Step 5: waitfe: CCA with same session id + tc->addWait(true /* from entity */, "272", "0", "", "", sessionId, "2001", "", "", ""); + } + } // loop + + response = "Completed provision for pid "; response += anna::functions::asString(a_app->getPid()); response += "; range ["; + response += seq_i; response += ", "; response += seq_f; response += "]; scenary: "; + response += "CCR-Initial"; if (haveTermination) response += " + CCR-Termination"; } diff --git a/dynamic/launcher/gx/00001/Procedure.hpp b/dynamic/launcher/gx/00001/Procedure.hpp index 884cad5..b46ef74 100644 --- a/dynamic/launcher/gx/00001/Procedure.hpp +++ b/dynamic/launcher/gx/00001/Procedure.hpp @@ -13,6 +13,13 @@ #include +namespace anna { + namespace diameter { + namespace comm { + class OriginHost; + } + } +} class Procedure { anna::comm::Application *a_app; @@ -20,7 +27,7 @@ class Procedure { public: Procedure(anna::comm::Application *app) : a_app(app) {;} - virtual void execute(const std::string &args, std::string &response) throw(); + virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException); }; #endif diff --git a/dynamic/launcher/gx/00001/dynamic.suffix b/dynamic/launcher/gx/00001/dynamic.suffix new file mode 100644 index 0000000..97afc7f --- /dev/null +++ b/dynamic/launcher/gx/00001/dynamic.suffix @@ -0,0 +1,23 @@ +# Procedure arguments: +# +# ||[|CCR-Termination path file>] +# +# is the first step to control the test cases execution. A value of 0 omits +# this first step (good to avoid huge load of timers during high performance testing). +# +# All the tests not fulfilled (those where the corresponding answers are not received) +# will be eternally keep 'in-progress' state. You could consider them failed after +# a specific time. A non-zero timeout step will ensure that this situation is updated +# as failed on expiration. Diameter application request timeouts also expire but are +# not processed here (not neccessary because reception conditions are enough to block +# the flow when something is wrong). Anyway, you could check ADML counters executing +# the command: ./operation show-oam +# The main problem with a zeroed first timeout step, is that cycle repeats are not +# possible except if you reset the pool (hard reset) when close to finish, something +# very dificult to monitor. + +# Only CCR-Initial: +5000|7|CCR-I.xml + +# CCR-Initial + CCR-Termination: +5000|7|CCR-I.xml|CCR-T.xml diff --git a/example/diameter/launcher/DEPLOY.sh b/example/diameter/launcher/DEPLOY.sh index a314a30..72604a8 100755 --- a/example/diameter/launcher/DEPLOY.sh +++ b/example/diameter/launcher/DEPLOY.sh @@ -208,6 +208,8 @@ do dir=$(dirname $dl | xargs dirname) mkdir -p $DPATH/dynlibs/$dir cp $dir/$dynlib_variant/*.so $DPATH/dynlibs/$dir + cp $dir/*.xml $DPATH/dynlibs/$dir 2>/dev/null + cp $dir/dynamic.suffix $DPATH/dynlibs/$dir 2>/dev/null done cd - >/dev/null cp ./resources/scripts/select_dynlib.sh $DPATH/dynlibs/select.sh diff --git a/example/diameter/launcher/Launcher.cpp b/example/diameter/launcher/Launcher.cpp index aebebec..b141865 100644 --- a/example/diameter/launcher/Launcher.cpp +++ b/example/diameter/launcher/Launcher.cpp @@ -24,15 +24,16 @@ #include #include #include +#include #include #include // Process #include -#include #include -#include -#include +#include +#include +#include #define SIGUSR2_TASKS_INPUT_FILENAME "sigusr2.in" @@ -326,11 +327,24 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp // Checking command line parameters std::string sessionBasedModelsType; + anna::diameter::comm::Entity::SessionBasedModelsType::_v sessionBasedModelsTypeEnum; if(sessionBasedModelsClientSocketSelection) { sessionBasedModelsType = sessionBasedModelsClientSocketSelection->getValue(); - if((sessionBasedModelsType != "SessionIdHighPart") && (sessionBasedModelsType != "SessionIdOptionalPart") && (sessionBasedModelsType != "RoundRobin")) { - throw anna::RuntimeException("Parameter 'sessionBasedModelsClientSocketSelection' only accepts 'SessionIdHighPart'/'SessionIdOptionalPart'/'RoundRobin' as parameter values", ANNA_FILE_LOCATION); - } + if (sessionBasedModelsType == "RoundRobin") { + sessionBasedModelsTypeEnum = anna::diameter::comm::Entity::SessionBasedModelsType::RoundRobin; + } + else if (sessionBasedModelsType == "SessionIdOptionalPart") { + sessionBasedModelsTypeEnum = anna::diameter::comm::Entity::SessionBasedModelsType::SessionIdOptionalPart; + } + else if (sessionBasedModelsType == "SessionIdHighPart") { + sessionBasedModelsTypeEnum = anna::diameter::comm::Entity::SessionBasedModelsType::SessionIdHighPart; + } + else if (sessionBasedModelsType == "SessionIdLowPart") { + sessionBasedModelsTypeEnum = anna::diameter::comm::Entity::SessionBasedModelsType::SessionIdLowPart; + } + else { + throw anna::RuntimeException("Parameter 'sessionBasedModelsClientSocketSelection' only accepts 'SessionIdLowPart'/'SessionIdHighPart'/'SessionIdOptionalPart'/'RoundRobin' as parameter values", ANNA_FILE_LOCATION); + } } int retransmissions = retries ? retries->getIntegerValue() : 0; @@ -338,19 +352,21 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp throw anna::RuntimeException("Parameter 'retries' must be non-negative", ANNA_FILE_LOCATION); } - // Create new Node instance ///////////////////////////////////////////////////////////////// - a_workingNode = new OriginHost(originHost->getValue(), applicationId, bpd); - MyDiameterEngine *commEngine = a_workingNode->getMyDiameterEngine(); ///////////////////////////////////////////////////////////////////////////////////////////// - - // Assignments: + // Diameter communication engine: + std::string commEngineName = originHost->getValue() + "_DiameterCommEngine"; + MyDiameterEngine *commEngine = new MyDiameterEngine(commEngineName.c_str(), bpd); + commEngine->setAutoBind(false); // allow to create client-sessions without binding them, in order to set timeouts. commEngine->setMaxConnectionDelay(tcpConnectDelayMs); commEngine->setWatchdogPeriod(watchdogPeriodMs); + commEngine->setOriginHostName(originHost->getValue()); + if (originRealm) commEngine->setOriginRealmName(originRealm->getValue()); + + // Origin host node: + a_workingNode = new anna::diameter::comm::OriginHost((anna::diameter::comm::Engine*)commEngine, applicationId); a_workingNode->setRequestRetransmissions(retransmissions); + ///////////////////////////////////////////////////////////////////////////////////////////// - // Realm information: - commEngine->setOriginHost(originHost->getValue()); - if (originRealm) commEngine->setOriginRealm(originRealm->getValue()); // Diameter entity: if(entity) { @@ -367,7 +383,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp // Register one entity for this engine: a_workingNode->createEntity(entity->getValue(), ceaTimeoutMs, answersTimeoutMs); - a_workingNode->getEntity()->setSessionBasedModelsType(sessionBasedModelsType); + a_workingNode->getEntity()->setSessionBasedModelsType(sessionBasedModelsTypeEnum); a_workingNode->getEntity()->setBalance(balance ? (balance->getValue() == "yes") : false); // for sendings if (eventOperation) a_workingNode->getEntity()->bind(); } @@ -379,12 +395,12 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp std::string ceaPathfile = cea ? cea->getValue() : ""; int sessions = diameterServerSessions ? diameterServerSessions->getIntegerValue() : 1; - a_workingNode->startDiameterServer(diameterServer->getValue(), sessions, allowedInactivityTimeMs, answersTimeoutMs, ceaPathfile); + a_workingNode->createDiameterServer(diameterServer->getValue(), sessions, allowedInactivityTimeMs, answersTimeoutMs, ceaPathfile); } // Logs: if (!allLogsDisabled) { - std::string host = commEngine->getOriginHost(); + std::string host = commEngine->getOriginHostName(); std::string s_log = host + ".launcher.log"; if (log) s_log = log->getValue(); bool b_splitLog = (splitLog ? (splitLog->getValue() == "yes") : false); bool b_detailedLog = (detailedLog ? (detailedLog->getValue() == "yes") : false); @@ -505,20 +521,20 @@ bool Launcher::setWorkingNode(const std::string &name) throw() { ); } else { - a_workingNode = const_cast(nodeIt->second); + a_workingNode = const_cast(nodeIt->second); result = true; } return result; } -OriginHost *Launcher::getOriginHost(const std::string &oh) const throw(anna::RuntimeException) { +anna::diameter::comm::OriginHost *Launcher::getOriginHost(const std::string &oh) const throw(anna::RuntimeException) { origin_hosts_it it = a_originHosts.find(oh); if (it != a_originHosts.end()) return it->second; throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", oh.c_str()), ANNA_FILE_LOCATION); } -OriginHost *Launcher::getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException) { +anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException) { std::string originHost = message.getAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->getValue(); return (getOriginHost(originHost)); } @@ -528,7 +544,14 @@ void Launcher::updateOperatedOriginHostWithMessage(const anna::diameter::codec:: a_operatedHost = getOriginHost(message); } -OriginHost *Launcher::getOperatedHost() const throw(anna::RuntimeException) { +anna::diameter::comm::OriginHost *Launcher::getWorkingNode() const throw(anna::RuntimeException) { + if(!a_workingNode) + throw anna::RuntimeException("Working node not identified (try to load services)", ANNA_FILE_LOCATION); + + return a_workingNode; +} + +anna::diameter::comm::OriginHost *Launcher::getOperatedHost() const throw(anna::RuntimeException) { if(!a_operatedHost) throw anna::RuntimeException("Node not identified (try to force a specific Origin-Host with 'node' operation)", ANNA_FILE_LOCATION); @@ -536,21 +559,21 @@ OriginHost *Launcher::getOperatedHost() const throw(anna::RuntimeException) { } MyDiameterEntity *Launcher::getOperatedEntity() const throw(anna::RuntimeException) { - MyDiameterEntity *result = getOperatedHost()->getEntity(); + MyDiameterEntity *result = (MyDiameterEntity *)(getOperatedHost()->getEntity()); if (!result) throw anna::RuntimeException("No entity configured for the operated node", ANNA_FILE_LOCATION); return result; } MyLocalServer *Launcher::getOperatedServer() const throw(anna::RuntimeException) { - MyLocalServer *result = getOperatedHost()->getDiameterServer(); + MyLocalServer *result = (MyLocalServer *)(getOperatedHost()->getDiameterServer()); if (!result) throw anna::RuntimeException("No local server configured for the operated node", ANNA_FILE_LOCATION); return result; } MyDiameterEngine *Launcher::getOperatedEngine() const throw(anna::RuntimeException) { - return getOperatedHost()->getMyDiameterEngine(); // never will be NULL + return (MyDiameterEngine *)getOperatedHost()->getCommEngine(); // never will be NULL } void Launcher::initialize() @@ -560,7 +583,7 @@ throw(anna::RuntimeException) { anna::comm::Communicator::WorkMode::_v workMode(anna::comm::Communicator::WorkMode::Single); a_communicator = new MyCommunicator(workMode); a_timeEngine = new anna::timex::Engine((anna::Millisecond)600000, a_admlMinResolution); - TestManager::instantiate().setTimerController(a_timeEngine); + anna::testing::TestManager::instantiate().setTimerController(a_timeEngine); // Counters record procedure: const char *varname = "cntRecordPeriod"; @@ -575,7 +598,7 @@ throw(anna::RuntimeException) { // Testing framework: std::string tmDir = "."; if(cl.exists("tmDir")) tmDir = cl.getValue("tmDir"); - TestManager::instantiate().setReportsDirectory(tmDir); + anna::testing::TestManager::instantiate().setReportsDirectory(tmDir); // Tracing: if(cl.exists("trace")) @@ -755,7 +778,7 @@ throw(anna::RuntimeException) { // Start client connections ////////////////////////////////////////////////////////////////////////////////// MyDiameterEntity *entity; for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) { - entity = it->second->getEntity(); + entity = (MyDiameterEntity *)(it->second->getEntity()); if (entity) entity->bind(); } @@ -796,11 +819,11 @@ bool Launcher::getDataBlockFromHexFile(const std::string &pathfile, anna::DataBl void Launcher::resetStatistics() throw() { if (a_workingNode) { - a_workingNode->getMyDiameterEngine()->resetStatistics(); + a_workingNode->getCommEngine()->resetStatistics(); } else { for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) { - it->second->getMyDiameterEngine()->resetStatistics(); + it->second->getCommEngine()->resetStatistics(); } } } @@ -1525,8 +1548,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons anna::diameter::codec::Message codecMsg; // auxiliary codec message // Singletons: - CommandLine& cl(anna::CommandLine::instantiate()); - TestManager &testManager = TestManager::instantiate(); + anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); /////////////////////////////////////////////////////////////////// @@ -1539,7 +1561,14 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons std::string args = ((operation.find("dynamic|") == 0) && (op_size > 8)) ? operation.substr(8) : ""; if (args == "" && op_size != 7) throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION); - p.execute(args, response_content); + try { + p.execute(args, response_content, getWorkingNode()); + } + catch(anna::RuntimeException &ex) { + ex.trace(); + response_content = ex.asString(); + return; + } return; } @@ -1789,7 +1818,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons try { if(getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); } } - bool success = getOperatedEntity()->send(msg, cl.exists("balance")); + bool success = getOperatedEntity()->send(msg); getOperatedHost()->releaseCommMessage(msg); // Detailed log: @@ -2033,7 +2062,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION); int id = ((param2 != "") ? atoi(param2.c_str()) : -1); - TestCase *testCase = testManager.findTestCase(id); + anna::testing::TestCase *testCase = testManager.findTestCase(id); if (testCase) { response_content = testCase->asXMLString(); @@ -2059,7 +2088,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons throw anna::RuntimeException("Interactive amount must be -1 (to disable interactive mode) or a positive number.", ANNA_FILE_LOCATION); int id = atoi(param3.c_str()); - TestCase *testCase = testManager.findTestCase(id); + anna::testing::TestCase *testCase = testManager.findTestCase(id); if (testCase) { if (amount == -1) { testCase->makeInteractive(false); @@ -2090,7 +2119,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION); int id = ((param3 != "") ? atoi(param3.c_str()) : -1); - TestCase *testCase = ((id != -1) ? testManager.findTestCase(id) : NULL); + anna::testing::TestCase *testCase = ((id != -1) ? testManager.findTestCase(id) : NULL); if (testCase) { bool done = testCase->reset((param2 == "hard") ? true:false); @@ -2259,7 +2288,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons } else if (param1 == "clear") { getOperatedServer()->getReactingAnswers()->clear(); } else if (param1 == "dump") { - getOperatedServer()->getReactingAnswers()->dump(); + getOperatedServer()->getReactingAnswers()->dump("programmed_answer"); } else { codecMsg.loadXML(param1); updateOperatedOriginHostWithMessage(codecMsg); @@ -2285,7 +2314,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons } else if (param1 == "clear") { getOperatedEntity()->getReactingAnswers()->clear(); } else if (param1 == "dump") { - getOperatedEntity()->getReactingAnswers()->dump(); + getOperatedEntity()->getReactingAnswers()->dump("programmed_answer"); } else { codecMsg.loadXML(param1); updateOperatedOriginHostWithMessage(codecMsg); @@ -2333,7 +2362,7 @@ throw() { statsAsXML(result); // Testing: could be heavy if test case reports are enabled - TestManager::instantiate().asXML(result); + anna::testing::TestManager::instantiate().asXML(result); return result; } diff --git a/example/diameter/launcher/Launcher.hpp b/example/diameter/launcher/Launcher.hpp index dcc684d..2d5b3a7 100644 --- a/example/diameter/launcher/Launcher.hpp +++ b/example/diameter/launcher/Launcher.hpp @@ -23,12 +23,7 @@ // Process #include #include -#include - - -#define SH_COMMAND_TAG_FOR_REPLACE__CYCLE_ID "##cycleid##" -#define SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID "##testcaseid##" -#define SH_COMMAND_TAG_FOR_REPLACE__TESTSTEP_ID "##teststepid##" +#include namespace anna { @@ -39,20 +34,21 @@ namespace anna { namespace codec { class Engine; } + namespace comm { + class OriginHost; + } } } class TestManager; -class OriginHost; class MyDiameterEntity; class MyLocalServer; class MyDiameterEngine; // OriginHost resources -class OriginHost; -typedef std::map origin_hosts_t; -typedef std::map::const_iterator origin_hosts_it; -typedef std::map::iterator origin_hosts_nc_it; +typedef std::map origin_hosts_t; +typedef std::map::const_iterator origin_hosts_it; +typedef std::map::iterator origin_hosts_nc_it; class Launcher : public anna::comm::Application { @@ -70,14 +66,12 @@ class Launcher : public anna::comm::Application { // Nodes deployment: origin_hosts_t a_originHosts; - OriginHost *a_workingNode; - OriginHost *a_operatedHost; // auxiliary for eventOperation + anna::diameter::comm::OriginHost *a_workingNode; + anna::diameter::comm::OriginHost *a_operatedHost; // auxiliary for eventOperation // comm resources: anna::comm::ServerSocket* a_httpServerSocket; // HTTP - const anna::Millisecond &getADMLMinResolution() const throw() { return a_admlMinResolution; } - std::string getSignalUSR2InputFile() const throw(); std::string getSignalUSR2OutputFile() const throw(); @@ -96,13 +90,14 @@ public: void startServices() throw(anna::RuntimeException); bool setWorkingNode(const std::string &name) throw(); - OriginHost *getOriginHost(const std::string &oh) const throw(anna::RuntimeException); - OriginHost *getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getOriginHost(const std::string &oh) const throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException); bool uniqueOriginHost() const throw() { return (a_originHosts.size() == 1); } // Operated host for communication resources smart assignment //////////////////////////////////////////////////////////// void updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException); - OriginHost *getOperatedHost() const throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getWorkingNode() const throw(anna::RuntimeException); + anna::diameter::comm::OriginHost *getOperatedHost() const throw(anna::RuntimeException); MyDiameterEntity *getOperatedEntity() const throw(anna::RuntimeException); MyLocalServer *getOperatedServer() const throw(anna::RuntimeException); MyDiameterEngine *getOperatedEngine() const throw(anna::RuntimeException); diff --git a/example/diameter/launcher/MyDiameterEngine.cpp b/example/diameter/launcher/MyDiameterEngine.cpp deleted file mode 100644 index e5700c0..0000000 --- a/example/diameter/launcher/MyDiameterEngine.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// ANNA - Anna is Not Nothingness Anymore // -// // -// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // -// // -// See project site at http://redmine.teslayout.com/projects/anna-suite // -// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // - - -// Project -#include -#include - -//#include -//#include -//#include -//#include -//#include - -// Process -#include - - -void MyDiameterEngine::readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) throw() { - - LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEngine", "readCEA", ANNA_FILE_LOCATION)); - - // Default implementation: - if (a_ceaPathfile == "") - return anna::diameter::comm::Engine::readCEA(cea, cer); - -// if(codec::functions::getCommandId(cer) != helpers::base::COMMANDID__Capabilities_Exchange_Answer) { -//throw anna::RuntimeException("The message provided as 'CEA' is not a Capabilities-Exchange-Answer", -//} - - anna::diameter::codec::Message diameterCEA(getBaseProtocolCodecEngine()); - try { - diameterCEA.loadXML(a_ceaPathfile); - diameterCEA.setHopByHop(anna::diameter::codec::functions::getHopByHop(cer)); - diameterCEA.setEndToEnd(anna::diameter::codec::functions::getEndToEnd(cer)); - cea = diameterCEA.code(); - - } catch(anna::RuntimeException &ex) { - ex.trace(); - LOGWARNING(anna::Logger::warning("CEA file not found or unable to parse. Encoding harcoded default version ...", ANNA_FILE_LOCATION)); - //return anna::diameter::comm::Engine::readCEA(cea, cer); - // will fail with empty cea - } -} - diff --git a/example/diameter/launcher/MyDiameterEngine.hpp b/example/diameter/launcher/MyDiameterEngine.hpp index f304d0d..4fe049f 100644 --- a/example/diameter/launcher/MyDiameterEngine.hpp +++ b/example/diameter/launcher/MyDiameterEngine.hpp @@ -35,8 +35,6 @@ public: // Default implementation is enough // void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) throw() {;} // DPA is not replied - void setCEA(const std::string &ceaPathfile) throw() { a_ceaPathfile = ceaPathfile; } - void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) throw(); // void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) throw() {;} // DWA is not replied private: @@ -57,8 +55,6 @@ private: MyLocalServer* aux = static_cast (localServer); a_localServersRecycler.release(aux); } - - std::string a_ceaPathfile; // path file to optional CEA (diameter local server configuration) }; #endif diff --git a/example/diameter/launcher/MyDiameterEntity.cpp b/example/diameter/launcher/MyDiameterEntity.cpp index 5e78ab3..6027bf0 100644 --- a/example/diameter/launcher/MyDiameterEntity.cpp +++ b/example/diameter/launcher/MyDiameterEntity.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -20,8 +21,7 @@ #include #include #include -#include -#include +#include void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::ClientSession* clientSession, anna::diameter::comm::Message *request) throw() { @@ -33,7 +33,7 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(request->getBody()); LOGDEBUG @@ -52,54 +52,12 @@ void MyDiameterEntity::eventRequestRetransmission(const anna::diameter::comm::Cl } -int MyDiameterEntity::readSocketId(const anna::diameter::comm::Message* message, int maxClientSessions) const throw() { - - if(a_sessionBasedModelsType == "RoundRobin") return -1; // IEC also would return -1 - - try { - // Service-Context-Id: - anna::diameter::helpers::dcca::ChargingContext::_v chargingContext; - std::string scid = anna::diameter::helpers::dcca::functions::getServiceContextId(message->getBody(), chargingContext); - - switch(chargingContext) { - case anna::diameter::helpers::dcca::ChargingContext::Data: - case anna::diameter::helpers::dcca::ChargingContext::Voice: - case anna::diameter::helpers::dcca::ChargingContext::Content: { - // Session-Id: ';;[;="">]' - std::string sid = anna::diameter::helpers::base::functions::getSessionId(message->getBody()); - std::string diameterIdentity, optional; - anna::U32 high, low; - anna::diameter::helpers::base::functions::decodeSessionId(sid, diameterIdentity, high, low /* context-teid */, optional); - - if(a_sessionBasedModelsType == "SessionIdLowPart") return (low % maxClientSessions); - - if(a_sessionBasedModelsType == "SessionIdHighPart") return (high % maxClientSessions); - - if(a_sessionBasedModelsType == "SessionIdOptionalPart") return (atoi(optional.c_str()) % maxClientSessions); - } - case anna::diameter::helpers::dcca::ChargingContext::SMS: - case anna::diameter::helpers::dcca::ChargingContext::MMS: - case anna::diameter::helpers::dcca::ChargingContext::Unknown: - default: - return -1; // IEC model and Unknown traffic types - } - } catch(anna::RuntimeException &ex) { - LOGDEBUG( - std::string msg = ex.getText(); - msg += " | Round-robin between sessions will be used to send"; - anna::Logger::debug(msg, ANNA_FILE_LOCATION); - ); - } - - return -1; -} - void MyDiameterEntity::eventRequest(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventRequest", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); @@ -154,7 +112,7 @@ throw(anna::RuntimeException) { // not found: forward to client (if exists) // Forward to client: - MyLocalServer *localServer = my_node->getDiameterServer(); + MyLocalServer *localServer = (MyLocalServer *)my_node->getDiameterServer(); if(localServer && (cid != anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request) /* don't forward CER */) { try { @@ -176,14 +134,14 @@ throw(anna::RuntimeException) { } // Testing: - TestManager::instantiate().receiveMessage(message, my_node, clientSession); + anna::testing::TestManager::instantiate().receiveMessage(message, clientSession); } void MyDiameterEntity::eventResponse(const anna::diameter::comm::Response &response) throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventResponse", ANNA_FILE_LOCATION)); Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); anna::diameter::comm::ClassCode::_v code = response.getClassCode(); anna::diameter::comm::Response::ResultCode::_v result = response.getResultCode(); anna::diameter::comm::Message* request = const_cast(response.getRequest()); @@ -239,7 +197,7 @@ throw(anna::RuntimeException) { } // Forward to client: - MyLocalServer *localServer = my_node->getDiameterServer(); + MyLocalServer *localServer = (MyLocalServer *)my_node->getDiameterServer(); if(localServer && (request_cid != anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request) /* don't forward CEA */) { anna::diameter::comm::Message *msg; @@ -251,7 +209,7 @@ throw(anna::RuntimeException) { bool success = localServer->send(msg, request->getRequestServerSessionKey()); // Detailed log: - anna::diameter::comm::ServerSession *usedServerSession = my_node->getMyDiameterEngine()->findServerSession(request->getRequestServerSessionKey()); + anna::diameter::comm::ServerSession *usedServerSession = my_node->getCommEngine()->findServerSession(request->getRequestServerSessionKey()); std::string detail = usedServerSession ? usedServerSession->asString() : ""; // esto no deberia ocurrir if(my_node->logEnabled()) { @@ -271,7 +229,7 @@ throw(anna::RuntimeException) { if(isOK || contextExpired) my_node->sendBurstMessage(); // Testing: - TestManager::instantiate().receiveMessage(*message, my_node, clientSession); + if(isOK) anna::testing::TestManager::instantiate().receiveMessage(*message, clientSession); } void MyDiameterEntity::eventUnknownResponse(anna::diameter::comm::ClientSession *clientSession, const anna::DataBlock &message) @@ -279,7 +237,7 @@ throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventUnknownResponse", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); LOGDEBUG @@ -302,7 +260,7 @@ throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyDiameterEntity", "eventDPA", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); LOGDEBUG @@ -320,5 +278,5 @@ throw(anna::RuntimeException) { if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfe", clientSession->asString()); // Testing: - TestManager::instantiate().receiveMessage(message, my_node, clientSession); + anna::testing::TestManager::instantiate().receiveMessage(message, clientSession); } diff --git a/example/diameter/launcher/MyDiameterEntity.hpp b/example/diameter/launcher/MyDiameterEntity.hpp index 73494b5..a63bf28 100644 --- a/example/diameter/launcher/MyDiameterEntity.hpp +++ b/example/diameter/launcher/MyDiameterEntity.hpp @@ -11,9 +11,8 @@ // Project #include +#include -// Process -#include namespace anna { namespace diameter { @@ -25,33 +24,18 @@ namespace anna { class MyDiameterEntity : public anna::diameter::comm::Entity { - bool a_balance; // Balance over entity servers instead of doing standard behaviour (first primary, secondary if fails, etc.). Default: false. - std::string a_sessionBasedModelsType; - void eventRequestRetransmission(const anna::diameter::comm::ClientSession *, anna::diameter::comm::Message*) throw(); void eventResponse(const anna::diameter::comm::Response&) throw(anna::RuntimeException); void eventRequest(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); void eventUnknownResponse(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); void eventDPA(anna::diameter::comm::ClientSession *, const anna::DataBlock&) throw(anna::RuntimeException); - // Reimplementation - int readSocketId(const anna::diameter::comm::Message* message, int maxClientSessions) const throw(); - public: - MyDiameterEntity() { - a_balance = false; - a_sessionBasedModelsType = "SessionIdLowPart"; - } - - ProgrammedAnswers a_reactingAnswers; - ProgrammedAnswers *getReactingAnswers() throw() { return (ProgrammedAnswers *)&a_reactingAnswers; } + MyDiameterEntity() {;} - // Additional configuration parameters: - void setSessionBasedModelsType(const std::string &type) throw() { a_sessionBasedModelsType = type; } - void setBalance(bool balance) throw() { a_balance = balance; } - const std::string & getSessionBasedModelsType() const throw() { return a_sessionBasedModelsType; } - bool getBalance() const throw() { return a_balance; } + anna::diameter::codec::MessagesDeque a_reactingAnswers; + anna::diameter::codec::MessagesDeque *getReactingAnswers() throw() { return (anna::diameter::codec::MessagesDeque*)&a_reactingAnswers; } }; #endif diff --git a/example/diameter/launcher/MyLocalServer.cpp b/example/diameter/launcher/MyLocalServer.cpp index 7d34b46..c4f5db7 100644 --- a/example/diameter/launcher/MyLocalServer.cpp +++ b/example/diameter/launcher/MyLocalServer.cpp @@ -14,14 +14,14 @@ #include #include #include +#include // Process #include #include #include #include -#include -#include +#include void MyLocalServer::eventRequest(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message) @@ -29,7 +29,7 @@ throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventRequest", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); anna::diameter::codec::Engine *codecEngine = my_node->getCodecEngine(); // CommandId: @@ -59,7 +59,7 @@ throw(anna::RuntimeException) { msg->forwardEndToEnd(); // end-to-end will be kept msg->setBody(message); msg->setRequestServerSessionKey(serverSession->getKey()); - bool success = entity->send(msg, my_node->getEntity()->getBalance()); + bool success = entity->send(msg); // Detailed log: if(my_node->logEnabled()) { @@ -71,7 +71,7 @@ throw(anna::RuntimeException) { // Testing: - TestManager::instantiate().receiveMessage(message, my_node, serverSession); + anna::testing::TestManager::instantiate().receiveMessage(message, serverSession); return; } @@ -90,7 +90,7 @@ throw(anna::RuntimeException) { // Decode try { codecMsg.decode(message, answer_message); } catch(anna::RuntimeException &ex) { ex.trace(); } - answer_message->setStandardToAnswer(codecMsg, my_node->getMyDiameterEngine()->getOriginHost(), my_node->getMyDiameterEngine()->getOriginRealm()); + answer_message->setStandardToAnswer(codecMsg, my_node->getCommEngine()->getOriginHostName(), my_node->getCommEngine()->getOriginRealmName()); analysisOK = (answer_message->getResultCode() == anna::diameter::helpers::base::AVPVALUES__Result_Code::DIAMETER_SUCCESS); } @@ -103,7 +103,7 @@ throw(anna::RuntimeException) { } else { // Testing: - TestManager::instantiate().receiveMessage(message, my_node, serverSession); + anna::testing::TestManager::instantiate().receiveMessage(message, serverSession); return; // nothing done } @@ -136,14 +136,14 @@ throw(anna::RuntimeException) { if(analysisOK && programmed) a_reactingAnswers.nextMessage(code); // Testing: - TestManager::instantiate().receiveMessage(message, my_node, serverSession); + anna::testing::TestManager::instantiate().receiveMessage(message, serverSession); } void MyLocalServer::eventResponse(const anna::diameter::comm::Response &response) throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventResponse", ANNA_FILE_LOCATION)); Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); anna::diameter::comm::ClassCode::_v code = response.getClassCode(); anna::diameter::comm::Response::ResultCode::_v result = response.getResultCode(); anna::diameter::comm::Message* request = const_cast(response.getRequest()); @@ -198,7 +198,7 @@ throw(anna::RuntimeException) { anna::diameter::comm::Entity *entity = my_node->getEntity(); if(entity) { - anna::diameter::comm::ClientSession *usedClientSession = my_node->getMyDiameterEngine()->findClientSession(request->getRequestClientSessionKey()); + anna::diameter::comm::ClientSession *usedClientSession = my_node->getCommEngine()->findClientSession(request->getRequestClientSessionKey()); std::string detail; if(my_node->logEnabled()) detail = usedClientSession ? usedClientSession->asString() : ""; // this should not happen @@ -229,7 +229,7 @@ throw(anna::RuntimeException) { } // Testing: - TestManager::instantiate().receiveMessage(*message, my_node, serverSession); + if(isOK) anna::testing::TestManager::instantiate().receiveMessage(*message, serverSession); } void MyLocalServer::eventUnknownResponse(anna::diameter::comm::ServerSession *serverSession, const anna::DataBlock &message) @@ -237,7 +237,7 @@ throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventUnknownResponse", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); LOGDEBUG @@ -259,7 +259,7 @@ throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tm("launcher::MyLocalServer", "eventDPA", ANNA_FILE_LOCATION)); // Performance stats: Launcher& my_app = static_cast (anna::app::functions::getApp()); - OriginHost * my_node = my_app.getOriginHost(getEngine()->getOriginHost()); + anna::diameter::comm::OriginHost *my_node = my_app.getOriginHost(getEngine()->getOriginHostName()); // CommandId: anna::diameter::CommandId cid = anna::diameter::codec::functions::getCommandId(message); LOGDEBUG @@ -277,5 +277,5 @@ throw(anna::RuntimeException) { if(my_node->logEnabled()) my_node->writeLogFile(message, "recvfc", serverSession->asString()); // Testing: - TestManager::instantiate().receiveMessage(message, my_node, serverSession); + anna::testing::TestManager::instantiate().receiveMessage(message, serverSession); } diff --git a/example/diameter/launcher/MyLocalServer.hpp b/example/diameter/launcher/MyLocalServer.hpp index 831e15b..7f66703 100644 --- a/example/diameter/launcher/MyLocalServer.hpp +++ b/example/diameter/launcher/MyLocalServer.hpp @@ -11,9 +11,8 @@ // Project #include +#include -// Process -#include namespace anna { namespace diameter { @@ -32,8 +31,8 @@ class MyLocalServer : public anna::diameter::comm::LocalServer { public: - ProgrammedAnswers a_reactingAnswers; - ProgrammedAnswers *getReactingAnswers() throw() { return (ProgrammedAnswers *)&a_reactingAnswers; } + anna::diameter::codec::MessagesDeque a_reactingAnswers; + anna::diameter::codec::MessagesDeque *getReactingAnswers() throw() { return (anna::diameter::codec::MessagesDeque*)&a_reactingAnswers; } }; #endif diff --git a/example/diameter/launcher/SConscript b/example/diameter/launcher/SConscript index d9d48ce..04ad2a5 100644 --- a/example/diameter/launcher/SConscript +++ b/example/diameter/launcher/SConscript @@ -12,7 +12,7 @@ pwd = str(Dir ('.').abspath); anna_libpaths = [] anna_libs = [] -modules = [ 'core', 'io', 'xml', 'app', 'http', 'comm', 'timex', 'http', 'statistics', 'time', 'diameter', 'diameter_comm' ]; +modules = [ 'core', 'io', 'xml', 'app', 'http', 'comm', 'timex', 'http', 'statistics', 'time', 'diameter', 'diameter_comm', 'testing' ]; for module in modules: anna_libs.append ("anna_" + module) module = module.replace("_", ".") @@ -43,12 +43,10 @@ localEnv.Append(LIBPATH = anna_libpaths) # Linking ################################################################# -# Process includes (avoid mandatory using of quoted includes and ../ paths from testing directory): +# Process includes: current_directory = Dir ('.').abspath -testing_include = os.path.join (current_directory, "testing") dynamic_include = os.path.join (pwd, "../../../../dynamic/launcher/default/") -localEnv.Append (CPPPATH = [current_directory, testing_include, dynamic_include]) - -result = localEnv.Program (pName, Glob ('*.cpp') + Glob ('testing/*.cpp')) +localEnv.Append (CPPPATH = [current_directory, dynamic_include]) +result = localEnv.Program (pName, Glob ('*.cpp')) Return ('result') diff --git a/example/diameter/launcher/deployments/st-client/checkStatus.sh b/example/diameter/launcher/deployments/st-client/checkStatus.sh new file mode 100755 index 0000000..7e7f861 --- /dev/null +++ b/example/diameter/launcher/deployments/st-client/checkStatus.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Result code: 1 (miss instances (and connections)), 2 (miss connections) +ADML_CONNECTIONS=`cat .st_conf_adml_connections 2>/dev/null` +ADML_INSTANCES=`cat .st_conf_adml_instances 2>/dev/null` +RESULT_CODE=0 + +ADML_INSTANCES_ALIVE=$(pgrep ADML- | wc -l) +echo -n "$ADML_INSTANCES_ALIVE instances alive" +if [ $ADML_INSTANCES_ALIVE -ne $ADML_INSTANCES ] +then + echo " ! (expected $ADML_INSTANCES configured)" + RESULT_CODE=1 +else + echo +fi + +ADML_CONNECTIONS_ALIVE=$(netstat -a | grep :diameter | grep ESTABLISHED | wc -l) +ADML_TOTAL_CONNECTIONS=$((ADML_CONNECTIONS*ADML_INSTANCES)) +echo -n "$ADML_CONNECTIONS_ALIVE connections established" +if [ $ADML_CONNECTIONS_ALIVE -ne $ADML_TOTAL_CONNECTIONS ] +then + echo " ! (expected $ADML_TOTAL_CONNECTIONS configured)" + [ $RESULT_CODE -ne 1 ] && RESULT_CODE=2 +else + echo +fi + +exit $RESULT_CODE + diff --git a/example/diameter/launcher/deployments/st-client/configure.sh b/example/diameter/launcher/deployments/st-client/configure.sh index b818a78..21e3112 100755 --- a/example/diameter/launcher/deployments/st-client/configure.sh +++ b/example/diameter/launcher/deployments/st-client/configure.sh @@ -57,17 +57,18 @@ calculate_deployment_layout() { echo "Orientative table" echo "-----------------------------------------------------------------------------------------------------------" echo -n "Number of instances: " + instances__dflt=$(ceil $max_connections $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE) for conn in `seq 1 $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE | tac` do instances=$(ceil $max_connections $conn) echo -n -e "\t$instances" + [ $conn -eq 1 ] && instances__dflt=$instances done echo echo -e "Connects per instance:\t10\t9\t8\t7\t6\t5\t4\t3\t2\t1" echo "===========================================================================================================" echo #echo "Input selection (connections per instance 1..$MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE) [1]:" - instances__dflt=$(ceil $max_connections $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE) echo "Input the desired number of ADML instances [$instances__dflt]:" echo " (more than $instances instances, implies 1 single connection/instance)" read G_ADML_INSTANCES @@ -77,7 +78,7 @@ calculate_deployment_layout() { if [ $G_ADML_CONNECTIONS -gt $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE ] then echo "Warning: the number of connections per ADML instance ($G_ADML_CONNECTIONS) is greater" - echo " than the maximum suggested: $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE" + echo " than the maximum recommended: $MAXIMUM_SUGGESTED_CLIENT_CONNECTION_PER_ADML_INSTANCE" echo echo "Press ENTER to continue, CTRL-C to abort ..." read dummy @@ -135,12 +136,15 @@ fi calculate_deployment_layout +# Format for instance number (for example: 1 -> 001, .., 45 -> 045, 300 -> 300) +INSTANCE_FORMAT=$(echo $G_ADML_INSTANCES | wc -c) +INSTANCE_FORMAT=$((INSTANCE_FORMAT-1)) + # Dump persintently: echo $G_ADML_INSTANCES > $ADML_INSTANCES__ST_CONF_FILE echo $G_ADML_CONNECTIONS > $ADML_CONNECTIONS__ST_CONF_FILE # Rate per instance: -#rate_per_instance=$(ceil $desired_rate $G_ADML_INSTANCES) rate_per_instance=$((desired_rate/$G_ADML_INSTANCES)) [ $rate_per_instance -lt 1 ] && rate_per_instance=1 echo $rate_per_instance > $ADML_RATE_PER_INSTANCE__ST_CONF_FILE @@ -151,7 +155,6 @@ echo "Layout:" echo echo " - $G_ADML_INSTANCES ADML instances" echo " - $G_ADML_CONNECTIONS client connections per ADML instance" -#maximum_rate_1c=$((G_ADML_INSTANCES*MAXIMUM_ADML_ASYNC_RATE)) maximum_rate=$((G_ADML_INSTANCES*G_ADML_CONNECTIONS*MAXIMUM_ADML_ASYNC_RATE)) overcommit_rate_per_instance=$((G_ADML_CONNECTIONS*MAXIMUM_ADML_ASYNC_RATE)) echo @@ -171,35 +174,20 @@ echo "Input the number of test cases to program:" read N_TESTCASES while [ -z "$N_TESTCASES" ]; do read N_TESTCASES; done echo $N_TESTCASES > $N_TESTCASES__ST_CONF_FILE -testcase_per_adml_instance=$N_TESTCASES echo "Input the first test id to program [1]:" read first_value [ "$first_value" = "" ] && first_value=1 [ $first_value -lt 1 ] && first_value=1 echo -time_covered_1=$(ceil $N_TESTCASES $desired_rate) -time_covered=$(ceil $N_TESTCASES $((desired_rate*G_ADML_INSTANCES))) -echo "That amount covers $time_covered_1 seconds for one running ADML instance." -if [ $G_ADML_INSTANCES -gt 1 ] -then - echo "But you will have $G_ADML_INSTANCES instances running in parallel, then the total covered time is: $time_covered seconds" - testcase_per_adml_instance=$((N_TESTCASES/G_ADML_INSTANCES)) - echo "(aproximately, $testcase_per_adml_instance test cases will be programmed on each ADML instance)" -fi - -0>$N_TESTCASES_PROGRAM_LAYOUT__ST_CONF_FILE -for instance in `seq 1 $G_ADML_INSTANCES` -do - offset=$((testcase_per_adml_instance * (instance-1))) - ini=$((offset + first_value)) - fin=$((offset + first_value + testcase_per_adml_instance - 1)) - echo "$instance $ini $fin" >> $N_TESTCASES_PROGRAM_LAYOUT__ST_CONF_FILE -done +time_covered=$(echo "$N_TESTCASES/$desired_rate" | bc) +testcase_per_adml_instance=$((N_TESTCASES/G_ADML_INSTANCES)) +echo "Aproximately, $testcase_per_adml_instance test cases will be programmed on each ADML instance (we have $G_ADML_INSTANCES instances)." +echo "As we shall program $N_TESTCASES test cases, the total time covered for the desired system rate of $desired_rate cps, is $time_covered seconds." echo -if [ $time_covered -lt 300 ] +if [ $time_covered -lt 10 ] then - echo "$time_covered seconds is under 5 minutes, you should add more test cases to the pool except if you are sure" + echo "$time_covered seconds is under 10 seconds, you should add more test cases to the pool except if you are sure" echo " they will take less time that cycle completion. You could ensure that with a first timeout step." echo "Configuring such timeout slightly under $((1000*time_covered)) milliseconds, you could repeat the cycle safely to" echo " obtain a greater total time of testing." @@ -209,17 +197,22 @@ echo "How many total time you need to cover (in minutes):" read minutes while [ -z "$minutes" ]; do read minutes; done seconds=$((minutes*60)) -repeats=$(ceil $seconds $time_covered) +repeats=0 +[ $seconds -gt $time_covered ] && { repeats=$(ceil $seconds $time_covered) ; repeats=$((repeats-1)) ; } if [ $repeats -gt 0 ] then - echo "You will need $repeats cycles to cover $minutes minutes." - echo "Input the number of cyles [$repeats]: " - echo " (providing 0, you will cover $time_covered seconds)" + cycles=$((repeats+1)) + echo "You will need $cycles cycles to cover $minutes minutes." + echo "Input the desired number of cyles [$cycles]: " + echo " (providing 1, you will cover $time_covered seconds)" echo - read wanted_repeats - [ -z "$wanted_repeats" ] && wanted_repeats=$repeats - echo $wanted_repeats > $CYCLE_REPEATS__ST_CONF_FILE - [ $wanted_repeats -gt 0 ] && echo "Configured $wanted_repeats cycle repeats ($((wanted_repeats+1)) x $time_covered seconds ~ $(((wanted_repeats+1)*time_covered)) seconds of testing)." + read wanted_cycles + [ -z "$wanted_cycles" ] && wanted_cycles=$cycles + wanted_repeats=$((wanted_cycles-1)) + echo $wanted_cycles > $CYCLE_REPEATS__ST_CONF_FILE + [ $wanted_repeats -gt 0 ] && echo "Configured $wanted_repeats cycle repeats ($wanted_cycles cycles x $time_covered seconds ~ $((wanted_cycles*time_covered)) seconds of testing)." +else + echo 0 > $CYCLE_REPEATS__ST_CONF_FILE fi echo echo "System test configuration completed." @@ -233,9 +226,16 @@ cp services.msk services.xml sed -i 's/__CLIENT_CONNECTIONS__/'$G_ADML_CONNECTIONS'/g' services.xml cd - >/dev/null - -for instance in `seq 1 $G_ADML_INSTANCES` +# Create instances and layout: +0>$N_TESTCASES_PROGRAM_LAYOUT__ST_CONF_FILE +for i in `seq 1 $G_ADML_INSTANCES` do + instance=$(printf "%0${INSTANCE_FORMAT}d" $i) + offset=$((testcase_per_adml_instance * (i-1))) + ini=$((offset + first_value)) + fin=$((offset + first_value + testcase_per_adml_instance - 1)) + echo "$instance $ini $fin" >> $N_TESTCASES_PROGRAM_LAYOUT__ST_CONF_FILE + echo "Creating ADML instance $instance ..." mkdir -p ADMLS/ADML-$instance cd ADMLS/ADML-$instance @@ -254,6 +254,7 @@ done echo echo "Now you can run all the instances deployed: ./run.sh" +echo "To configure another layout you should execute this script again." echo echo "Done!" diff --git a/example/diameter/launcher/deployments/st-client/launchCPS.sh b/example/diameter/launcher/deployments/st-client/launchCPS.sh new file mode 100755 index 0000000..44d55b3 --- /dev/null +++ b/example/diameter/launcher/deployments/st-client/launchCPS.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +############# +# VARIABLES # +############# +ADML_INSTANCES=`cat .st_conf_adml_instances 2>/dev/null` + +############# +# FUNCTIONS # +############# +_exit() { + echo + echo $1 + echo + exit 1 +} + +############# +# EXECUTION # +############# +echo +echo +cd `dirname $0` +./checkStatus.sh +[ $? -ne 0 ] && _exit "Fix status to continue ..." +echo +echo "Input desired rate (test cases per second) to start testing [0: stop if active]:" +read desired_rate +if [ "$desired_rate" != "" ] +then + rate_per_instance=$((desired_rate/$ADML_INSTANCES)) +fi + +echo +echo "As we have $ADML_INSTANCES instances available, we shall launch $rate_per_instance test cases" +echo " per second and instance (./operation.sh \"test|ttps|$rate_per_instance\")." +echo +echo "Press ENTER to continue, CTRL-C to abort ..." +read dummy +./operation.sh "test|ttps|$rate_per_instance" + diff --git a/example/diameter/launcher/deployments/st-client/operation_all.sh b/example/diameter/launcher/deployments/st-client/operation_all.sh index e2efaa4..2dcb900 100755 --- a/example/diameter/launcher/deployments/st-client/operation_all.sh +++ b/example/diameter/launcher/deployments/st-client/operation_all.sh @@ -8,14 +8,21 @@ then exit 1 fi +if [ "$1" = "-h" -o "$1" = "--help" ] +then + first_adml=$(ls -d ADMLS/* | head -n +1) + $first_adml/operation.sh help + exit 0 +fi + for op in `ls ADMLS/*/operation.sh` do dn_op=`dirname $op` cd $dn_op echo -n "Instance `basename $dn_op`: " 0>launcher.trace - ./operation.sh $@ - [ $? -ne 0 ] && { echo ; exit 1 ; } + ./operation.sh $@ & + #[ $? -ne 0 ] && { echo ; exit 1 ; } cd - >/dev/null done diff --git a/example/diameter/launcher/deployments/st-client/program.sh b/example/diameter/launcher/deployments/st-client/program.sh index 07e7616..31eb97d 100755 --- a/example/diameter/launcher/deployments/st-client/program.sh +++ b/example/diameter/launcher/deployments/st-client/program.sh @@ -8,38 +8,91 @@ RATE_PER_INSTANCE=`cat .st_conf_rate_per_instance 2>/dev/null` DESIRED_RATE=`cat .st_conf_desired_rate 2>/dev/null` REPEATS=`cat .st_conf_cycle_repeats 2>/dev/null` PROGRAM_LAYOUT_FILE=.st_conf_n_testcases_program_layout +[ -z "$ADML_CONCURRENT_PROVISION_JOBS" ] && ADML_CONCURRENT_PROVISION_JOBS=20 ############# # FUNCTIONS # ############# _exit() { - echo - echo $1 - echo + echo -e "\n$1\n" exit 1 } usage() { - echo "Usage: $0 [-s]" - echo - echo " Performs test case programming from scratch (current test cases will be dropped from ADML involved instances)." - echo - echo " test stuff directory: contains msk files, specially a testcase file with xml files referenced inside. Those" - echo " xml files (without the .msk extension) shall exists in the directory. For example:" - echo - echo " $0 st_examples/DynamicQualification" - echo - echo " Optionally, a file called 'specific' could exists containing testcase-specific information," - echo " which normally will be used to specify database sentences. This file will be accumulated" - echo " as a cloning seed over the file 'specific.all' created on test stuff directory." - echo - echo - echo " -s: start testing just after programming, using desired rate: $DESIRED_RATE test cases per second." + cat << EOF +Usage: $0 [-s] + + Performs test case programming from scratch (current test cases will be dropped + from ADML involved instances). There are two types of programming depending on + the first argument provided: + + test stuff directory: + + The folder provided must contain msk files, specially a testcase file with + xml files referenced inside. Those xml files (without the .msk extension) + shall exists in the directory. For example: + + $0 st_examples/DynamicQualification + + Optionally, a file 'specific' could exists containing testcase-specific + information, which normally will be used to specify database sentences. + This file will be accumulated as a cloning seed over the file 'specific.all' + created on test stuff directory. + + Template type programming could be used for medium-duration testings, because + the scripting used for programming, have lots of groups divisions which even + background-executed are much more slower on programming than a c++ builtin + procedure: dynamic type is the one for large sets of test cases: + + + dynamic: + + The current dynamic procedure selected by mean 'dynlibs/select.sh' script, + will be programmed using its dirname resources: inside, you may found not + only the .so library but the needed xml files for the implemented scenary + and a file called 'dynamic.suffix' used to complete the dynamic operation + in this way: + + dynamic|||| + + For example, you could have this content for 'dynamic.suffix': + + 0|7|CCR-I.xml|CCR-T.xml (0 for timeout means no timeout step) + + in order to generate the operation: + + dynamic|0|||7|CCR-I.xml|CCR-T.xml + + which would be parsed for the specific ADML instance programmed: + + dynamic|0|2000001|2001000|7|CCR-I.xml|CCR-T.xml + + The file 'dynamic.suffix' could have several lines for several scenaries. + In this case, this script will prompt for the desired one. + + This script will build every operation for the configured ADML instances + to complete all the sequence ranges along the whole test system. + + + + -s: start testing just after programming, using desired rate: $DESIRED_RATE test cases per second. +EOF [ $ADML_INSTANCES -gt 1 ] && echo " In your case, with $ADML_INSTANCES, a rate of $RATE_PER_INSTANCE ttps will be send per instance." echo _exit } +advice_to_squeeze_idle_cpu () { + local idle=$(top -b -d 0.1 -n 2 | grep 'Cpu(s):'| tail -1 | awk '{print $8}' | sed 's/,/./') + sleep 10 + echo + echo "Idle cpu now: $idle. Check the system CPU with top. If is not overcommited, consider" + echo " increase the environment variable 'ADML_CONCURRENT_PROVISION_JOBS' (now $ADML_CONCURRENT_PROVISION_JOBS)." + echo + echo "Press ENTER to continue ..." + read dummy +} + ############# # EXECUTION # ############# @@ -53,73 +106,161 @@ miss_conf= echo [ -z "$1" ] && usage -echo "Starting testcases programming ..." +echo "Testcases programming ..." echo +cd `dirname $0` +./checkStatus.sh +[ $? -eq 1 ] && _exit "Fix status to continue ..." -./operation.sh --ping >/dev/null -[ $? -ne 0 ] && _exit "Programming aborted (some ADML client process is not running) !" -TESTCASE_DIR=$1 +# We launch in background ! +#./operation.sh --ping >/dev/null +#[ $? -ne 0 ] && _exit "Programming aborted (some ADML client process is not running) !" + +# Arguments: +PROG_TYPE=$1 AUTOSTART=$2 -[ ! -d $TESTCASE_DIR ] && _exit "Cannot found the test directory '$TESTCASE_DIR' !!" -TESTCASE=( `ls $TESTCASE_DIR/testcase*msk 2>/dev/null` ) -TESTCASE_FILES=${#TESTCASE[@]} -[ $TESTCASE_FILES -ne 1 ] && _exit "One and only one 'testcase*msk' file must be present !!" - -MAX_NUMBER_GROUPS=$(grep ^MAX_NUMBER_GROUPS= clone.sh | cut -d= -f2) -CLONE_GROUPS=$((MAX_NUMBER_GROUPS/ADML_INSTANCES)) -#CLONE_GROUPS=1 -specific= -[ -f $TESTCASE_DIR/specific ] && specific=specific - -[ -z "$ADML_CONCURRENT_PROVISION_JOBS" ] && ADML_CONCURRENT_PROVISION_JOBS=5 - -count=0 -while read -r line -do - instance=$(echo $line | awk '{ print $1 }') - ini_seq=$(echo $line | awk '{ print $2 }') - fin_seq=$(echo $line | awk '{ print $3 }') - ADML_DIR=`readlink -f ADMLS/ADML-$instance` - echo -e "\rCloning interval [$ini_seq,$fin_seq] for $(basename $ADML_DIR) ..." - ./clone.sh $ADML_DIR $TESTCASE $ini_seq $fin_seq $CLONE_GROUPS $specific & - sleep 0.1 - count=$((count+1)) - if [ $count -eq $ADML_CONCURRENT_PROVISION_JOBS ] +# test case stuff programming ######################################################### +if [ "$PROG_TYPE" != "dynamic" ] +then + TESTCASE_DIR=$PROG_TYPE + + [ ! -d $TESTCASE_DIR ] && _exit "Cannot found the test directory '$TESTCASE_DIR' !!" + TESTCASE=( `ls $TESTCASE_DIR/testcase*msk 2>/dev/null` ) + TESTCASE_FILES=${#TESTCASE[@]} + [ $TESTCASE_FILES -ne 1 ] && _exit "One and only one 'testcase*msk' file must be present !!" + + MAX_NUMBER_GROUPS=$(grep ^MAX_NUMBER_GROUPS= clone.sh | cut -d= -f2) + CLONE_GROUPS=$((MAX_NUMBER_GROUPS/ADML_INSTANCES)) + #CLONE_GROUPS=1 + specific= + [ -f $TESTCASE_DIR/specific ] && specific=specific + + count=0 + while read -r line + do + instance=$(echo $line | awk '{ print $1 }') + ini_seq=$(echo $line | awk '{ print $2 }') + fin_seq=$(echo $line | awk '{ print $3 }') + ADML_DIR=`readlink -f ADMLS/ADML-$instance` + echo -e "\rCloning interval [$ini_seq,$fin_seq] for $(basename $ADML_DIR) ..." + ./clone.sh $ADML_DIR $TESTCASE $ini_seq $fin_seq $CLONE_GROUPS $specific & + sleep 0.1 + count=$((count+1)) + if [ $count -eq $ADML_CONCURRENT_PROVISION_JOBS ] + then + wait $(jobs -p) + count=0 + fi + + done < $PROGRAM_LAYOUT_FILE + + # Advice for idle cpu: + advice_to_squeeze_idle_cpu + + # Wait background jobs to finish: + sleep 5 + echo "Waiting for clone completion ..." + echo "(please be patient, this may take a while)" + echo + echo "Background Jobs: $(jobs -p | wc -l)" + wait $(jobs -p) + + echo + echo "Programming has finished !" + echo + + echo "Configuring repeat cycles ..." + ./operation.sh "test|repeats|$REPEATS" + + if [ -n "$specific" ] then - idle_cpu=$(top -b -d 0.1 -n 2 | grep 'Cpu(s):'| tail -1 |awk '{print $8}') - echo - echo "Idle cpu = $idle_cpu%" - echo "if cpu is not overcommited, consider increase ADML_CONCURRENT_PROVISION_JOBS environment variable (now $ADML_CONCURRENT_PROVISION_JOBS)" + echo "A new file '$TESTCASE_DIR/specific.all' has been created." + echo "Probably you need to apply it before starting traffic." echo - wait $(jobs -p) - count=0 + echo "Press ENTER to continue, CTRL-C to abort ..." + read dummy fi -done < $PROGRAM_LAYOUT_FILE +# dynamic programming ################################################################# +else + TESTCASE_DIR=$(readlink -f dynlibs/libanna_dynamicLauncherProcedure.so | xargs dirname) + DYNAMIC_SUFFIX_FILE=$TESTCASE_DIR/dynamic.suffix -# Wait background jobs to finish: -sleep 5 -echo "Waiting for clone completion ..." -echo "(please be patient, this may take a while)" -echo -echo "Background Jobs: $(jobs -p | wc -l)" -wait $(jobs -p) + [ ! -f $DYNAMIC_SUFFIX_FILE ] && _exit "Missing '$DYNAMIC_SUFFIX_FILE' file.\nUse 'dynlibs/select.sh' to change the dynamic procedure and restart the ADML instances." + dynamic_suffix=( $(grep -v ^# $DYNAMIC_SUFFIX_FILE) ) -echo -echo "Programming has finished !" -echo + # Multiple scenarios: + suffixes=${#dynamic_suffix[@]} + if [ $suffixes -gt 1 ] + then + echo + echo "----------------------------------------------------------------" + cat $DYNAMIC_SUFFIX_FILE + echo "----------------------------------------------------------------" + echo + echo "Detected $suffixes scenarios:" + echo + tmpfile=$(mktemp) + opt=1 + for line in $(grep -v ^# $DYNAMIC_SUFFIX_FILE) + do + echo "${opt}) $line" + opt=$((opt+1)) + done > $tmpfile + cat $tmpfile + echo + echo "Select the desired option (0 to input a user defined one):" + read option + while [ -z "$option" ]; do read option ; done + if [ "$option" != "0" ] + then + dynamic_suffix=$(grep "^${option}) " $tmpfile | cut -d" " -f2-) + [ -z "$dynamic_suffix" ] && _exit "Invalid option !" + else + echo "Input specific program arguments:" + echo " (be sure that are supported by the dynamic procedure)" + echo + read dynamic_suffix + while [ -z "$dynamic_suffix" ]; do read dynamic_suffix ; done + fi + fi -echo "Configuring repeat cycles ..." -./operation.sh "test|repeats|$REPEATS" + # Modify xml files path: + xmls=( $(echo $dynamic_suffix | sed 's/'\|'/ /g') ) + dynamic_suffix=$(for xml in ${xmls[@]} + do + echo $xml | grep -q "\.xml$" + [ $? -eq 0 ] && echo -n "$TESTCASE_DIR/" + echo -n "${xml}|" + done | sed 's/'\|'$//') -if [ -n "$specific" ] -then - echo "A new file '$TESTCASE_DIR/specific.all' has been created." - echo "Probably you need to apply it before starting traffic." + # If still idle CPU, you could increase chunks number of background jobs + echo "Dynamic programming ..." echo - echo "Press ENTER to continue, CTRL-C to abort ..." - read dummy + while read -r line + do + instance=$(echo $line | awk '{ print $1 }') + ini_seq=$(echo $line | awk '{ print $2 }') + fin_seq=$(echo $line | awk '{ print $3 }') + ADML_DIR=`readlink -f ADMLS/ADML-$instance` + + cd $ADML_DIR + ./operation.sh -t 60 "dynamic|$ini_seq|$fin_seq|$dynamic_suffix" & + sleep 0.1 + count=$((count+1)) + if [ $count -eq $ADML_CONCURRENT_PROVISION_JOBS ] + then + wait $(jobs -p) + count=1 + fi + cd - >/dev/null + + done < $PROGRAM_LAYOUT_FILE + + # Advice for idle cpu: + advice_to_squeeze_idle_cpu + fi echo @@ -129,20 +270,42 @@ if [ "$AUTOSTART" = "-s" ] then start_testing=yes else - echo "Input desired rate (test cases per second) to start testing [0: nothing done]:" - read desired_rate - if [ "$desired_rate" != "" ] - then - rate_per_instance=$((desired_rate/$ADML_INSTANCES)) - [ $rate_per_instance -lt 1 ] && rate_per_instance=1 - ./operation.sh "test|ttps|$rate_per_instance" - else - echo "Remember that you could start traffic using:" - echo " ./operation.sh \"test|ttps|\"" - echo - echo "For example, to reach $DESIRED_RATE test cases per second:" - echo " ./operation.sh \"test|ttps|$RATE_PER_INSTANCE\"" - fi + cat << EOF + +To start testing, you must use the './operation.sh' script. The most + common commands used for testing are: + + - Enable reports dump for failed tests: ./operation.sh "test|report|failed" + - Launch traffic: ./operation.sh "test|ttps|" + + (*) this is related to a single instance, because operation script launched + here invokes every 'ADMLS/ADML-/operation.sh' counterpart + script. Then, you should divide the desired CPS by the number of + instances. For example, if you need $DESIRED_RATE test cases per second, + as you have $ADML_INSTANCES instances, then you should execute: + + ./operation.sh "test|ttps|$RATE_PER_INSTANCE" + + - Stop traffic: ./operation.sh "test|ttps|0" + - Reset already classified (Success/Failed) test cases: ./operation.sh "test|reset[|soft]" + - Reset also 'in-progress' state test cases: ./operation.sh "test|reset|hard" + - Clear programmed test cases: ./operation.sh "test|clear" + +Remember that './operation.sh' broadcasts the operation scripts inside + the ADML instances, then some operations should better be used within + a specific 'ADMLS/ADML-' directory to avoid console spam: + + - Check a testcase in runtime: ADMLS/ADML-001/operation.sh "test|look|" + - Execute the next programmed test case: ADMLS/ADML-001/operation.sh "test|next" + - Interactive-step execution: ADMLS/ADML-001/operation.sh "test|interact||" + - Summary: ADMLS/ADML-001/operation.sh "test|summary" + +For a complete and detailed information, execute: ./operation.sh --help | less + +You could also use './launchCPS.sh' script. + +EOF + fi if [ -n "$start_testing" ] diff --git a/example/diameter/launcher/deployments/st-client/run_all.sh b/example/diameter/launcher/deployments/st-client/run_all.sh index 3d1c33b..489855c 100755 --- a/example/diameter/launcher/deployments/st-client/run_all.sh +++ b/example/diameter/launcher/deployments/st-client/run_all.sh @@ -11,23 +11,35 @@ fi for run in `ls ADMLS/*/run.sh` do cd `dirname $run` - ./run.sh - #sleep 0.1 + instance_name=$(basename $PWD) + pkill $instance_name + [ $? -eq 0 ] && echo -n "Re-" + echo "Starting $instance_name ..." + ./run.sh > /dev/null & cd - >/dev/null done - -sleep 1 -echo -echo -echo "To enable reports dump for failed tests, execute:" -echo " ./operation.sh \"test|report|failed\"" -echo -echo "To stop the processes, you could execute:" -echo " pgrep ADML-[0-9] | xargs kill" echo -echo "When running, use script './program.sh' to configure the test cases." -echo "To configure another layout you should execute './configure.sh'." -echo -echo "Done!" +wait $(jobs -p) + +sleep 3 +./checkStatus.sh + +cat << EOF + $(pgrep ADML- | wc -l) instances alive ! + $(netstat -a | grep :diameter | grep ESTABLISHED | wc -l) connections established ! + + To stop the processes, you could execute: pgrep ADML-[0-9] | xargs kill + Anyway, executing './run.sh' again you will restart the ADML instances. + + Now it's time to './program.sh' the started instances with the desired + scenary. There are two programming variants: + + ./program.sh + ./program.sh dynamic + + + Done! +EOF + echo diff --git a/include/anna/diameter.comm/Engine.hpp b/include/anna/diameter.comm/Engine.hpp index 4416bec..72e3ad9 100644 --- a/include/anna/diameter.comm/Engine.hpp +++ b/include/anna/diameter.comm/Engine.hpp @@ -103,32 +103,32 @@ public: /** Diameter application node origin realm - @param originRealm Used to configure the Origin-Realm for outgoing messages. + @param originRealmName Used to configure the Origin-Realm for outgoing messages. If not configured or empty string provided, host domainname will be set. */ - void setOriginRealm(const std::string & originRealm) throw(); + void setOriginRealmName(const std::string & originRealmName) throw(); /** Diameter application origin host - @param originHost Used to configure the Origin-Host for outgoing messages. + @param originHostName Used to configure the Origin-Host for outgoing messages. If not configured or empty string provided, hostname (system name) will be set. */ - void setOriginHost(const std::string & originHost) throw(); + void setOriginHostName(const std::string & originHostName) throw(); /** Gets the configured diameter application node origin realm @return Diameter application node origin realm */ - const std::string & getOriginRealm() const throw() { return a_originRealm; } + const std::string & getOriginRealmName() const throw() { return a_originRealm; } /** Gets the configured diameter application origin host @return Diameter application node origin host */ - const std::string & getOriginHost() const throw() { return a_originHost; } + const std::string & getOriginHostName() const throw() { return a_originHost; } /** @@ -573,12 +573,20 @@ public: */ virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) throw(); + /** + * Sets optional CEA from file, when default is not enough + * + * @param &ceaPathfile Path file for the CEA xml message provided + */ + void setCEA(const std::string &ceaPathfile) throw() { a_ceaPathfile = ceaPathfile; } + /** * Class user should implement this method in order to define Capabilities-Exchange-Answer for received CER over server socket. * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name). * Default implementation imply CEA with DIAMETER_SUCCESS Result-Code, and own domain node parameters, but application should * analyze the CER message in order to accept it or not (with apropiate non-success Result-Code). - * Any other implementation is responsible to build a valid CEA diameter message: + * If @setCEA was invoked, a message from file is used instead of default implementation. + * Any other implementation is responsible to build a valid CEA diameter message, even ignoring a possible cea from file when @setCEA is used: * * If one peer sends a CER message to another Peer and receiver does not have support for * @@ -729,6 +737,7 @@ private: anna::Millisecond a_watchdogPeriod; // // ServerSessions messages: + std::string a_ceaPathfile; // path file to optional CEA (diameter local server configuration) // anna::DataBlock a_cea; // anna::DataBlock a_dwa; diff --git a/include/anna/diameter.comm/Entity.hpp b/include/anna/diameter.comm/Entity.hpp index 8dec08c..b372497 100644 --- a/include/anna/diameter.comm/Entity.hpp +++ b/include/anna/diameter.comm/Entity.hpp @@ -49,6 +49,16 @@ class ClientSession; */ class Entity { +public: + + /** + * Defines behaviour on validation procedure: complete analysis or stop at first validation error over the message (by default) + */ + struct SessionBasedModelsType { enum _v { RoundRobin, SessionIdOptionalPart, SessionIdHighPart, SessionIdLowPart /* default */ }; }; + +private: + + std::vector a_servers; int a_maxServers; // -1 means "no limit to add servers" std::string a_description; @@ -59,6 +69,10 @@ class Entity { // Engine Engine *a_engine; + // Balance and socket selection: + bool a_balance; + SessionBasedModelsType::_v a_sessionBasedModelsType; + // Availability bool a_available; // any of the servers must be bound void availabilityLost() throw(); @@ -86,6 +100,8 @@ class Entity { // Private close/destroy method void close(bool destroy) throw(anna::RuntimeException); + // helpers + static const char* asText(const SessionBasedModelsType::_v) throw(); public: @@ -192,6 +208,21 @@ public: Server *getLastUsedResource() const throw() { return (a_lastUsedResource); } + /** + * Balance over entity servers or use standard behaviour (first primary, secondary if fails, etc.). + * New created entities have balance disabled. + * + * @param balance True or false to enable or disable. + */ + void setBalance (bool balance) throw() { a_balance = balance; } + + /** + * Gets the balance mode + * + * @return True if balance over entity servers is enabled, false if standard behaviour is configured (default). + */ + bool getBalance() const throw() { return a_balance; } + // SIMPLE BALANCE or STANDARD documentation version // /** @@ -223,8 +254,8 @@ public: /** Sent a message to the entity. First uses primary server, secondary if fails and so on to the last defined resource (server) within entity. Another sending algorithm (non standard) could - be enabled (balance boolean parameter): it consist in round-robin server selection to set the - first resource in a complete cycle (standard behaviour tries all servers from FIRST defined). + be enabled (@setBalance): it consist in round-robin server selection to set the first resource + in a complete cycle (standard behaviour tries all servers from FIRST defined). Anyway, last used delivery resource could be known through #getLastUsedResource(). When the message is a request, a timer will be set automatically to control the response time. @@ -232,15 +263,26 @@ public: timeout value will be configured at #setClassCodeTimeout. \param message Message sent. - \param balance False by default (standard beaviour), but useful to balance over servers within entity. @return Boolean about success in send operation. Implies true result when any of the entity servers could send the message, and false when neither of the servers was available or fail to send the message (an alarm and error counter will be generated in this case). Broadcast try to send all over the resources in spite of any fail. */ - bool send(const Message *message, bool balance = false) throw(anna::RuntimeException); - bool send(const Message &message, bool balance = false) throw(anna::RuntimeException) { return send(&message, balance); } + bool send(const Message *message) throw(anna::RuntimeException); + bool send(const Message &message) throw(anna::RuntimeException) { return send(&message); } + + /** + * Sets sessions based models type. + * \param sessionBasedModelsType Session based models type: RoundRobin, SessionIdLowPart (default), SessionIdHighPart or SessionIdOptionalPart. + */ + void setSessionBasedModelsType(const SessionBasedModelsType::_v sessionBasedModelsType) throw() { a_sessionBasedModelsType = sessionBasedModelsType; } + + /** + * Returns sessions based models type. + * \return Session based models type: RoundRobin, SessionIdLowPart, SessionIdHighPart or SessionIdOptionalPart. + */ + SessionBasedModelsType::_v getSessionBasedModelsType() const throw() { return a_sessionBasedModelsType; } /** @@ -286,7 +328,7 @@ public: subscriber and service aware contextual load balancing strategies. By default, Session-Id avp is used to select the resource. Session-Id is split into 4 sections: diameter identity, high part, low part and optional part. Default implementation analizes 'low' part, returning its - value as reference for socket selection. + value as reference for socket selection. Use @setSessionBasedModelsType to change this behaviour. When server is configured as single client session (max client sessions equal to 1), entity will ignore diff --git a/example/diameter/launcher/OriginHost.hpp b/include/anna/diameter.comm/OriginHost.hpp similarity index 76% rename from example/diameter/launcher/OriginHost.hpp rename to include/anna/diameter.comm/OriginHost.hpp index 2ea2f7f..8338e0d 100644 --- a/example/diameter/launcher/OriginHost.hpp +++ b/include/anna/diameter.comm/OriginHost.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_OriginHost_hpp -#define example_diameter_launcher_OriginHost_hpp +#ifndef anna_diameter_comm_OriginHost_hpp +#define anna_diameter_comm_OriginHost_hpp // Standard #include @@ -18,6 +18,7 @@ #include #include #include +#include namespace anna { @@ -25,26 +26,19 @@ namespace anna { namespace codec { class Engine; } - namespace stack { - class Dictionary; - } namespace comm { - class Message; - } - } -} - - -class MyDiameterEntity; -class MyDiameterEngine; -class MyLocalServer; - + class Engine; + class Entity; + class LocalServer; +/** + * OriginHost with single access point for client and server + */ class OriginHost { - MyDiameterEngine *a_commEngine; - MyDiameterEntity *a_entity; // we could get it finding the unique instante within comm engine, but it is more comfortable assign here. - MyLocalServer* a_diameterServer; // idem + anna::diameter::comm::Engine *a_commEngine; + anna::diameter::comm::Entity *a_entity; // we could get it finding the unique instante within comm engine, but it is more comfortable assign here. + anna::diameter::comm::LocalServer* a_diameterServer; // idem anna::diameter::codec::Engine *a_codecEngine; // resources @@ -52,16 +46,8 @@ class OriginHost { anna::Recycler a_commMessages; // main - std::string a_originHost; unsigned int a_applicationId; - // Timming - anna::Millisecond a_allowedInactivityTime; - anna::Millisecond a_tcpConnectDelay; - anna::Millisecond a_answersTimeout; - anna::Millisecond a_ceaTimeout; - anna::Millisecond a_watchdogPeriod; - // Logs & burst std::string a_logFile; bool a_splitLog, a_detailedLog, a_dumpLog; @@ -77,20 +63,22 @@ class OriginHost { int a_burstPopCounter; public: - OriginHost(const std::string &originHost, unsigned int applicationId, const anna::diameter::stack::Dictionary *baseProtocolDictionary); + OriginHost(anna::diameter::comm::Engine* commEngine, unsigned int applicationId); ~OriginHost() {;} - const std::string &getName() const throw() { return a_originHost; } + // OriginHost name: + const std::string &getName() const throw(); // Core resources: - MyDiameterEngine* getMyDiameterEngine() const throw() { return a_commEngine; } + anna::diameter::comm::Engine* getCommEngine() const throw() { return a_commEngine; } unsigned int getApplicationId() const throw() { return a_applicationId; } anna::diameter::codec::Engine *getCodecEngine() const throw() { return a_codecEngine; } void createEntity(const std::string &entityRepresentation, const anna::Millisecond &bindTimeout, const anna::Millisecond &applicationTimeout) throw(anna::RuntimeException); - MyDiameterEntity *getEntity() const throw() { return a_entity; } - void startDiameterServer(const std::string &serverRepresentation, int sessions, const anna::Millisecond &inactivityTimeout, const anna::Millisecond &applicationTimeout, const std::string &ceaPathfile) throw(anna::RuntimeException); - MyLocalServer* getDiameterServer() throw() { return a_diameterServer; } + anna::diameter::comm::Entity *getEntity() const throw() { return a_entity; } + + void createDiameterServer(const std::string &serverRepresentation, int sessions, const anna::Millisecond &inactivityTimeout, const anna::Millisecond &applicationTimeout, const std::string &ceaPathfile) throw(anna::RuntimeException); + anna::diameter::comm::LocalServer* getDiameterServer() throw() { return a_diameterServer; } void setRequestRetransmissions(int r) throw() { if (r >= 0) a_requestRetransmissions = r; } // Messages factory: @@ -128,4 +116,8 @@ public: std::string asXMLString() const throw(); }; +} +} +} + #endif diff --git a/include/anna/diameter/codec/Message.hpp b/include/anna/diameter/codec/Message.hpp index a040aa1..e7edc85 100644 --- a/include/anna/diameter/codec/Message.hpp +++ b/include/anna/diameter/codec/Message.hpp @@ -796,3 +796,4 @@ public: #endif + diff --git a/example/diameter/launcher/ProgrammedAnswers.hpp b/include/anna/diameter/codec/MessagesDeque.hpp similarity index 76% rename from example/diameter/launcher/ProgrammedAnswers.hpp rename to include/anna/diameter/codec/MessagesDeque.hpp index 00b9d4d..8a52d30 100644 --- a/example/diameter/launcher/ProgrammedAnswers.hpp +++ b/include/anna/diameter/codec/MessagesDeque.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_ProgrammedAnswers_hpp -#define example_diameter_launcher_ProgrammedAnswers_hpp +#ifndef anna_diameter_codec_MessagesDeque_hpp +#define anna_diameter_codec_MessagesDeque_hpp // Standard #include @@ -15,39 +15,44 @@ #include namespace anna { - namespace diameter { - namespace codec { - class Message; - } - } -} +namespace diameter { +namespace codec { + + +class Message; -class ProgrammedAnswers { +class MessagesDeque { typedef std::deque codec_messages_deque; typedef std::deque::iterator codec_messages_deque_iterator; typedef std::deque::const_iterator codec_messages_deque_const_iterator; -typedef std::map < int /* message code */, codec_messages_deque* > reacting_answers_container; -typedef std::map < int /* message code */, codec_messages_deque* >::iterator reacting_answers_iterator; -typedef std::map < int /* message code */, codec_messages_deque* >::const_iterator reacting_answers_const_iterator; +typedef std::map < int /* message code */, codec_messages_deque* > messages_container; +typedef std::map < int /* message code */, codec_messages_deque* >::iterator messages_iterator; +typedef std::map < int /* message code */, codec_messages_deque* >::const_iterator messages_const_iterator; - reacting_answers_container a_deques; + messages_container a_deques; bool a_rotate; public: - ProgrammedAnswers() { a_rotate = false; } - ~ProgrammedAnswers() { clear(); } + MessagesDeque() { a_rotate = false; } + ~MessagesDeque() { clear(); } bool rotate() const throw() { return a_rotate; } void rotate(bool r) throw() { a_rotate = r; } void clear () throw(); - void dump () throw(); + void dump (const char *filenamePrefix = "programmed_message") throw(); void addMessage(int code, anna::diameter::codec::Message *message) throw(); anna::diameter::codec::Message* getMessage(int code) const throw(); void nextMessage(int code) throw(); std::string asString(const char *queueName) const throw(); }; +} +} +} + + #endif + diff --git a/example/diameter/launcher/testing/TestCase.hpp b/include/anna/testing/TestCase.hpp similarity index 89% rename from example/diameter/launcher/testing/TestCase.hpp rename to include/anna/testing/TestCase.hpp index b55abd7..b722cac 100644 --- a/example/diameter/launcher/testing/TestCase.hpp +++ b/include/anna/testing/TestCase.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestCase_hpp -#define example_diameter_launcher_TestCase_hpp +#ifndef anna_testing_TestCase_hpp +#define anna_testing_TestCase_hpp // Standard #include @@ -15,12 +15,11 @@ #include // Project -#include -#include #include +#include +#include +#include -// Process -#include namespace anna { @@ -29,11 +28,16 @@ namespace anna { namespace xml { class Node; } -} - -class OriginHost; + namespace diameter { + namespace comm { + class OriginHost; + } + } +namespace testing { + class TestStep; + class TestStepWait; class TestCase { void assertInitialized() const throw(anna::RuntimeException); @@ -83,8 +87,8 @@ public: // Step type & information void addTimeout(const anna::Millisecond &timeout) throw(anna::RuntimeException); - void addSendxml2e(const anna::DataBlock &db, OriginHost *host, int stepNumber) throw(anna::RuntimeException); - void addSendxml2c(const anna::DataBlock &db, OriginHost *host, int stepNumber) throw(anna::RuntimeException); + void addSendxml2e(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) throw(anna::RuntimeException); + void addSendxml2c(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) throw(anna::RuntimeException); void addDelay(const anna::Millisecond &delay) throw(anna::RuntimeException); void addWait(bool fromEntity, const std::string &code, const std::string &bitR, const std::string &hopByHop, const std::string &applicationId, @@ -134,4 +138,7 @@ private: friend class TestStep; }; +} +} + #endif diff --git a/example/diameter/launcher/testing/TestClock.hpp b/include/anna/testing/TestClock.hpp similarity index 88% rename from example/diameter/launcher/testing/TestClock.hpp rename to include/anna/testing/TestClock.hpp index e007cb6..9ae98f4 100644 --- a/example/diameter/launcher/testing/TestClock.hpp +++ b/include/anna/testing/TestClock.hpp @@ -6,13 +6,17 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestClock_hpp -#define example_diameter_launcher_TestClock_hpp +#ifndef anna_testing_TestClock_hpp +#define anna_testing_TestClock_hpp // Project #include #include +namespace anna { + +namespace testing { + class TestManager; class TestClock : public anna::timex::Clock { @@ -25,5 +29,8 @@ public: virtual bool tick() throw(anna::RuntimeException); }; +} +} + #endif diff --git a/example/diameter/launcher/testing/TestCondition.hpp b/include/anna/testing/TestCondition.hpp similarity index 78% rename from example/diameter/launcher/testing/TestCondition.hpp rename to include/anna/testing/TestCondition.hpp index 57cba63..e833712 100644 --- a/example/diameter/launcher/testing/TestCondition.hpp +++ b/include/anna/testing/TestCondition.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestCondition_hpp -#define example_diameter_launcher_TestCondition_hpp +#ifndef anna_testing_TestCondition_hpp +#define anna_testing_TestCondition_hpp // Standard #include @@ -20,7 +20,8 @@ namespace anna { namespace xml { class Node; } -} + +namespace testing { class TestCondition { @@ -55,7 +56,31 @@ class TestCondition { void setServiceContextId(const std::string &value) throw() { a_serviceContextId = value; } bool exists() const throw(); - friend bool operator==(const TestCondition &c1, const TestCondition &c2) throw(); + friend bool operator==(const TestCondition &c1, const TestCondition &c2) throw() { + + if (c1.getType() != c2.getType()) return false; + + if (c1.getType() == TestCondition::Type::Generic) { + if (c1.getRegexp() != c2.getRegexp()) return false; + } + else { + if (c1.getCode() != c2.getCode()) return false; + if (c1.getBitR() != c2.getBitR()) return false; + if (c1.getHopByHop() != c2.getHopByHop()) return false; + if (c1.getApplicationId() != c2.getApplicationId()) return false; + if (c1.getSessionId() != c2.getSessionId()) return false; + if (c1.getResultCode() != c2.getResultCode()) return false; + if (c1.getMsisdn() != c2.getMsisdn()) return false; + if (c1.getImsi() != c2.getImsi()) return false; + if (c1.getServiceContextId() != c2.getServiceContextId()) return false; + } + + return true; + } + + + + const Type::_v &getType() const throw() { return a_type; } // Generic const std::string & getRegexp() const throw() { return a_regexp; } @@ -100,5 +125,8 @@ class TestCondition { std::string a_serviceContextId; }; +} +} #endif + diff --git a/example/diameter/launcher/testing/TestManager.hpp b/include/anna/testing/TestManager.hpp similarity index 89% rename from example/diameter/launcher/testing/TestManager.hpp rename to include/anna/testing/TestManager.hpp index d1cc1c1..a1cf8ed 100644 --- a/example/diameter/launcher/testing/TestManager.hpp +++ b/include/anna/testing/TestManager.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestManager_hpp -#define example_diameter_launcher_TestManager_hpp +#ifndef anna_testing_TestManager_hpp +#define anna_testing_TestManager_hpp // Project #include @@ -16,10 +16,8 @@ #include #include #include - -// Process -#include -#include +#include +#include namespace anna { @@ -34,13 +32,13 @@ namespace anna { class ServerSession; } } -} + +namespace testing { class TestClock; class TestCase; class TestCaseStep; -class OriginHost; typedef std::map test_pool_t; @@ -91,7 +89,6 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto int a_synchronousAmount; TestClock *a_clock; bool tick() throw(); - bool execTestCases(int sync_amount) throw(); bool nextTestCase() throw(); // Test timers @@ -149,8 +146,7 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto bool getDumpSuccessReports() const throw() { return a_dumpSuccessReports; } // Helper to calculate time interval and synchronous amount of execution tests to guarantee the input rate (tests per second) - // through the time manager which has a minimum resolution of ADML minimum resolution. The first call to this method will - // start the time trigger system and check for new test cases to be launched. + // through the time manager. The first call to this method will start the time trigger system and check for new test cases to be launched. bool configureTTPS(int testTicksPerSecond) throw(); bool clearPool() throw(); @@ -170,8 +166,10 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto // Main logic TestCase *getTestCaseFromSessionId(const anna::DataBlock &message, std::string &sessionId) throw(); TestCase *getTestCaseFromSubscriberId(const anna::DataBlock &message, std::string &subscriberId) throw(); - void receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException); - void receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException); + void receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException); + void receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException); + + bool execTestCases(int sync_amount) throw(); anna::xml::Node* asXML(anna::xml::Node* parent) const throw(); std::string asXMLString() const throw(); @@ -186,7 +184,10 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto friend class TestStepTimeout; // createTimer friend class TestStepDelay; // createTimer friend class TestClock; // tick - friend class Launcher; // tick }; +} +} + #endif + diff --git a/example/diameter/launcher/testing/TestStep.hpp b/include/anna/testing/TestStep.hpp similarity index 95% rename from example/diameter/launcher/testing/TestStep.hpp rename to include/anna/testing/TestStep.hpp index 75cbae3..34af880 100644 --- a/example/diameter/launcher/testing/TestStep.hpp +++ b/include/anna/testing/TestStep.hpp @@ -6,8 +6,8 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestStep_hpp -#define example_diameter_launcher_TestStep_hpp +#ifndef anna_testing_TestStep_hpp +#define anna_testing_TestStep_hpp // Standard #include @@ -16,13 +16,8 @@ // Project #include -#include -#include - -// Process -#include - - +#include +#include namespace anna { @@ -36,15 +31,16 @@ namespace anna { class Message; } namespace comm { + class OriginHost; class ClientSession; class ServerSession; } } -} + +namespace testing { class TestCase; class TestTimer; -class OriginHost; class TestStep { @@ -122,7 +118,7 @@ class TestStepSendxml : public TestStep { protected: // possible end points: - OriginHost *a_originHost; + anna::diameter::comm::OriginHost *a_originHost; // Step number reference ('wait for request' step) int a_waitForRequestStepNumber; @@ -138,8 +134,8 @@ class TestStepSendxml : public TestStep { ~TestStepSendxml() {;} // setter & getters - void setOriginHost(OriginHost *host) throw() { a_originHost = host; } - OriginHost *getOriginHost() const throw() { return a_originHost; } + void setOriginHost(anna::diameter::comm::OriginHost *host) throw() { a_originHost = host; } + anna::diameter::comm::OriginHost *getOriginHost() const throw() { return a_originHost; } void setWaitForRequestStepNumber(int stepNumber) throw() { a_waitForRequestStepNumber = stepNumber; } int getWaitForRequestStepNumber() const throw() { return a_waitForRequestStepNumber; } void setMsgDataBlock(const anna::DataBlock &db) throw() { a_message = db; } @@ -259,5 +255,8 @@ class TestStepCmd : public TestStep { anna::xml::Node* asXML(anna::xml::Node* parent) throw(); }; +} +} #endif + diff --git a/example/diameter/launcher/testing/TestTimer.hpp b/include/anna/testing/TestTimer.hpp similarity index 92% rename from example/diameter/launcher/testing/TestTimer.hpp rename to include/anna/testing/TestTimer.hpp index 3f1b5eb..54ece7b 100644 --- a/example/diameter/launcher/testing/TestTimer.hpp +++ b/include/anna/testing/TestTimer.hpp @@ -6,14 +6,18 @@ // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // -#ifndef example_diameter_launcher_TestTimer_hpp -#define example_diameter_launcher_TestTimer_hpp +#ifndef anna_testing_TestTimer_hpp +#define anna_testing_TestTimer_hpp #include #include #include +namespace anna { + +namespace testing { + class TestStep; @@ -44,5 +48,8 @@ private: friend class anna::Allocator; }; +} +} + #endif diff --git a/include/anna/testing/defines.hpp b/include/anna/testing/defines.hpp new file mode 100644 index 0000000..6dfa42b --- /dev/null +++ b/include/anna/testing/defines.hpp @@ -0,0 +1,18 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +#ifndef anna_testing_defines_hpp +#define anna_testing_defines_hpp + + +#define SH_COMMAND_TAG_FOR_REPLACE__CYCLE_ID "##cycleid##" +#define SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID "##testcaseid##" +#define SH_COMMAND_TAG_FOR_REPLACE__TESTSTEP_ID "##teststepid##" + +#endif + diff --git a/source/diameter.comm/Engine.cpp b/source/diameter.comm/Engine.cpp index d43da75..56aa1b6 100644 --- a/source/diameter.comm/Engine.cpp +++ b/source/diameter.comm/Engine.cpp @@ -64,6 +64,7 @@ comm::Engine::Engine(const char *className, const stack::Dictionary *baseProtoco anna::diameter::sccs::activate(); a_originRealm = anna::functions::getDomainname(); a_originHost = anna::functions::getHostname(); + a_ceaPathfile = ""; // Internal base protocol codec engine: a_baseProtocolCodecEngine.setValidationMode(anna::diameter::codec::Engine::ValidationMode::Always); // default was: after decoding @@ -115,8 +116,8 @@ void comm::Engine::setClientCERandDWR(const std::string & cer, const std::string // * [Acct-Application-Id] 259 Unsigned32 anna::diameter::codec::Message diameterCER(getBaseProtocolCodecEngine()); int applicationId = 0 /*anna::diameter::helpers::APPID__3GPP_Rx*/; // Unsigned32 - std::string OH = getOriginHost(); - std::string OR = getOriginRealm(); + std::string OH = getOriginHostName(); + std::string OR = getOriginRealmName(); std::string hostIP = anna::functions::getHostnameIP(); // Address int vendorId = anna::diameter::helpers::VENDORID__tgpp; // Unsigned32 std::string productName = "ANNA Diameter Client"; // UTF8String @@ -768,13 +769,13 @@ int comm::Engine::getOTARequestsForLocalServers() const throw() { } -void comm::Engine::setOriginRealm(const std::string & originRealm) throw() { - a_originRealm = ((originRealm != "") ? originRealm : anna::functions::getDomainname()); +void comm::Engine::setOriginRealmName(const std::string & originRealmName) throw() { + a_originRealm = ((originRealmName != "") ? originRealmName : anna::functions::getDomainname()); } -void comm::Engine::setOriginHost(const std::string & originHost) throw() { - a_originHost = ((originHost != "") ? originHost : anna::functions::getHostname()); +void comm::Engine::setOriginHostName(const std::string & originHostName) throw() { + a_originHost = ((originHostName != "") ? originHostName : anna::functions::getHostname()); } @@ -927,9 +928,9 @@ void comm::Engine::availabilityLostForEntities() throw() { a_availableForEntities = false; LOGDEBUG( std::string msg = "diameter::comm::Engine { Origin-Realm: "; - msg += getOriginRealm(); + msg += getOriginRealmName(); msg += " | Origin-Host: "; - msg += getOriginHost(); + msg += getOriginHostName(); msg += " } has lost its availability for entities"; anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); @@ -946,9 +947,9 @@ void comm::Engine::availabilityRecoveredForEntities() throw() { a_availableForEntities = true; LOGDEBUG( std::string msg = "diameter::comm::Engine { Origin-Realm: "; - msg += getOriginRealm(); + msg += getOriginRealmName(); msg += " | Origin-Host: "; - msg += getOriginHost(); + msg += getOriginHostName(); msg += " } has recovered its availability for entities"; anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); @@ -965,9 +966,9 @@ void comm::Engine::availabilityLostForLocalServers() throw() { a_availableForLocalServers = false; LOGDEBUG( std::string msg = "diameter::comm::Engine { Origin-Realm: "; - msg += getOriginRealm(); + msg += getOriginRealmName(); msg += " | Origin-Host: "; - msg += getOriginHost(); + msg += getOriginHostName(); msg += " } has lost its availability for local servers"; anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); @@ -984,9 +985,9 @@ void comm::Engine::availabilityRecoveredForLocalServers() throw() { a_availableForLocalServers = true; LOGDEBUG( std::string msg = "diameter::comm::Engine { Origin-Realm: "; - msg += getOriginRealm(); + msg += getOriginRealmName(); msg += " | Origin-Host: "; - msg += getOriginHost(); + msg += getOriginHostName(); msg += " } has recovered its availability for local servers"; anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); @@ -1102,11 +1103,30 @@ void comm::Engine::readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) th } -void comm::Engine::readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) throw() { +void comm::Engine::readCEA(anna::DataBlock &cea, const anna::DataBlock &cer) throw() { // Check for base protocol codec engine health: assertBaseProtocolHealth(); + if (a_ceaPathfile != "") { + anna::diameter::codec::Message diameterCEA(getBaseProtocolCodecEngine()); + + try { + diameterCEA.loadXML(a_ceaPathfile); + diameterCEA.setHopByHop(anna::diameter::codec::functions::getHopByHop(cer)); + diameterCEA.setEndToEnd(anna::diameter::codec::functions::getEndToEnd(cer)); + cea = diameterCEA.code(); + + } catch(anna::RuntimeException &ex) { + ex.trace(); + LOGWARNING(anna::Logger::warning("CEA file not found or unable to parse. Encoding harcoded default version ...", ANNA_FILE_LOCATION)); + //return anna::diameter::comm::Engine::readCEA(cea, cer); + // will fail with empty cea + } + + return; + } + // Default CEA implementation: // // 'Capabilities-Exchange-Answer' (257,answer) diff --git a/source/diameter.comm/Entity.cpp b/source/diameter.comm/Entity.cpp index 23b8a31..d5b3dd3 100644 --- a/source/diameter.comm/Entity.cpp +++ b/source/diameter.comm/Entity.cpp @@ -39,6 +39,7 @@ void Entity::initialize() throw() { a_description = ""; a_category = 0; a_lastUsedResource = NULL; + a_balance = false; } @@ -74,6 +75,9 @@ throw(anna::RuntimeException) { int Entity::readSocketId(const Message* message, int maxClientSessions) const throw() { + + if(a_sessionBasedModelsType == SessionBasedModelsType::RoundRobin) return -1; // IEC also would return -1 + try { // Service-Context-Id: anna::diameter::helpers::dcca::ChargingContext::_v chargingContext; @@ -88,7 +92,12 @@ int Entity::readSocketId(const Message* message, int maxClientSessions) const th std::string diameterIdentity, optional; anna::U32 high, low; anna::diameter::helpers::base::functions::decodeSessionId(sid, diameterIdentity, high, low /* context-teid */, optional); - return (low % maxClientSessions); + + if(a_sessionBasedModelsType == SessionBasedModelsType::SessionIdLowPart) return (low % maxClientSessions); + + if(a_sessionBasedModelsType == SessionBasedModelsType::SessionIdHighPart) return (high % maxClientSessions); + + if(a_sessionBasedModelsType == SessionBasedModelsType::SessionIdOptionalPart) return (atoi(optional.c_str()) % maxClientSessions); } case anna::diameter::helpers::dcca::ChargingContext::SMS: case anna::diameter::helpers::dcca::ChargingContext::MMS: @@ -108,7 +117,7 @@ int Entity::readSocketId(const Message* message, int maxClientSessions) const th } -bool Entity::send(const Message* message, bool balance) throw(anna::RuntimeException) { +bool Entity::send(const Message* message) throw(anna::RuntimeException) { LOGMETHOD(anna::TraceMethod tttm("diameter::comm::Entity", "send", ANNA_FILE_LOCATION)); assertReady(); // Carried socket id (forwarding/proxy features): @@ -137,7 +146,7 @@ bool Entity::send(const Message* message, bool balance) throw(anna::RuntimeExcep //////////////////////////////////////////////////////////////////////////////////////// // Balance - if(balance) { + if(a_balance) { for(int k = 0; k < getMaxServers(); k++) { // try round-robin only over one cycle, // no matter where you are: don't repeat same server if(a_deliveryIterator == end()) a_deliveryIterator = begin(); @@ -263,6 +272,11 @@ void Entity::close(bool destroy) throw(anna::RuntimeException) { a_engine->closeServer(*it, destroy); } +const char* Entity::asText(const SessionBasedModelsType::_v sbmt) +throw() { + static const char* text [] = { "RoundRobin", "SessionIdOptionalPart", "SessionIdHighPart", "SessionIdLowPart" }; + return text [sbmt]; +} socket_v Entity::getAddressPortList() const throw() { socket_v result; @@ -335,8 +349,8 @@ void Entity::eventRequestRetransmission(const ClientSession* clientSession, Mess std::string Entity::asString() const throw() { std::string result("diameter::comm::Entity { "); - std::string originRealm = a_engine->getOriginRealm(); - std::string originHost = a_engine->getOriginHost(); + std::string originRealm = a_engine->getOriginRealmName(); + std::string originHost = a_engine->getOriginHostName(); result += "Parent Engine Origin-Realm: "; result += (originRealm != "") ? originRealm:""; @@ -366,6 +380,8 @@ std::string Entity::asString() const throw() { result += a_lastOutgoingActivityTime.asString(); result += " | Hidden: "; result += (hidden() ? "yes" : "no"); + result += " | SessionBasedModelsType: "; + result += asText(a_sessionBasedModelsType); result += "\n"; for(std::vector::const_iterator it = begin(); it != end(); it++) { @@ -378,8 +394,8 @@ std::string Entity::asString() const throw() { anna::xml::Node* Entity::asXML(anna::xml::Node* parent) const throw() { anna::xml::Node* result = parent->createChild("diameter.Entity"); - std::string originRealm = a_engine->getOriginRealm(); - std::string originHost = a_engine->getOriginHost(); + std::string originRealm = a_engine->getOriginRealmName(); + std::string originHost = a_engine->getOriginHostName(); if(originRealm != "") result->createAttribute("ParentEngineOriginRealm", originRealm); if(originHost != "") result->createAttribute("ParentEngineOriginHost", originHost); @@ -396,6 +412,7 @@ anna::xml::Node* Entity::asXML(anna::xml::Node* parent) const throw() { result->createAttribute("LastIncomingActivityTime", a_lastIncomingActivityTime.asString()); result->createAttribute("LastOutgoingActivityTime", a_lastOutgoingActivityTime.asString()); result->createAttribute("Hidden", hidden() ? "yes" : "no"); + result->createAttribute("SessionBasedModelsType:", asText(a_sessionBasedModelsType)); anna::xml::Node* servers = result->createChild("Entity.Servers"); for(std::vector::const_iterator it = begin(); it != end(); it++) diff --git a/source/diameter.comm/LocalServer.cpp b/source/diameter.comm/LocalServer.cpp index 0e2bc2e..9e03084 100644 --- a/source/diameter.comm/LocalServer.cpp +++ b/source/diameter.comm/LocalServer.cpp @@ -50,9 +50,9 @@ void LocalServer::initializeStatisticResources() throw() { std::string accName = "local server '"; accName += anna::functions::socketLiteralAsString(a_key.first, a_key.second); accName += "' on origin-realm '"; - accName += a_engine ? a_engine->getOriginRealm() : "unknown"; // it should be known (createServer) + accName += a_engine ? a_engine->getOriginRealmName() : "unknown"; // it should be known (createServer) accName += "' and origin-host '"; - accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer) + accName += a_engine ? a_engine->getOriginHostName() : "unknown"; // it should be known (createServer) accName += "'"; a_messageStatistics.initialize(accName); } diff --git a/example/diameter/launcher/OriginHost.cpp b/source/diameter.comm/OriginHost.cpp similarity index 89% rename from example/diameter/launcher/OriginHost.cpp rename to source/diameter.comm/OriginHost.cpp index 195edad..ed181bd 100644 --- a/example/diameter/launcher/OriginHost.cpp +++ b/source/diameter.comm/OriginHost.cpp @@ -10,32 +10,23 @@ #include // Project +#include + +#include #include -#include +#include +#include #include #include #include #include -// Process -#include -#include - +using namespace anna::diameter::comm; -namespace anna { - namespace diameter { - namespace stack { - class Dictionary; - } - } -} -OriginHost::OriginHost(const std::string &originHost, unsigned int applicationId, const anna::diameter::stack::Dictionary *baseProtocolDictionary) : - a_originHost(originHost), a_applicationId(applicationId) { +OriginHost::OriginHost(anna::diameter::comm::Engine* commEngine, unsigned int applicationId) : + a_commEngine(commEngine), a_applicationId(applicationId) { - std::string commEngineName = a_originHost + "_DiameterCommEngine"; - a_commEngine = new MyDiameterEngine(commEngineName.c_str(), baseProtocolDictionary); - a_commEngine->setAutoBind(false); // allow to create client-sessions without binding them, in order to set timeouts. a_codecEngine = anna::diameter::codec::EngineManager::instantiate().getCodecEngine(applicationId); // i know, this is going to exist (getCodecEngine is not null) a_logFile = ""; @@ -47,11 +38,6 @@ OriginHost::OriginHost(const std::string &originHost, unsigned int applicationId a_diameterServer = NULL; // Comm resources: - a_allowedInactivityTime = (anna::Millisecond)90000; - a_tcpConnectDelay = (anna::Millisecond)200; - a_answersTimeout = (anna::Millisecond)10000; - a_ceaTimeout = (anna::Millisecond)10000; - a_watchdogPeriod = (anna::Millisecond)30000; a_requestRetransmissions = 0; // Burst @@ -64,25 +50,28 @@ OriginHost::OriginHost(const std::string &originHost, unsigned int applicationId a_burstPopCounter = 0; } +const std::string &OriginHost::getName() const throw() { + return a_commEngine->getOriginHostName(); +} void OriginHost::createEntity(const std::string &entityRepresentation, const anna::Millisecond &bindTimeout, const anna::Millisecond &applicationTimeout) throw(anna::RuntimeException) { anna::socket_v servers = anna::functions::getSocketVectorFromString(entityRepresentation); - std::string entityDescription = "Launcher diameter entity for "; entityDescription += a_originHost; - a_entity = (MyDiameterEntity*)(a_commEngine->createEntity(servers, entityDescription)); + std::string entityDescription = "Launcher diameter entity for "; entityDescription += getName(); + a_entity = (anna::diameter::comm::Entity*)a_commEngine->createEntity(servers, entityDescription); a_entity->setClassCodeTimeout(anna::diameter::comm::ClassCode::Bind, bindTimeout); a_entity->setClassCodeTimeout(anna::diameter::comm::ClassCode::ApplicationMessage, applicationTimeout); } -void OriginHost::startDiameterServer(const std::string &serverRepresentation, int sessions, const anna::Millisecond &inactivityTimeout, const anna::Millisecond &applicationTimeout, const std::string &ceaPathfile) throw(anna::RuntimeException) { +void OriginHost::createDiameterServer(const std::string &serverRepresentation, int sessions, const anna::Millisecond &inactivityTimeout, const anna::Millisecond &applicationTimeout, const std::string &ceaPathfile) throw(anna::RuntimeException) { //if(sessions <= 0) return; negative implies no limit for accepted connections std::string address; int port; anna::functions::getAddressAndPortFromSocketLiteral(serverRepresentation, address, port); - std::string serverDescription = "Launcher diameter local server for "; serverDescription += a_originHost; + std::string serverDescription = "Launcher diameter local server for "; serverDescription += getName(); a_commEngine->setCEA(ceaPathfile); - a_diameterServer = (MyLocalServer*)(a_commEngine->createLocalServer(address, port, sessions)); + a_diameterServer = (anna::diameter::comm::LocalServer*)(a_commEngine->createLocalServer(address, port, sessions)); // we could set sessions = 0, and after application run(), use setMaxConnections(real sessions) // over the local server in order to start it. @@ -152,7 +141,7 @@ void OriginHost::writeLogFile(const anna::diameter::codec::Message &decodedMessa // .......xml std::string name = anna::functions::asString((anna::Millisecond)anna::functions::millisecond()); name += "."; - name += getMyDiameterEngine()->getOriginHost(); + name += getCommEngine()->getOriginHostName(); name += "."; name += anna::functions::asString(decodedMessage.getHopByHop()); name += "."; @@ -337,7 +326,7 @@ bool OriginHost::sendBurstMessage(bool anyway) throw() { a_burstDeliveryIt++; bool dot = true; // sending - bool result = a_entity->send(msg, anna::CommandLine::instantiate().exists("balance")); + bool result = a_entity->send(msg); if(burstLogEnabled()) { if(a_burstMessages.size() >= 100) @@ -404,9 +393,9 @@ anna::xml::Node* OriginHost::asXML(anna::xml::Node* parent) const throw() { anna::xml::Node* result = parent->createChild("OriginHost"); - result->createAttribute("originHost", a_originHost); + result->createAttribute("originHost", getName()); result->createAttribute("ApplicationId", a_applicationId); - result->createAttribute("originRealm", a_commEngine->getOriginRealm()); + result->createAttribute("originRealm", a_commEngine->getOriginRealmName()); result->createAttribute("LogFile", a_logFile); result->createAttribute("SplitLog", a_splitLog ? "yes" : "no"); result->createAttribute("DetailedLog", a_detailedLog ? "yes" : "no"); diff --git a/source/diameter.comm/Server.cpp b/source/diameter.comm/Server.cpp index 1ba8356..3207094 100644 --- a/source/diameter.comm/Server.cpp +++ b/source/diameter.comm/Server.cpp @@ -43,9 +43,9 @@ void Server::initializeStatisticResources() throw() { std::string accName = "remote server '"; accName += anna::functions::socketLiteralAsString(a_socket.first, a_socket.second); accName += "' from origin-realm '"; - accName += a_engine ? a_engine->getOriginRealm() : "unknown"; // it should be known (createServer) + accName += a_engine ? a_engine->getOriginRealmName() : "unknown"; // it should be known (createServer) accName += "' and origin-host '"; - accName += a_engine ? a_engine->getOriginHost() : "unknown"; // it should be known (createServer) + accName += a_engine ? a_engine->getOriginHostName() : "unknown"; // it should be known (createServer) accName += "'"; a_messageStatistics.initialize(accName); } diff --git a/example/diameter/launcher/ProgrammedAnswers.cpp b/source/diameter/codec/MessagesDeque.cpp similarity index 78% rename from example/diameter/launcher/ProgrammedAnswers.cpp rename to source/diameter/codec/MessagesDeque.cpp index b2b89b2..2461e19 100644 --- a/example/diameter/launcher/ProgrammedAnswers.cpp +++ b/source/diameter/codec/MessagesDeque.cpp @@ -15,15 +15,18 @@ #include // Process -#include +#include -void ProgrammedAnswers::clear() throw () { +using namespace anna::diameter::codec; + + +void MessagesDeque::clear() throw () { try { anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate(); anna::diameter::codec::Engine *engine; - for (reacting_answers_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { + for (messages_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { anna::diameter::codec::Message *message = *(it->second->begin()); engine = em.getCodecEngine(message->getApplicationId()); if (engine) { @@ -41,15 +44,16 @@ void ProgrammedAnswers::clear() throw () { } } -void ProgrammedAnswers::dump() throw () { +void MessagesDeque::dump(const char *filenamePrefix) throw () { std::string outfilename, xmlString; - for (reacting_answers_const_iterator it = a_deques.begin(); + for (messages_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { int sequence = 1; for (codec_messages_deque_const_iterator itm = it->second->begin(); itm != it->second->end(); itm++) { - // programmed_answer.. - outfilename = "programmed_answer."; + // message.. + outfilename = filenamePrefix; + outfilename += "."; outfilename += anna::functions::asString(it->first); outfilename += "."; outfilename += anna::functions::asString(sequence++); @@ -62,11 +66,11 @@ void ProgrammedAnswers::dump() throw () { } } -void ProgrammedAnswers::addMessage(int code, anna::diameter::codec::Message *message) throw () { +void MessagesDeque::addMessage(int code, anna::diameter::codec::Message *message) throw () { if (!message) return; // just in case - reacting_answers_const_iterator it = a_deques.find(code); + messages_const_iterator it = a_deques.find(code); if (it != a_deques.end()) { it->second->push_back(message); } else { @@ -76,9 +80,9 @@ void ProgrammedAnswers::addMessage(int code, anna::diameter::codec::Message *mes } } -anna::diameter::codec::Message* ProgrammedAnswers::getMessage(int code) const throw () { //get the front message (begin()), returns NULL if deque is empty +anna::diameter::codec::Message* MessagesDeque::getMessage(int code) const throw () { //get the front message (begin()), returns NULL if deque is empty anna::diameter::codec::Message *result = NULL; - reacting_answers_const_iterator it = a_deques.find(code); + messages_const_iterator it = a_deques.find(code); if (it != a_deques.end()) { if (!it->second->empty()) result = *(it->second->begin()); @@ -86,11 +90,11 @@ anna::diameter::codec::Message* ProgrammedAnswers::getMessage(int code) const th return result; } -void ProgrammedAnswers::nextMessage(int code) throw () { //pops the deque and release the message (when deque is not empty: deque::empty) +void MessagesDeque::nextMessage(int code) throw () { //pops the deque and release the message (when deque is not empty: deque::empty) anna::diameter::codec::Engine *engine; try { - reacting_answers_const_iterator it = a_deques.find(code); + messages_const_iterator it = a_deques.find(code); if (it != a_deques.end()) { if (!it->second->empty()) { anna::diameter::codec::Message *message = *(it->second->begin()); @@ -115,7 +119,7 @@ void ProgrammedAnswers::nextMessage(int code) throw () { //pops the deque and re } } -std::string ProgrammedAnswers::asString(const char *queueName) const throw () { +std::string MessagesDeque::asString(const char *queueName) const throw () { std::string result = ""; std::string aux = "FIFO QUEUE '"; aux += queueName; @@ -123,10 +127,10 @@ std::string ProgrammedAnswers::asString(const char *queueName) const throw () { aux += a_rotate ? "enabled" : "disabled"; result += anna::functions::highlightJustify(aux); if (a_deques.size() != 0) { - for (reacting_answers_const_iterator it = a_deques.begin(); + for (messages_const_iterator it = a_deques.begin(); it != a_deques.end(); it++) { if (it->second->size() != 0) { - aux = "Answer code "; + aux = "Message code "; aux += anna::functions::asString(it->first); result += anna::functions::highlightJustify(aux, anna::functions::TextHighlightMode::OverAndUnderline, diff --git a/source/testing/SConscript b/source/testing/SConscript new file mode 100644 index 0000000..e9ea1e5 --- /dev/null +++ b/source/testing/SConscript @@ -0,0 +1,8 @@ +Import ('env') + +sources = Glob('*.cpp') + +result = env.StaticLibrary ('anna_testing', sources); + +Return ('result') + diff --git a/source/testing/SConstruct b/source/testing/SConstruct new file mode 100644 index 0000000..bc482f0 --- /dev/null +++ b/source/testing/SConstruct @@ -0,0 +1,12 @@ +release = ARGUMENTS.get ('release', 0) + +Import ('env') + +# See http://stackoverflow.com/questions/4693826/scons-binary-directory +if int(release): + result = SConscript ('SConscript', exports='env', variant_dir="release", duplicate=0) +else: + result = SConscript ('SConscript', exports='env', variant_dir="debug", duplicate=0) + +Return ('result') + diff --git a/example/diameter/launcher/testing/TestCase.cpp b/source/testing/TestCase.cpp similarity index 97% rename from example/diameter/launcher/testing/TestCase.cpp rename to source/testing/TestCase.cpp index 087e29b..efaba5c 100644 --- a/example/diameter/launcher/testing/TestCase.cpp +++ b/source/testing/TestCase.cpp @@ -14,18 +14,22 @@ #include // Project +#include +#include + #include #include #include #include +#include #include #include #include #include +#include + -// Process -#include -#include +using namespace anna::testing; /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -265,7 +269,7 @@ void TestCase::addTimeout(const anna::Millisecond &timeout) throw(anna::RuntimeE addStep(step); } -void TestCase::addSendxml2e(const anna::DataBlock &db, OriginHost *host, int stepNumber) throw(anna::RuntimeException) { +void TestCase::addSendxml2e(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) throw(anna::RuntimeException) { assertInitialized(); assertMessage(db, true /* to entity */); @@ -290,7 +294,7 @@ void TestCase::addSendxml2e(const anna::DataBlock &db, OriginHost *host, int ste addStep(step); } -void TestCase::addSendxml2c(const anna::DataBlock &db, OriginHost *host, int stepNumber) throw(anna::RuntimeException) { +void TestCase::addSendxml2c(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) throw(anna::RuntimeException) { assertInitialized(); assertMessage(db, false /* to client */); diff --git a/example/diameter/launcher/testing/TestClock.cpp b/source/testing/TestClock.cpp similarity index 82% rename from example/diameter/launcher/testing/TestClock.cpp rename to source/testing/TestClock.cpp index 885e87e..d949983 100644 --- a/example/diameter/launcher/testing/TestClock.cpp +++ b/source/testing/TestClock.cpp @@ -10,11 +10,11 @@ #include // Process -#include -#include +#include +#include -bool TestClock::tick() throw(anna::RuntimeException) { +bool anna::testing::TestClock::tick() throw(anna::RuntimeException) { return a_manager->tick(); } diff --git a/example/diameter/launcher/testing/TestCondition.cpp b/source/testing/TestCondition.cpp similarity index 86% rename from example/diameter/launcher/testing/TestCondition.cpp rename to source/testing/TestCondition.cpp index ced5db6..ba1db97 100644 --- a/example/diameter/launcher/testing/TestCondition.cpp +++ b/source/testing/TestCondition.cpp @@ -9,6 +9,8 @@ // Standard // Project +#include + #include #include #include @@ -20,8 +22,8 @@ #include #include -// Process -#include + +using namespace anna::testing; const char* TestCondition::asText(const Type::_v type) @@ -37,27 +39,29 @@ bool TestCondition::exists() const throw() { return (a_code != "" || a_bitR != "" || a_hopByHop != "" || a_applicationId != "" || a_sessionId != "" || a_resultCode != "" || a_msisdn != "" || a_imsi != "" || a_serviceContextId != ""); } -bool operator==(const TestCondition &c1, const TestCondition &c2) throw() { +/* +bool anna::testing::operator==(const TestCondition &c1, const TestCondition &c2) throw() { - if (c1.a_type != c2.a_type) return false; + if (c1.getType() != c2.getType()) return false; - if (c1.a_type == TestCondition::Type::Generic) { - if (c1.a_regexp != c2.a_regexp) return false; + if (c1.getType() == TestCondition::Type::Generic) { + if (c1.getRegexp() != c2.getRegexp()) return false; } else { - if (c1.a_code != c2.a_code) return false; - if (c1.a_bitR != c2.a_bitR) return false; - if (c1.a_hopByHop != c2.a_hopByHop) return false; - if (c1.a_applicationId != c2.a_applicationId) return false; - if (c1.a_sessionId != c2.a_sessionId) return false; - if (c1.a_resultCode != c2.a_resultCode) return false; - if (c1.a_msisdn != c2.a_msisdn) return false; - if (c1.a_imsi != c2.a_imsi) return false; - if (c1.a_serviceContextId != c2.a_serviceContextId) return false; + if (c1.getCode() != c2.getCode()) return false; + if (c1.getBitR() != c2.getBitR()) return false; + if (c1.getHopByHop() != c2.getHopByHop()) return false; + if (c1.getApplicationId() != c2.getApplicationId()) return false; + if (c1.getSessionId() != c2.getSessionId()) return false; + if (c1.getResultCode() != c2.getResultCode()) return false; + if (c1.getMsisdn() != c2.getMsisdn()) return false; + if (c1.getImsi() != c2.getImsi()) return false; + if (c1.getServiceContextId() != c2.getServiceContextId()) return false; } return true; } +*/ bool TestCondition::comply(const anna::DataBlock &message/*, bool matchSessionId*/) const throw() { diff --git a/example/diameter/launcher/testing/TestManager.cpp b/source/testing/TestManager.cpp similarity index 91% rename from example/diameter/launcher/testing/TestManager.cpp rename to source/testing/TestManager.cpp index cf768ab..8f1a728 100644 --- a/example/diameter/launcher/testing/TestManager.cpp +++ b/source/testing/TestManager.cpp @@ -10,6 +10,8 @@ #include // Project +#include + #include #include #include @@ -17,19 +19,18 @@ #include #include #include +#include #include #include - -// Process -#include -#include -#include -#include +#include +#include +#include -class TestTimer; +//class TestTimer; +using namespace anna::testing; /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -203,22 +204,19 @@ bool TestManager::configureTTPS(int testTicksPerSecond) throw() { return false; } - anna::Millisecond admlTimeInterval = anna::Millisecond(1000 / testTicksPerSecond); + anna::Millisecond applicationTimeInterval = anna::Millisecond(1000 / testTicksPerSecond); a_synchronousAmount = 1; - if (admlTimeInterval < anna::Millisecond(1)) { + if (applicationTimeInterval < anna::Millisecond(1)) { LOGWARNING(anna::Logger::warning("Not allowed to configure more than 1000 events per second for for triggering testing system", ANNA_FILE_LOCATION)); return false; } - Launcher& my_app = static_cast (anna::app::functions::getApp()); - const anna::Millisecond &admlMinResolution = my_app.getADMLMinResolution(); - - if (admlTimeInterval < admlMinResolution) { - int maximumObtained = 1000 / (int)admlMinResolution; + if (applicationTimeInterval < a_timeController->getResolution()) { + int maximumObtained = 1000 / (int)(a_timeController->getResolution()); a_synchronousAmount = ceil((double)testTicksPerSecond/maximumObtained); // calculate again: - admlTimeInterval = anna::Millisecond(a_synchronousAmount * 1000 / testTicksPerSecond); + applicationTimeInterval = anna::Millisecond(a_synchronousAmount * 1000 / testTicksPerSecond); } if (a_synchronousAmount > 1) { @@ -226,9 +224,9 @@ bool TestManager::configureTTPS(int testTicksPerSecond) throw() { std::string msg = anna::functions::asString("Desired testing time trigger rate (%d events per second) requires more than one sending per event (%d every %lld milliseconds). Consider launch more instances with lower rate (for example %d ADML processes with %d ttps), or configure %d or more sockets to the remote endpoints to avoid burst sendings", testTicksPerSecond, a_synchronousAmount, - admlTimeInterval.getValue(), + applicationTimeInterval.getValue(), a_synchronousAmount, - 1000/admlTimeInterval, + 1000/applicationTimeInterval, a_synchronousAmount); anna::Logger::warning(msg, ANNA_FILE_LOCATION); @@ -236,10 +234,10 @@ bool TestManager::configureTTPS(int testTicksPerSecond) throw() { } if (a_clock) { - a_clock->setTimeout(admlTimeInterval); + a_clock->setTimeout(applicationTimeInterval); } else { - a_clock = new TestClock("Testing clock", admlTimeInterval, this); // clock + a_clock = new TestClock("Testing clock", applicationTimeInterval, this); // clock } if (!a_clock->isActive()) a_timeController->activate(a_clock); @@ -410,7 +408,7 @@ TestCase *TestManager::getTestCaseFromSubscriberId(const anna::DataBlock &messag return NULL; } -void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException) { +void TestManager::receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException) { // Testing disabled: if (!tests()) return; @@ -435,12 +433,6 @@ void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *hos static anna::diameter::codec::Message codecMsg; codecMsg.decode(message); hint += "\n"; hint += codecMsg.asXMLString(); - - // // Host checking: - // std::string messageOH = message.getAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->getValue(); - // if (messageOH != host->getName()) { - // LOGWARNING(anna::Logger::warning(anna::functions::asString("Received message from host '%s', with different Origin-Host: %s", host->getName().c_str(), messageOH.c_str()), ANNA_FILE_LOCATION)); - // } } catch (anna::RuntimeException &ex) { ex.trace(); @@ -456,7 +448,7 @@ void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *hos } } -void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *host, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException) { +void TestManager::receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException) { // Testing disabled: if (!tests()) return; @@ -481,12 +473,6 @@ void TestManager::receiveMessage(const anna::DataBlock &message, OriginHost *hos static anna::diameter::codec::Message codecMsg; codecMsg.decode(message); hint += "\n"; hint += codecMsg.asXMLString(); - - // // Host checking: - // std::string messageOH = message.getAvp(anna::diameter::helpers::base::AVPID__Origin_Host)->getDiameterIdentity()->getValue(); - // if (messageOH != host->getName()) { - // LOGWARNING(anna::Logger::warning(anna::functions::asString("Received message from host '%s', with different Origin-Host: %s", host->getName().c_str(), messageOH.c_str()), ANNA_FILE_LOCATION)); - // } } catch (anna::RuntimeException &ex) { ex.trace(); diff --git a/example/diameter/launcher/testing/TestStep.cpp b/source/testing/TestStep.cpp similarity index 97% rename from example/diameter/launcher/testing/TestStep.cpp rename to source/testing/TestStep.cpp index fdbd798..7e96926 100644 --- a/example/diameter/launcher/testing/TestStep.cpp +++ b/source/testing/TestStep.cpp @@ -22,9 +22,19 @@ // Project +#include + +#include +#include +#include +#include +#include +#include #include #include #include +#include +#include #include #include #include @@ -32,15 +42,9 @@ #include #include -// Process -#include -#include -#include -#include -#include -#include -#include -#include + + +using namespace anna::testing; namespace { @@ -354,8 +358,8 @@ throw() { bool TestStepSendxml::do_execute() throw() { bool success = false; std::string failReason; - MyDiameterEntity *entity = a_originHost->getEntity(); // by default - MyLocalServer *localServer = a_originHost->getDiameterServer(); // by default + anna::diameter::comm::Entity *entity = a_originHost->getEntity(); // by default + anna::diameter::comm::LocalServer *localServer = a_originHost->getDiameterServer(); // by default const TestStepWait *tsw = NULL; anna::diameter::comm::Message *msg = a_originHost->createCommMessage(); diff --git a/example/diameter/launcher/testing/TestTimer.cpp b/source/testing/TestTimer.cpp similarity index 93% rename from example/diameter/launcher/testing/TestTimer.cpp rename to source/testing/TestTimer.cpp index abe8b4d..47c4ccc 100644 --- a/example/diameter/launcher/testing/TestTimer.cpp +++ b/source/testing/TestTimer.cpp @@ -7,19 +7,19 @@ // Project +#include #include -// Process -#include -#include - // Standard #include +// Project +#include + using namespace std; using namespace anna; - +using namespace anna::testing; void TestTimer::expire(anna::timex::Engine*) throw(anna::RuntimeException) { -- 2.20.1