Fix bug while getting step number.
[anna.git] / example / diameter / launcher / testing / TestManager.cpp
index ca45e9c..6dfec1e 100644 (file)
@@ -24,6 +24,7 @@
 #include <TestCase.hpp>
 #include <TestClock.hpp>
 #include <Launcher.hpp>
+#include <RealmNode.hpp>
 
 
 class TestTimer;
@@ -34,8 +35,10 @@ TestManager::TestManager() :
   a_timeController = NULL;
   a_reportsDirectory = "./";
   a_dumpReports = false;
+  a_dumpHexMessages = false;
   a_synchronousAmount = 1;
-  a_poolRepeat = false;
+  a_poolRepeats = 0; // repeat disabled by default
+  a_poolCycle = 1;
   a_inProgressCount = 0;
   a_inProgressLimit = UINT_MAX; // no limit
   a_clock = NULL;
@@ -134,7 +137,7 @@ bool TestManager::configureTTPS(int testTicksPerSecond) throw() {
   a_synchronousAmount = 1;
 
   if (admlTimeInterval < anna::Millisecond(1)) {
-    LOGWARNING(anna::Logger::warning("Not allowed to configure more than 1000 events per second for the time trigger testing system", ANNA_FILE_LOCATION));
+    LOGWARNING(anna::Logger::warning("Not allowed to configure more than 1000 events per second for for triggering testing system", ANNA_FILE_LOCATION));
     return false;
   }
 
@@ -208,6 +211,7 @@ bool TestManager::clearPool() throw() {
   a_testPool.clear();
   a_sessionIdTestCaseMap.clear();
   a_currentTestIt = a_testPool.end();
+  a_poolCycle = 1;
   configureTTPS(0); // stop
   return true;
 }
@@ -217,8 +221,8 @@ bool TestManager::resetPool(bool hard) throw() {
 
   if (!tests()) return result;
   for (test_pool_nc_it it = a_testPool.begin(); it != a_testPool.end(); it++) {
-    it->second->reset(hard);
-    result = true;
+    if (it->second->reset(hard))
+      result = true;
   }
   //a_sessionIdTestCaseMap.clear();
   return result;
@@ -232,6 +236,7 @@ bool TestManager::tick() throw() {
     return false;
   }
 
+  // Synchronous sendings per tick:
   int count = a_synchronousAmount;
   while (count > 0) {
     if (!nextTestCase()) return false; // stop the clock
@@ -259,33 +264,46 @@ bool TestManager::nextTestCase() throw() {
 
     // Completed:
     if (a_currentTestIt == a_testPool.end()) {
-      if (a_poolRepeat) {
-        LOGWARNING(anna::Logger::warning("Testing pool cycle completed. Repeat mode on. Restarting", ANNA_FILE_LOCATION));
+      if ((a_poolCycle > a_poolRepeats) && (a_poolRepeats != -1)) {
+        LOGWARNING(anna::Logger::warning("Testing pool cycle completed. No remaining repeat cycles left. Suspending", ANNA_FILE_LOCATION));
+        a_poolCycle = 1;
+        return false;
+      }
+      else {
+        LOGWARNING(
+          std::string nolimit = (a_poolRepeats != -1) ? "":" [no limit]";
+          anna::Logger::warning(anna::functions::asString("Testing pool cycle %d completed (repeats configured: %d%s). Restarting for the %s cycle", a_poolCycle, a_poolRepeats, nolimit.c_str(), (a_poolRepeats == a_poolCycle) ? "last":"next"), ANNA_FILE_LOCATION);
+        );
+        a_poolCycle++;
         //a_currentTestIt = a_testPool.begin();
         return true; // avoids infinite loop: if the cycle takes less time than test cases completion, below reset never will turns state
                      // into Initialized and this while will be infinite. It is preferable to wait one tick when the cycle is completed.
       }
-      else {
-        LOGWARNING(anna::Logger::warning("Testing pool cycle completed. Repeat mode off. Suspending", ANNA_FILE_LOCATION));
-        return false;
-      }
     }
 
-    // Hard reset, because normally a cycle takes more time that a single test case lifetime. We can consider that never
-    //  going to break a in-progress test case due to cycle repeat
+    // Soft reset to initialize already finished (in previous cycle) test cases:
     a_currentTestIt->second->reset(false);
 
     // Process test case:
     LOGDEBUG(anna::Logger::debug(anna::functions::asString("Processing test case id = %llu, currently '%s' state", a_currentTestIt->first, TestCase::asText(a_currentTestIt->second->getState())), ANNA_FILE_LOCATION));
     if (a_currentTestIt->second->getState() != TestCase::State::InProgress) {
       a_currentTestIt->second->process();
-      return true;
+      return true; // is not probably to reach still In-Progress test cases from previous cycles due to the whole
+                   //  time for complete the test cases pool regarding the single test case lifetime. You shouldn't
+                   //  forget to programm a test case timeout with a reasonable value
     }
   }
 }
 
-TestCase *TestManager::getTestCaseFromSessionId(const anna::DataBlock &message, std::string &sessionId) throw(anna::RuntimeException) {
-  sessionId = anna::diameter::helpers::base::functions::getSessionId(message);
+TestCase *TestManager::getTestCaseFromSessionId(const anna::DataBlock &message, std::string &sessionId) throw() {
+  try {
+    sessionId = anna::diameter::helpers::base::functions::getSessionId(message);
+  }
+  catch (anna::RuntimeException &ex) {
+    //ex.trace();
+    LOGWARNING(anna::Logger::warning("Cannot get the Session-Id from received DataBlock in order to identify the Test Case", ANNA_FILE_LOCATION));
+    return NULL;
+  }
   std::map<std::string /* session id's */, TestCase*>::const_iterator sessionIdIt = a_sessionIdTestCaseMap.find(sessionId);
   if (sessionIdIt != a_sessionIdTestCaseMap.end())
     return sessionIdIt->second;
@@ -294,7 +312,7 @@ TestCase *TestManager::getTestCaseFromSessionId(const anna::DataBlock &message,
   return NULL;
 }
 
-void TestManager::receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException) {
+void TestManager::receiveMessage(const anna::DataBlock &message, RealmNode *realm, const anna::diameter::comm::ClientSession *clientSession) throw(anna::RuntimeException) {
 
   // Testing disabled:
   if (!tests()) return;
@@ -310,10 +328,15 @@ void TestManager::receiveMessage(const anna::DataBlock &message, const anna::dia
     std::string hint = "Uncovered condition for received message from entity over Session-Id '"; hint += sessionId; hint += "':";
 
     try {
-      Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-      static anna::diameter::codec::Message codecMsg(my_app.getCodecEngine());
+      static anna::diameter::codec::Message codecMsg;
       codecMsg.decode(message);
       hint += "\n"; hint += codecMsg.asXMLString();
+
+      //      // Realm checking:
+      //      std::string messageOR = message.getAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->getValue();
+      //      if (messageOR != realm->getName()) {
+      //        LOGWARNING(anna::Logger::warning(anna::functions::asString("Received message from realm '%s', with different Origin-Realm: %s", realm->getName().c_str(), messageOR.c_str()), ANNA_FILE_LOCATION));
+      //      }
     }
     catch (anna::RuntimeException &ex) {
       ex.trace();
@@ -325,10 +348,11 @@ void TestManager::receiveMessage(const anna::DataBlock &message, const anna::dia
   }
   else {
     tsw->setClientSession(const_cast<anna::diameter::comm::ClientSession*>(clientSession));
+    tc->process();
   }
 }
 
-void TestManager::receiveMessage(const anna::DataBlock &message, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException) {
+void TestManager::receiveMessage(const anna::DataBlock &message, RealmNode *realm, const anna::diameter::comm::ServerSession *serverSession) throw(anna::RuntimeException) {
 
   // Testing disabled:
   if (!tests()) return;
@@ -344,10 +368,15 @@ void TestManager::receiveMessage(const anna::DataBlock &message, const anna::dia
     std::string hint = "Uncovered condition for received message from client over Session-Id '"; hint += sessionId; hint += "':";
 
     try {
-      Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
-      static anna::diameter::codec::Message codecMsg(my_app.getCodecEngine());
+      static anna::diameter::codec::Message codecMsg;
       codecMsg.decode(message);
       hint += "\n"; hint += codecMsg.asXMLString();
+
+      //      // Realm checking:
+      //      std::string messageOR = message.getAvp(anna::diameter::helpers::base::AVPID__Origin_Realm)->getDiameterIdentity()->getValue();
+      //      if (messageOR != realm->getName()) {
+      //        LOGWARNING(anna::Logger::warning(anna::functions::asString("Received message from realm '%s', with different Origin-Realm: %s", realm->getName().c_str(), messageOR.c_str()), ANNA_FILE_LOCATION));
+      //      }
     }
     catch (anna::RuntimeException &ex) {
       ex.trace();
@@ -359,6 +388,7 @@ void TestManager::receiveMessage(const anna::DataBlock &message, const anna::dia
   }
   else {
     tsw->setServerSession(const_cast<anna::diameter::comm::ServerSession*>(serverSession));
+    tc->process();
   }
 }
 
@@ -368,13 +398,16 @@ throw() {
 
   int poolSize = a_testPool.size();
   result->createAttribute("NumberOfTestCases", poolSize);
-  result->createAttribute("PoolRepeat", (a_poolRepeat ? "yes":"no"));
+  if (a_poolRepeats) result->createAttribute("PoolRepeats", a_poolRepeats);
+  else result->createAttribute("PoolRepeats", "disabled");
+  result->createAttribute("PoolCycle", a_poolCycle);
   result->createAttribute("InProgressCount", a_inProgressCount);
   if (a_inProgressLimit == UINT_MAX)
     result->createAttribute("InProgressLimit", "<no limit>");
   else
     result->createAttribute("InProgressLimit", a_inProgressLimit);
   result->createAttribute("DumpReports", (a_dumpReports ? "yes":"no"));
+  result->createAttribute("DumpHexMessages", (a_dumpHexMessages ? "yes":"no"));
   result->createAttribute("ReportsDirectory", a_reportsDirectory);
   if (a_clock) {
     result->createAttribute("AsynchronousSendings", a_synchronousAmount);