1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
13 #include <EventOperation.hpp>
14 #include <Launcher.hpp>
15 #include <Procedure.hpp>
16 #include <MyDiameterEngine.hpp>
17 #include <MyLocalServer.hpp>
18 #include <anna/testing/TestManager.hpp>
22 #include <unistd.h> // chdir
25 #include <anna/diameter.comm/OriginHost.hpp>
26 #include <anna/json/functions.hpp>
27 #include <anna/diameter/codec/Message.hpp>
28 #include <anna/diameter/helpers/base/functions.hpp>
29 #include <anna/time/functions.hpp>
30 #include <anna/core/functions.hpp>
31 #include <anna/xml/xml.hpp>
32 #include <anna/diameter.comm/Message.hpp>
38 bool EventOperation::node(std::string &response, const std::string & name) {
40 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
42 anna::diameter::comm::OriginHost *workingNode;
43 try { workingNode = my_app.getWorkingNode(); } catch(anna::RuntimeException &ex) { ex.trace(); }
46 if (my_app.setWorkingNode(name)) {
47 response = anna::functions::asString("Forced node is now '%s'", name.c_str());
48 my_app.setOperatedHost(my_app.getWorkingNode()); // now is the new one
51 response = anna::functions::asString("Node '%s' invalid. Nothing done", name.c_str());
57 response = anna::functions::encodeBase64(workingNode->asXMLString());
60 response = workingNode->asXMLString();
64 response = "Working node is automatic";
70 bool EventOperation::node_auto(std::string &response) {
72 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
75 response = "Working node has been set to automatic";
80 ////////////////////////
81 // Parsing operations //
82 ////////////////////////
83 bool EventOperation::code(std::string &response, const std::string & diameterJson) {
86 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
88 response += "json to xml failed, unable to encode !";
91 anna::diameter::codec::Message codecMsg; // auxiliary codec message
92 codecMsg.loadXMLString(diameterXml);
93 response = anna::functions::asHexString(codecMsg.code());
98 bool EventOperation::decode(std::string &response, const std::string & diameterHex) {
100 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
102 anna::DataBlock db_aux(true);
103 anna::functions::fromHexString(diameterHex, db_aux);
104 anna::diameter::codec::Message codecMsg; // auxiliary codec message
106 codecMsg.decode(db_aux);
107 std::string xmlString = codecMsg.asXMLString();
108 response = anna::functions::encodeBase64(xmlString);
110 catch(anna::RuntimeException &ex) { ex.trace(); }
115 bool EventOperation::loadmsg(std::string &response, const std::string & diameterJson) {
118 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
120 response += "json to xml failed, unable to load message !";
123 anna::diameter::codec::Message codecMsg; // auxiliary codec message
124 codecMsg.loadXMLString(diameterXml);
125 response = anna::functions::encodeBase64(codecMsg.asXMLString());
133 bool EventOperation::services(std::string &response, const std::string & servicesJson) {
135 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
138 std::string servicesXml = anna::json::functions::json2xml(servicesJson, success);
140 response += "json to xml failed, unable to load services !";
145 my_app.loadServicesFromXMLString(servicesXml, true /* bind entities */);
147 catch(anna::RuntimeException &ex) {
149 response += "loaded services with errors";
152 response = "loaded services correctly";
157 bool EventOperation::diameterServerSessions(std::string &response, int sessions) {
159 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
162 my_app.getOperatedServer()->setMaxConnections(sessions);
164 catch(anna::RuntimeException &ex) {
166 response += "fail to operate the server";
169 response = "new sessions successfully established on operated diameter server";
174 bool EventOperation::change_dir(std::string &response, const std::string & directory) {
176 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
178 std::string dir = directory;
179 if (dir == "") dir = my_app.getInitialWorkingDirectory();
180 bool result = (chdir(dir.c_str()) == 0);
183 response = "New execution directory configured: ";
185 response = "Cannot assign provided execution directory: ";
191 ////////////////////////////////
192 // Client sessions visibility //
193 ////////////////////////////////
194 bool EventOperation::visibility(std::string &response, const std::string & action, const std::string &addressPort, int socket) {
196 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
200 if(addressPort != "") {
202 std::string key = addressPort;
204 key += anna::functions::asString(socket);
206 if(action == "hide") my_app.getOperatedEngine()->findClientSession(key)->hide();
207 if(action == "show") my_app.getOperatedEngine()->findClientSession(key)->show();
208 if(action == "hidden") response = my_app.getOperatedEngine()->findClientSession(key)->hidden() ? "true" : "false";
209 if(action == "shown") response = my_app.getOperatedEngine()->findClientSession(key)->shown() ? "true" : "false";
213 anna::functions::getAddressAndPortFromSocketLiteral(addressPort, address, port);
215 if(action == "hide") my_app.getOperatedEngine()->findServer(address, port)->hide();
216 if(action == "show") my_app.getOperatedEngine()->findServer(address, port)->show();
217 if(action == "hidden") response = my_app.getOperatedEngine()->findServer(address, port)->hidden() ? "true" : "false";
218 if(action == "shown") response = my_app.getOperatedEngine()->findServer(address, port)->shown() ? "true" : "false";
221 if(action == "hide") my_app.getOperatedEntity()->hide();
222 if(action == "show") my_app.getOperatedEntity()->show();
223 if(action == "hidden") response = my_app.getOperatedEntity()->hidden() ? "true" : "false";
224 if(action == "shown") response = my_app.getOperatedEntity()->shown() ? "true" : "false";
234 bool EventOperation::collect(std::string &response) {
236 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
238 my_app.resetCounters();
239 my_app.resetStatistics();
240 response = "All process counters & statistic information have been reset";
245 bool EventOperation::context(std::string &response, const std::string & targetFile) {
247 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
249 std::string contextFile = (targetFile != "") ? targetFile : anna::functions::asString("/var/tmp/anna.context.%05d", my_app.getPid());
250 my_app.writeContext(contextFile);
251 response = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str());
256 bool EventOperation::forceCountersRecord(std::string &response) {
258 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
260 my_app.forceCountersRecord();
261 response = "Current counters have been dump to disk";
266 bool EventOperation::log_statistics_samples(std::string &response, const std::string & list) {
268 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
270 my_app.logStatisticsSamples(list);
271 response = anna::functions::asString("Log statistics samples for '%s' concepts", list.c_str());
276 bool EventOperation::show_oam(std::string &response) {
278 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
280 anna::xml::Node root("root");
281 response = anna::xml::Compiler().apply(my_app.oamAsXML(&root));
283 response = anna::functions::encodeBase64(response);
288 bool EventOperation::show_stats(std::string &response) {
290 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
292 anna::xml::Node root("root");
293 response = anna::xml::Compiler().apply(my_app.statsAsXML(&root));
295 response = anna::functions::encodeBase64(response);
300 /////////////////////
301 // Flow operations //
302 /////////////////////
303 bool EventOperation::sendmsg_hex_2e(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
305 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
306 anna::diameter::codec::Message codecMsg; // auxiliary codec message
308 anna::diameter::comm::Message *msg;
311 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
313 response += "json to xml failed, unable to send message !";
316 codecMsg.loadXMLString(diameterXml);
318 my_app.updateOperatedOriginHostWithMessage(codecMsg);
319 msg = my_app.getOperatedHost()->createCommMessage();
322 catch(anna::RuntimeException &ex) {
324 response += "invalid operated host";
327 try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
328 msg->setBody(codecMsg.code());
330 // Get DataBlock from hex content:
331 anna::DataBlock db_aux(true);
332 std::string hexString = diameterJson_or_Hex;
333 hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
335 std::string msg = "Hex string (remove colons if exists): ";
337 anna::Logger::debug(msg, ANNA_FILE_LOCATION);
339 anna::functions::fromHexString(hexString, db_aux); // could launch exception
341 my_app.updateOperatedOriginHostWithMessage(db_aux);
342 msg = my_app.getOperatedHost()->createCommMessage();
344 catch(anna::RuntimeException &ex) {
346 response += "invalid operated host";
349 msg->setBody(db_aux);
350 try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
353 success = my_app.getOperatedEntity()->send(msg);
354 my_app.getOperatedHost()->releaseCommMessage(msg);
357 if(my_app.getOperatedHost()->logEnabled()) {
358 anna::diameter::comm::Server *usedServer = my_app.getOperatedEntity()->getLastUsedResource();
359 anna::diameter::comm::ClientSession *usedClientSession = usedServer ? usedServer->getLastUsedResource() : NULL;
360 std::string detail = usedClientSession ? usedClientSession->asString() : "[null client session]"; // shouldn't happen
361 my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2e" : "send2eError"), detail);
365 response = "Operation processed"; // could be failed
369 bool EventOperation::sendmsg_hex_2c(std::string &response, const std::string & diameterJson_or_Hex, bool msg_or_hex) {
371 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
372 anna::diameter::codec::Message codecMsg; // auxiliary codec message
374 anna::diameter::comm::Message *msg;
377 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_Hex, success);
379 response += "json to xml failed, unable to send message !";
382 codecMsg.loadXMLString(diameterXml);
384 my_app.updateOperatedOriginHostWithMessage(codecMsg);
385 msg = my_app.getOperatedHost()->createCommMessage();
388 catch(anna::RuntimeException &ex) {
390 response += "invalid operated host";
393 try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); } // at least we need to see validation errors although it will continue sending (see validation mode configured in launcher)
394 msg->setBody(codecMsg.code());
396 // Get DataBlock from hex content:
397 anna::DataBlock db_aux(true);
398 std::string hexString = diameterJson_or_Hex;
399 hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
401 std::string msg = "Hex string (remove colons if exists): ";
403 anna::Logger::debug(msg, ANNA_FILE_LOCATION);
405 anna::functions::fromHexString(hexString, db_aux); // could launch exception
407 my_app.updateOperatedOriginHostWithMessage(db_aux);
408 msg = my_app.getOperatedHost()->createCommMessage();
410 catch(anna::RuntimeException &ex) {
412 response += "invalid operated host";
415 msg->setBody(db_aux);
416 try { if(my_app.getOperatedHost()->logEnabled()) codecMsg.decode(db_aux); } catch(anna::RuntimeException &ex) { ex.trace(); }
419 success = my_app.getOperatedServer()->send(msg);
420 my_app.getOperatedHost()->releaseCommMessage(msg);
423 if(my_app.getOperatedHost()->logEnabled()) {
424 anna::diameter::comm::ServerSession *usedServerSession = my_app.getOperatedServer()->getLastUsedResource();
425 std::string detail = usedServerSession ? usedServerSession->asString() : "[null server session]"; // shouldn't happen
426 my_app.getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
430 response = "Operation processed"; // could be failed
434 bool EventOperation::answermsg_action_2e(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
436 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
437 anna::diameter::codec::Message codecMsg; // auxiliary codec message
438 anna::diameter::codec::Message *message;
443 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
445 response += "json to xml failed, unable to send message !";
448 codecMsg.loadXMLString(diameterXml);
450 my_app.updateOperatedOriginHostWithMessage(codecMsg);
451 message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
452 LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
454 catch(anna::RuntimeException &ex) {
456 response += "invalid operated host";
460 if(message->isRequest()) {
461 response += "cannot program diameter requests. Answer type must be provided";
465 int code = message->getId().first;
466 LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to entity' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
467 response = "Added 'answer to entity' to the FIFO queue corresponding to its message code";
468 my_app.getOperatedEntity()->getReactingAnswers()->addMessage(code, message);
472 if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
473 response = anna::functions::encodeBase64(my_app.getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY"));
474 } else if (diameterJson_or_action == "rotate") {
475 my_app.getOperatedEntity()->getReactingAnswers()->rotate(true);
477 } else if (diameterJson_or_action == "exhaust") {
478 my_app.getOperatedEntity()->getReactingAnswers()->rotate(false);
479 response = "exhaust";
480 } else if (diameterJson_or_action == "clear") {
481 my_app.getOperatedEntity()->getReactingAnswers()->clear();
483 } else if (diameterJson_or_action == "dump") {
484 my_app.getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
493 bool EventOperation::answermsg_action_2c(std::string &response, const std::string & diameterJson_or_action, bool msg_or_action) {
495 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
496 anna::diameter::codec::Message codecMsg; // auxiliary codec message
497 anna::diameter::codec::Message *message;
502 std::string diameterXml = anna::json::functions::json2xml(diameterJson_or_action, success);
504 response += "json to xml failed, unable to send message !";
507 codecMsg.loadXMLString(diameterXml);
509 my_app.updateOperatedOriginHostWithMessage(codecMsg);
510 message = my_app.getOperatedHost()->getCodecEngine()->createMessage(diameterXml, false /* is xml string */); // loads xml again, lesser of two evils
511 LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
513 catch(anna::RuntimeException &ex) {
515 response += "invalid operated host";
519 if(message->isRequest()) {
520 response += "cannot program diameter requests. Answer type must be provided";
524 int code = message->getId().first;
525 LOGDEBUG(anna::Logger::debug("Adding a new programed 'answer to client' to the FIFO queue corresponding to its message code ...", ANNA_FILE_LOCATION));
526 my_app.getOperatedServer()->getReactingAnswers()->addMessage(code, message);
527 response = "Added 'answer to client' to the FIFO queue corresponding to its message code";
531 if(diameterJson_or_action == "list") { // programmed answers FIFO's to stdout
532 response = anna::functions::encodeBase64(my_app.getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT"));
533 } else if (diameterJson_or_action == "rotate") {
534 my_app.getOperatedServer()->getReactingAnswers()->rotate(true);
536 } else if (diameterJson_or_action == "exhaust") {
537 my_app.getOperatedServer()->getReactingAnswers()->rotate(false);
538 response = "exhaust";
539 } else if (diameterJson_or_action == "clear") {
540 my_app.getOperatedServer()->getReactingAnswers()->clear();
542 } else if (diameterJson_or_action == "dump") {
543 my_app.getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
555 bool EventOperation::test_id__description(std::string &response, unsigned int id, const std::string & description) {
557 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
558 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
561 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
562 tc->setDescription(description);
563 response = std::to_string(tc->getId());
565 catch(anna::RuntimeException &ex) {
567 response += "invalid ip-limit";
574 bool EventOperation::test_id__ip_limit(std::string &response, unsigned int id, int amount) {
576 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
577 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
580 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
581 tc->addIpLimit(amount);
582 response = std::to_string(tc->getId());
584 catch(anna::RuntimeException &ex) {
586 response += "invalid ip-limit";
593 bool EventOperation::test_id__timeout(std::string &response, unsigned int id, int msecs) {
595 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
596 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
599 anna::Millisecond timeout = my_app.checkTimeMeasure("Test case timeout", anna::functions::asString(msecs));
600 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
601 tc->addTimeout(timeout);
602 response = std::to_string(tc->getId());
604 catch(anna::RuntimeException &ex) {
606 response += "invalid timeout";
613 bool EventOperation::test_id__sendmsg2e_2c(std::string &response, unsigned int id, bool _2e_or_2c, const std::string & diameterJson, int stepNumber) {
615 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
616 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
619 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
621 response += "json to xml failed, unable to load message !";
624 anna::diameter::codec::Message codecMsg; // auxiliary codec message
625 codecMsg.loadXMLString(diameterXml);
628 if (!codecMsg.isRequest() && (stepNumber == -1))
629 anna::Logger::warning("Step number has not been provided. Take into account that this answer message will be sent 'as is' and sequence information could be wrong at the remote peer", ANNA_FILE_LOCATION);
633 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
634 my_app.updateOperatedOriginHostWithMessage(codecMsg);
636 tc->addSendDiameterXml2e(codecMsg.code(), my_app.getOperatedHost(), stepNumber);
638 tc->addSendDiameterXml2c(codecMsg.code(), my_app.getOperatedHost(), stepNumber);
640 response = std::to_string(tc->getId());
642 catch(anna::RuntimeException &ex) {
644 response += "failed";
651 bool EventOperation::test_id__delay(std::string &response, unsigned int id, int msecs) {
653 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
654 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
657 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
658 anna::Millisecond delay = ((msecs == 0 /* special case */) ? (anna::Millisecond)0 : my_app.checkTimeMeasure("Test case delay step", anna::functions::asString(msecs)));
659 tc->addDelay(delay); // creates / reuses
660 response = std::to_string(tc->getId());
662 catch(anna::RuntimeException &ex) {
664 response += "invalid delay";
671 bool EventOperation::test_id__sh_command(std::string &response, unsigned int id, const std::string & script) {
673 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
674 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
677 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
678 tc->addCommand(script); // creates / reuses
679 response = std::to_string(tc->getId());
681 catch(anna::RuntimeException &ex) {
683 response += "failed";
690 bool EventOperation::test_id__waitfefc_hex(std::string &response, unsigned int id, bool fe_or_fc, const std::string & hex, bool strict) {
692 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
693 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
695 // Get DataBlock from hex content:
696 anna::DataBlock db_aux(true);
697 std::string hexString = hex;
698 hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
700 std::string msg = "Hex string (remove colons if exists): ";
702 anna::Logger::debug(msg, ANNA_FILE_LOCATION);
707 anna::functions::fromHexString(hexString, db_aux); // could launch exception
708 regexp = anna::functions::asHexString(db_aux);
710 catch(anna::RuntimeException &ex) {
712 response += "failed";
718 //// If request, we will ignore sequence data:
719 //if (anna::diameter::codec::functions::requestBit(db_aux))
720 regexp.replace (24, 16, "[0-9A-Fa-f]{16}");
722 regexp.insert(0, "^");
727 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
728 tc->addWaitDiameterRegexpHex(fe_or_fc, regexp);
729 response = std::to_string(tc->getId());
731 catch(anna::RuntimeException &ex) {
733 response += "failed";
740 bool EventOperation::test_id__waitfefc_msg(std::string &response, unsigned int id, bool fe_or_fc, const std::string & diameterJson, bool strict) {
742 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
743 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
746 std::string diameterXml = anna::json::functions::json2xml(diameterJson, success);
748 response += "json to xml failed, unable to load message !";
753 anna::diameter::codec::Message codecMsg; // auxiliary codec message
754 codecMsg.loadXMLString(diameterXml);
755 std::string regexp = codecMsg.asXMLString(true /* normalization */);
757 // Now we must insert regular expressions in hop-by-hop, end-to-end and Origin-State-Id:
761 std::string::size_type pos, pos_1, pos_2;
763 pos = regexp.find("end-to-end-id=", 0u);
764 if (pos != std::string::npos) {
765 pos = regexp.find("\"", pos);
767 pos = regexp.find("\"", pos+1);
769 regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
772 pos = regexp.find("hop-by-hop-id=", 0u);
773 if (pos != std::string::npos) {
774 pos = regexp.find("\"", pos);
776 pos = regexp.find("\"", pos+1);
778 regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
781 // For this representation: <avp name="Origin-State-Id" data="1428633668"/>
782 //pos = regexp.find("Origin-State-Id", 0u);
783 //pos = regexp.find("\"", pos);
784 //pos = regexp.find("\"", pos+1);
786 //pos = regexp.find("\"", pos+1);
788 //regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
789 // But we have this one: <avp data="1428633668" name="Origin-State-Id"/>
790 pos = regexp.find("Origin-State-Id", 0u);
791 if (pos != std::string::npos) {
792 pos = regexp.rfind("\"", pos);
793 pos = regexp.rfind("\"", pos-1);
794 pos = regexp.rfind("\"", pos-1);
796 pos = regexp.find("\"", pos+1);
798 regexp.replace(pos_1 + 1, pos_2 - pos_1 - 1, "[0-9]+");
801 //regexp.insert(0, "^");
805 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
806 tc->addWaitDiameterRegexpXml(fe_or_fc, regexp);
807 response = std::to_string(tc->getId());
809 catch(anna::RuntimeException &ex) {
811 response += "failed";
818 bool EventOperation::test_id__waitfefc(std::string &response, unsigned int id, bool fe_or_fc,
819 const std::string & code,
820 const std::string & bitR,
821 const std::string & hopByHop,
822 const std::string & applicationId,
823 const std::string & sessionId,
824 const std::string & resultCode,
825 const std::string & msisdn,
826 const std::string & imsi,
827 const std::string & serviceContextId) {
829 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
830 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
832 try { // [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId]
833 anna::testing::TestCase *tc = testManager.getTestCase(id); // creates / reuses
834 tc->addWaitDiameter(fe_or_fc, code, bitR, hopByHop, applicationId, sessionId, resultCode, msisdn, imsi, serviceContextId);
835 response = std::to_string(tc->getId());
837 catch(anna::RuntimeException &ex) {
839 response += "failed";
846 /////////////////////////
847 // Testcases execution //
848 /////////////////////////
849 bool EventOperation::test__ttps(std::string &response, int amount) {
851 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
852 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
854 bool success = testManager.configureTTPS(amount);
856 response = "Assigned new test launch rate to ";
857 response += anna::functions::asString(amount);
858 response += " events per second";
861 response += "unable to configure the test rate provided";
864 return success; // OK
867 bool EventOperation::test__next(std::string &response, int syncAmount) {
869 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
870 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
872 if (syncAmount < 1) {
873 response += "the parameter 'sync-amount' must be a positive integer value";
877 bool success = testManager.execTestCases(syncAmount);
879 response = (success ? "P" : "Not completely p" /* completed cycle and no repeats, rare case */);
880 response += "rocessed ";
881 response += anna::functions::asString(syncAmount);
882 response += ((syncAmount > 1) ? " test cases synchronously" : " test case");
887 bool EventOperation::test__ip_limit(std::string &response, int amount) {
889 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
890 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
893 testManager.setInProgressLimit(amount);
894 response = "New in-progress limit: ";
895 response += (amount != -1) ? anna::functions::asString(amount) : "[no limit]";
898 response = "In-progress limit amount: ";
899 int limit = testManager.getInProgressLimit();
900 response += (limit != -1) ? anna::functions::asString(limit) : "[no limit]";
901 response += "; currently there are ";
902 response += anna::functions::asString(testManager.getInProgressCount());
903 response += " test cases running";
909 bool EventOperation::test__goto(std::string &response, int id) {
911 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
912 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
914 bool success = testManager.gotoTestCase(id);
917 response = "Position updated for id provided (";
920 response += "cannot found test id (";
922 response += anna::functions::asString(id);
928 bool EventOperation::test__run(std::string &response, int id) {
930 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
931 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
933 bool success = testManager.runTestCase(id);
936 response = "Test executed for id provided (";
939 response += "cannot found test id (";
941 response += anna::functions::asString(id);
947 bool EventOperation::test__look(std::string &response, int id) {
949 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
950 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
952 anna::testing::TestCase *testCase = testManager.findTestCase(id);
955 response += "no current test case detected (testing started ?)";
958 response += "cannot found test id (";
959 response += anna::functions::asString(id);
967 response = anna::functions::encodeBase64(testCase->asXMLString());
969 response = testCase->asXMLString();
974 bool EventOperation::test__state(std::string &response, int id) {
976 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
977 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
979 anna::testing::TestCase *testCase = testManager.findTestCase(id);
982 response += "no current test case detected (testing started ?)";
985 response += "cannot found test id (";
986 response += anna::functions::asString(id);
993 response = anna::testing::TestCase::asText(testCase->getState());
994 return testCase->isSuccess();
997 bool EventOperation::test__interact(std::string &response, int amount, unsigned int id) {
999 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1000 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1003 response += "interactive amount must be -1 (to disable interactive mode) or a positive number.";
1007 anna::testing::TestCase *testCase = testManager.findTestCase(id);
1010 testCase->makeInteractive(false);
1011 response = "Interactive mode disabled";
1014 testCase->addInteractiveAmount(amount);
1015 response = "Added interactive amount of ";
1016 response += anna::functions::asString(amount);
1017 response += " units";
1018 if (amount == 0) response += " (0: freezing a non-interactive testcase, no effect on already interactive)";
1020 response += " for test case id ";
1021 response += anna::functions::asString(id);
1024 response += "cannot found test id (";
1025 response += anna::functions::asString(id);
1033 bool EventOperation::test__reset(std::string &response, bool soft_hard, int id) {
1035 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1036 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1038 anna::testing::TestCase *testCase = ((id != -1) ? testManager.findTestCase(id) : NULL);
1040 bool done = testCase->reset(!soft_hard);
1042 response += (soft_hard ? "soft":"hard");
1043 response += " reset for id ";
1044 response += anna::functions::asString(id);
1045 response += done ? ": done": ": not done";
1049 bool anyReset = testManager.resetPool(!soft_hard);
1050 response = (soft_hard ? "Soft":"Hard");
1051 response += " reset have been sent to all programmed tests: "; response += anyReset ? "some/all have been reset" : "nothing was reset";
1054 response += "cannot found test id (";
1055 response += anna::functions::asString(id);
1064 bool EventOperation::test__repeats(std::string &response, int amount) {
1066 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1067 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1069 if (amount < 0) amount = -1;
1070 testManager.setPoolRepeats(amount);
1071 std::string nolimit = (amount != -1) ? "":" [no limit]";
1072 response = anna::functions::asString("Pool repeats: %d%s (current cycle: %d)", amount, nolimit.c_str(), testManager.getPoolCycle());
1077 bool EventOperation::test__auto_reset(std::string &response, bool soft_hard) {
1079 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1080 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1082 testManager.setAutoResetHard(!soft_hard);
1083 response = anna::functions::asString("Auto-reset configured to '%s'", (soft_hard ? "soft":"hard"));
1088 bool EventOperation::test__initialized(std::string &response) {
1090 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1091 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1093 response = anna::functions::asString("%lu", testManager.getInitializedCount());
1098 bool EventOperation::test__finished(std::string &response) {
1100 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1101 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1103 response = anna::functions::asString("%lu", testManager.getFinishedCount());
1108 bool EventOperation::test__clear(std::string &response) {
1110 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1111 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1113 return testManager.clearPool(response);
1116 bool EventOperation::test__junit(std::string &response, const std::string & targetFile) {
1118 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1119 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1122 out.open(targetFile.c_str());
1124 if(out.is_open() == false) {
1125 response += "error opening '";
1126 response += targetFile;
1131 out << testManager.junitAsXMLString() << std::endl;
1134 response = "Junit report written on '";
1135 response += targetFile;
1141 bool EventOperation::test__summary_counts(std::string &response) {
1143 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1144 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1146 response = anna::functions::encodeBase64(testManager.summaryCounts());
1151 bool EventOperation::test__summary_states(std::string &response) {
1153 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1154 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1156 response = anna::functions::encodeBase64(testManager.summaryStates());
1161 bool EventOperation::test__summary(std::string &response) {
1163 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1164 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1166 response = anna::functions::encodeBase64(testManager.asXMLString());
1171 bool EventOperation::test__report(std::string &response, const std::string & state, bool enable) {
1173 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1174 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1176 std::string _state = state;
1178 if(_state == "initialized")
1179 testManager.setDumpInitializedReports(enable);
1180 else if(_state == "in-progress")
1181 testManager.setDumpInProgressReports(enable);
1182 else if(_state == "failed")
1183 testManager.setDumpFailedReports(enable);
1184 else if(_state == "success")
1185 testManager.setDumpSuccessReports(enable);
1186 else if(_state == "all") {
1188 testManager.setDumpAllReports(enable);
1190 else if(_state == "none") {
1193 testManager.setDumpAllReports(enable);
1196 response += "invalid state (allowed: initialized|in-progress|failed|success|[all]|none)";
1200 response = (enable ? "Report enabled " : "Report disabled ");
1201 response += "for tests in '";
1203 response += "' state";
1208 bool EventOperation::test__report_hex(std::string &response, bool enable) {
1210 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1211 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1213 testManager.setDumpHex(enable);
1214 response = (testManager.getDumpHex() ? "Report includes hexadecimal messages" : "Report excludes hexadecimal messages");
1219 bool EventOperation::test__dump_stdout(std::string &response, bool enable) {
1221 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1222 anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate();
1224 testManager.setDumpStdout(enable);
1225 response = (testManager.getDumpStdout() ? "Test manager dumps progress into stdout" : "Test manager does not dump progress into stdout");
1230 bool EventOperation::test__dynamic(std::string &response, const nlohmann::json &arguments) {
1232 Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
1234 Procedure p(&my_app);
1236 p.execute(arguments, response);
1238 catch(anna::RuntimeException &ex) {
1240 response += ex.asString();