Add nlohmann/json parser
[anna.git] / example / diameter / launcher / Launcher.cpp
index 2175263..07c2e1b 100644 (file)
 #include <anna/xml/xml.hpp>
 #include <anna/diameter.comm/OriginHost.hpp>
 #include <anna/diameter.comm/OriginHostManager.hpp>
-#include <Procedure.hpp>
 
 // Process
 #include <Launcher.hpp>
+#include <Procedure.hpp>
+#include <EventOperation.hpp>
 #include <MyDiameterEngine.hpp>
 #include <anna/testing/TestManager.hpp>
 #include <anna/testing/TestCase.hpp>
@@ -330,7 +331,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp
 
       // Checking command line parameters
       std::string sessionBasedModelsType;
-      anna::diameter::comm::Entity::SessionBasedModelsType::_v sessionBasedModelsTypeEnum;
+      anna::diameter::comm::Entity::SessionBasedModelsType::_v sessionBasedModelsTypeEnum = anna::diameter::comm::Entity::SessionBasedModelsType::SessionIdLowPart;
       if(sessionBasedModelsClientSocketSelection) {
         sessionBasedModelsType = sessionBasedModelsClientSocketSelection->getValue();
        if (sessionBasedModelsType == "RoundRobin") {
@@ -1463,6 +1464,8 @@ std::string Launcher::help() const throw() {
   result += "\n                                 Test cases reports are not dumped on process context (too many information in general).";
   result += "\n                                 The report contains context information in every moment: this operation acts as a snapshot.";
   result += "\n";
+  result += "\n   test|state[|id]               Get test case state for id provided, current 'in-process' test case when missing.";
+  result += "\n";
   result += "\n   test|interact|amount[|id]     Makes interactive a specific test case id. The amount is the margin of execution steps";
   result += "\n                                 to be done. Normally, we will execute 'test|interact|0[|<test case id>]', which means that";
   result += "\n                                 the test case is selected to be interactive, but no step is executed. Then you have to";
@@ -1567,7 +1570,7 @@ std::string Launcher::help() const throw() {
   result += "\n";
   result += "\nThe alternative using SIGUSR2 signal requires the creation of the task(s) file which will be read at";
   result += "\n signal event:";
-  result += "\n   echo \"<<operation>\" > "; result += getSignalUSR2InputFile();
+  result += "\n   echo \"<operation>\" > "; result += getSignalUSR2InputFile();
   result += "\n    then";
   result += "\n   kill -12 <pid>";
   result += "\n    or";
@@ -1619,9 +1622,12 @@ void Launcher::logStatisticsSamples(const std::string &conceptsList) throw() {
 }
 
 
-void Launcher::eventOperation(const std::string &operation, std::string &response_content) throw(anna::RuntimeException) {
+bool Launcher::eventOperation(const std::string &operation, std::string &response_content) throw(anna::RuntimeException) {
+
+  bool result = true;
+
   LOGMETHOD(anna::TraceMethod tm("Launcher", "eventOperation", ANNA_FILE_LOCATION));
-  if (operation == "") return; // ignore
+  if (operation == "") return result; // ignore
   LOGDEBUG(anna::Logger::debug(anna::functions::asString("Operation: %s", operation.c_str()), ANNA_FILE_LOCATION));
 
   // Default response:
@@ -1651,15 +1657,15 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     catch(anna::RuntimeException &ex) {
       ex.trace();
       response_content = ex.asString();
-      return;
+      return false;
     }
-    return;
+    return true; // OK
   }
 
   // Help:
   if(operation == "help") {
     response_content = help();
-    return;
+    return true; // OK
   }
 
   // Reset performance data:
@@ -1667,26 +1673,26 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     resetCounters();
     resetStatistics();
     response_content = "All process counters & statistic information have been reset";
-    return;
+    return true; // OK
   }
 
   // Counters dump on demand:
   if(operation == "forceCountersRecord") {
     forceCountersRecord();
     response_content = "Current counters have been dump to disk";
-    return;
+    return true; // OK
   }
 
   // OAM & statistics:
   if(operation == "show-oam") {
     anna::xml::Node root("root");
     response_content = anna::xml::Compiler().apply(oamAsXML(&root));
-    return;
+    return true; // OK
   }
   if(operation == "show-stats") {
     anna::xml::Node root("root");
     response_content = anna::xml::Compiler().apply(statsAsXML(&root));
-    return;
+    return true; // OK
   }
 
   ///////////////////////////////////////////////////////////////////
@@ -1761,25 +1767,27 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     std::string contextFile = ((numParams == 1) ? param1 : anna::functions::asString("/var/tmp/anna.context.%05d", getPid()));
     writeContext(contextFile);
     response_content = anna::functions::asString("Context dumped on file '%s'", contextFile.c_str());
-    return;
+    return true; // OK
   }
 
   if(opType == "log-statistics-samples") {
     logStatisticsSamples(param1);
     response_content = anna::functions::asString("Log statistics samples for '%s' concepts", param1.c_str());
-    return;
+    return true; // OK
   }
 
   // Change execution directory:
   if(opType == "change-dir") {
     if (param1 == "") param1 = a_initialWorkingDirectory;
-    if (chdir(param1.c_str()) == 0)
+    result = (chdir(param1.c_str()) == 0);
+
+    if (result)
       response_content = "New execution directory configured: ";
     else
       response_content = "Cannot assign provided execution directory: ";
 
     response_content += param1;
-    return;
+    return result;
   }
 
   if(opType == "services") {
@@ -1790,10 +1798,10 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     catch(anna::RuntimeException &ex) {
       ex.trace();
       response_content = anna::functions::asString("Loaded services from file '%s' with errors", servicesFile.c_str());
-      return;
+      return false;
     }
     response_content = anna::functions::asString("Loaded services from file '%s'", servicesFile.c_str());
-    return;
+    return true; // OK
   }
 
   // Host switch:
@@ -1810,12 +1818,12 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
         response_content = "Working node is automatic";
       }
     }
-    return;
+    return true; // OK
   }
   if(opType == "node_auto") {
     a_workingNode = NULL;
     response_content = "Working node has been set to automatic";
-    return;
+    return true; // OK
   }
 
   // Operated host from possible forced-working node:
@@ -1827,7 +1835,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
 
 
   if(opType == "code") {
-    codecMsg.loadXML(param1);
+    codecMsg.loadXMLFile(param1);
     std::string hexString = anna::functions::asHexString(codecMsg.code());
     // write to outfile
     std::ofstream outfile(param2.c_str(), std::ifstream::out);
@@ -1887,7 +1895,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     anna::diameter::comm::Message *msg;
 
     if(opType == "sendxml2e") {
-      codecMsg.loadXML(param1);
+      codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
       msg = getOperatedHost()->createCommMessage();
       msg->clearBody();
@@ -1937,7 +1945,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     } else if(param1 == "load") {
       if(param2 == "") throw anna::RuntimeException("Missing xml path file for burst load operation", ANNA_FILE_LOCATION);
 
-      codecMsg.loadXML(param2);
+      codecMsg.loadXMLFile(param2);
       if(codecMsg.isAnswer()) throw anna::RuntimeException("Cannot load diameter answers for burst feature", ANNA_FILE_LOCATION);
       try { codecMsg.valid(); } catch(anna::RuntimeException &ex) { ex.trace(); }  // at least we need to see validation errors although it will continue loading (see validation mode configured in launcher)
 
@@ -2159,9 +2167,33 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
 
       if (testCase) {
         response_content = testCase->asXMLString();
-        return;
+        return true; // OK
+      }
+      else {
+        result = false;
+        if (id == -1) {
+          opt_response_content = "no current test case detected (testing started ?)";
+        }
+        else {
+          opt_response_content = "cannot found test id (";
+          opt_response_content += anna::functions::asString(id);
+          opt_response_content += ")";
+        }
+      }
+    }
+    else if(param1 == "state") {
+      if (numParams > 2)
+        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);
+      anna::testing::TestCase *testCase = testManager.findTestCase(id);
+
+      if (testCase) {
+        response_content = anna::testing::TestCase::asText(testCase->getState());
+        return testCase->isSuccess();
       }
       else {
+        result = false;
         if (id == -1) {
           opt_response_content = "no current test case detected (testing started ?)";
         }
@@ -2198,6 +2230,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
         opt_response_content += anna::functions::asString(id);
       }
       else {
+        result = false;
         opt_response_content = "cannot found test id (";
         opt_response_content += anna::functions::asString(id);
         opt_response_content += ")";
@@ -2228,6 +2261,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
           opt_response_content = param2; opt_response_content += " reset have been sent to all programmed tests: "; opt_response_content += anyReset ? "some/all have been reset" : "nothing was reset";
         }
         else {
+          result = false;
           opt_response_content = "cannot found test id (";
           opt_response_content += anna::functions::asString(id);
           opt_response_content += ")";
@@ -2269,19 +2303,19 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     }
     else if(param1 == "junit") {
       response_content = testManager.junitAsXMLString();
-      return;
+      return true; // OK
     }
     else if(param1 == "summary-counts") {
       response_content = testManager.summaryCounts();
-      return;
+      return true; // OK
     }
     else if(param1 == "summary-states") {
       response_content = testManager.summaryStates();
-      return;
+      return true; // OK
     }
     else if(param1 == "summary") {
       response_content = testManager.asXMLString();
-      return;
+      return true; // OK
     }
     else {
       int id = atoi(param1.c_str());
@@ -2326,7 +2360,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
         if (numParams > 4)
           throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
         if(param3 == "") throw anna::RuntimeException(anna::functions::asString("Missing xml file for '%s' command in test id operation", param2.c_str()), ANNA_FILE_LOCATION);
-        codecMsg.loadXML(param3);
+        codecMsg.loadXMLFile(param3);
         LOGWARNING(
           if (!codecMsg.isRequest() && (param4 == ""))
             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);
@@ -2461,7 +2495,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     anna::diameter::comm::Message *msg;
 
     if(opType == "sendxml2c") {
-      codecMsg.loadXML(param1);
+      codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
       msg = getOperatedHost()->createCommMessage();
       msg->clearBody();
@@ -2486,9 +2520,9 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
       getOperatedHost()->writeLogFile(codecMsg, (success ? "sent2c" : "send2cError"), detail);
     }
   } else if(opType == "loadxml") {
-    codecMsg.loadXML(param1);
+    codecMsg.loadXMLFile(param1);
     response_content = codecMsg.asXMLString();
-    return;
+    return true; // OK
   } else if(opType == "diameterServerSessions") {
     int diameterServerSessions = atoi(param1.c_str());
     getOperatedServer()->setMaxConnections(diameterServerSessions);
@@ -2496,7 +2530,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
   } else if(opType == "answerxml2c") {
     if(param1 == "") { // programmed answers FIFO's to stdout
       response_content = getOperatedServer()->getReactingAnswers()->asString("ANSWERS TO CLIENT");
-      return;
+      return true; // OK
     } else if (param1 == "rotate") {
       getOperatedServer()->getReactingAnswers()->rotate(true);
     } else if (param1 == "exhaust") {
@@ -2506,7 +2540,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     } else if (param1 == "dump") {
       getOperatedServer()->getReactingAnswers()->dump("programmed_answer");
     } else {
-      codecMsg.loadXML(param1);
+      codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
       anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
       LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
@@ -2522,7 +2556,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
 
     if(param1 == "") { // programmed answers FIFO's to stdout
       response_content = getOperatedEntity()->getReactingAnswers()->asString("ANSWERS TO ENTITY");
-      return;
+      return true; // OK
     } else if (param1 == "rotate") {
       getOperatedEntity()->getReactingAnswers()->rotate(true);
     } else if (param1 == "exhaust") {
@@ -2532,7 +2566,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     } else if (param1 == "dump") {
       getOperatedEntity()->getReactingAnswers()->dump("programmed_answer");
     } else {
-      codecMsg.loadXML(param1);
+      codecMsg.loadXMLFile(param1);
       updateOperatedOriginHostWithMessage(codecMsg);
       anna::diameter::codec::Message *message = getOperatedHost()->getCodecEngine()->createMessage(param1); // loads xml again, lesser of two evils
       LOGDEBUG(anna::Logger::debug(message->asXMLString(), ANNA_FILE_LOCATION));
@@ -2554,6 +2588,8 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     response_content += " => ";
     response_content += opt_response_content;
   }
+
+  return result;
 }
 
 anna::xml::Node* Launcher::asXML(anna::xml::Node* parent) const