Improvements from anna fork
[anna.git] / source / testing / TestStep.cpp
index 07ed6b3..d975ddd 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdio.h>     // perror
 #include <stdlib.h>    // exit
 #include <sys/wait.h>  // waitpid, pid_t, WNOHANG
+#include <climits>
 
 // cmd with fork:
 #include <sys/types.h>
@@ -65,6 +66,7 @@ namespace {
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
     if (sigaction(SIGCHLD, &sa, 0) != -1) {
+
       status = system(cmd.c_str());
       /* POPEN version:
           char readbuf[256];
@@ -199,7 +201,7 @@ bool TestStep::decodeMessage(bool trust) throw() {
 
 const char* TestStep::asText(const Type::_v type)
 throw() {
-  static const char* text [] = { "Unconfigured", "Timeout", "Sendxml2e", "Sendxml2c", "Delay", "Wait", "Command" };
+  static const char* text [] = { "Unconfigured", "Timeout", "SendDiameterXmlToEntity", "SendDiameterXmlToClient", "Delay", "Wait", "Command", "IpLimit" };
   return text [type];
 }
 
@@ -223,6 +225,9 @@ throw() {
   //  if (a_endTimestamp != 0 && deltaMs > 0) s_aux += anna::functions::asString(" [%.3f]", deltaMs/1000.0);
   result->createAttribute("EndTimestamp", s_aux);
 
+  if (a_beginTimestamp != 0 && a_endTimestamp != 0)
+    result->createAttribute("LapseMilliseconds", getLapseMs());
+
   return result;
 }
 
@@ -241,21 +246,47 @@ bool TestStep::execute() throw() {
     if (a_executed) return false; // avoid repeating (this implies amount consumption)
   }
 
-  LOGDEBUG(anna::Logger::debug(anna::functions::asString("EXECUTING %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
+  const char *literal = "Execute %s Test Step %d/%d (test case %llu)";
+
+  TestManager& testManager (TestManager::instantiate ());
+  if (testManager.getDumpStdout()) {
+    bool dump = (a_type == Type::Wait) ? (!a_completed) : true;
+    if (dump) {
+    std::cout << std::endl << "=> " << anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()) << std::endl;
+    }
+  }
+
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()), ANNA_FILE_LOCATION));
   setBeginTimestamp(anna::functions::millisecond());
   a_executed = true;
   return do_execute();
 }
 
 void TestStep::complete() throw() {
-  LOGDEBUG(anna::Logger::debug(anna::functions::asString("COMPLETE %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
+
+  const char *literal = "Complete %s Test Step %d/%d (test case %llu)";
+
+  TestManager& testManager (TestManager::instantiate ());
+  if (testManager.getDumpStdout()) {
+    std::cout << "=> " << anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()) << std::endl;
+  }
+
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()), ANNA_FILE_LOCATION));
   a_completed = true;
   setEndTimestamp(anna::functions::millisecond());
   do_complete();
 }
 
 void TestStep::reset() throw() {
-  LOGDEBUG(anna::Logger::debug(anna::functions::asString("RESET %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
+
+  const char *literal = "Reset %s Test Step %d/%d (test case %llu)";
+
+  TestManager& testManager (TestManager::instantiate ());
+  if (testManager.getDumpStdout()) {
+    std::cout << "=> " << anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()) << std::endl;
+  }
+
+  LOGDEBUG(anna::Logger::debug(anna::functions::asString(literal, asText(a_type), a_number, a_testCase->steps(), a_testCase->getId()), ANNA_FILE_LOCATION));
   // type and testCase kept
   a_completed = false;
   a_executed = false;
@@ -300,16 +331,23 @@ void TestStepTimeout::do_complete() throw() {
   if (stepNumber == a_testCase->steps()) {
     a_testCase->addDebugSummaryHint(anna::functions::asString("Timeout expired (step number %d) but it was the last test case step", stepNumber)); // before report (when set Failed state)
     a_testCase->setState(TestCase::State::Success);
+    if (TestManager::instantiate().getDumpStdout()) {
+      std::cout << "Expired Timeout Test LAST Step: considered SUCCESSFUL TEST CASE" << std::endl;
+    }
   }
   else if (a_testCase->getState() == TestCase::State::InProgress) { // sure
     a_testCase->addDebugSummaryHint(anna::functions::asString("Timeout expired (step number %d) before test case finished", stepNumber)); // before report (when set Failed state)
     a_testCase->setState(TestCase::State::Failed);
+    if (TestManager::instantiate().getDumpStdout()) {
+      std::cout << "Expired Timeout Test Step: FAILED TEST CASE" << std::endl;
+    }
   }
 
   a_timer = NULL;
 }
 
-void TestStepTimeout::do_reset() throw() {
+void TestStepTimeout::cancelTimer() throw() {
+  if (!a_timer) return;
   try {
     TestManager::instantiate().cancelTimer(a_timer);
   }
@@ -320,13 +358,17 @@ void TestStepTimeout::do_reset() throw() {
   //a_timeout = 0; THIS IS CONFIGURATION INFO
 }
 
+void TestStepTimeout::do_reset() throw() {
+  cancelTimer();
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////
-// TestStepSendxml
+// TestStepSendDiameterXml
 ////////////////////////////////////////////////////////////////////////////////////////////////////////
-anna::xml::Node* TestStepSendxml::asXML(anna::xml::Node* parent)
+anna::xml::Node* TestStepSendDiameterXml::asXML(anna::xml::Node* parent)
 throw() {
   anna::xml::Node* result = TestStep::asXML(parent);
-  //parent->createChild("TestStepSendxml");
+  //parent->createChild("TestStepSendDiameterXml");
   std::string msg = "", xmlmsg = "";
 
   // Message
@@ -357,12 +399,12 @@ throw() {
   return result;
 }
 
-bool TestStepSendxml::do_execute() throw() {
+bool TestStepSendDiameterXml::do_execute() throw() {
   bool success = false;
   std::string failReason = "Error sending diameter message";
   anna::diameter::comm::Entity *entity = a_originHost->getEntity(); // by default
   anna::diameter::comm::LocalServer *localServer = a_originHost->getDiameterServer(); // by default
-  const TestStepWait *tsw = NULL;
+  const TestStepWaitDiameter *tsw = NULL;
   anna::diameter::comm::Message *msg = a_originHost->createCommMessage();
 
   try {
@@ -375,7 +417,7 @@ bool TestStepSendxml::do_execute() throw() {
       );
 
       // Referenced request in the 'wait for request step':
-      tsw = static_cast<const TestStepWait*>(a_testCase->getStep(a_waitForRequestStepNumber));
+      tsw = static_cast<const TestStepWaitDiameter*>(a_testCase->getStep(a_waitForRequestStepNumber));
       const anna::DataBlock &referenceRequest = tsw->getMsgDataBlock();
       std::string sessionIdReferenceRequest = anna::diameter::helpers::base::functions::getSessionId(referenceRequest);
 
@@ -491,10 +533,14 @@ bool TestStepSendxml::do_execute() throw() {
     complete();
   }
 
+  if (TestManager::instantiate().getDumpStdout()) {
+    std::cout << "Executed SendDiameterXml Test Step: " << (success ? "OK":"ERROR") << std::endl;
+  }
+
   return success; // go next if sent was OK
 }
 
-void TestStepSendxml::do_reset() throw() {
+void TestStepSendDiameterXml::do_reset() throw() {
   a_expired = false;
   //a_message.clear();
   //a_messageAlreadyDecoded = false;
@@ -530,11 +576,15 @@ bool TestStepDelay::do_execute() throw() {
 void TestStepDelay::do_complete() throw() {
   if (a_delay == 0) return; // special case
   a_timer = NULL;
+  if (TestManager::instantiate().getDumpStdout()) {
+    std::cout << "Consumed Delay Test Step (" << a_delay << " milliseconds)" << std::endl;
+  }
   next(); // next() invoked here because execute() is always false for delay and never advance the iterator
   // TODO, avoid this recursion
 }
 
-void TestStepDelay::do_reset() throw() {
+void TestStepDelay::cancelTimer() throw() {
+  if (!a_timer) return;
   if (a_delay == 0) return; // special case
   try {
     TestManager::instantiate().cancelTimer(a_timer);
@@ -546,10 +596,15 @@ void TestStepDelay::do_reset() throw() {
   //a_delay = 0; THIS IS CONFIGURATION INFO
 }
 
+void TestStepDelay::do_reset() throw() {
+  cancelTimer();
+}
+
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////
-// TestStepWait
+// TestStepWaitDiameter
 ////////////////////////////////////////////////////////////////////////////////////////////////////////
-void TestStepWait::setCondition(bool fromEntity,
+void TestStepWaitDiameter::setCondition(bool fromEntity,
     const std::string &code, const std::string &bitR, const std::string &hopByHop, const std::string &applicationId,
     const std::string &sessionId, const std::string &resultCode,
     const std::string &msisdn, const std::string &imsi, const std::string &serviceContextId) throw() {
@@ -565,20 +620,20 @@ void TestStepWait::setCondition(bool fromEntity,
   a_condition.setServiceContextId(serviceContextId);
 }
 
-void TestStepWait::setConditionRegexpHex(bool fromEntity, const std::string &regexp) throw() {
+void TestStepWaitDiameter::setConditionRegexpHex(bool fromEntity, const std::string &regexp) throw() {
   a_condition.setReceivedFromEntity(fromEntity);
   a_condition.setRegexpHex(regexp);
 }
 
-void TestStepWait::setConditionRegexpXml(bool fromEntity, const std::string &regexp) throw() {
+void TestStepWaitDiameter::setConditionRegexpXml(bool fromEntity, const std::string &regexp) throw() {
   a_condition.setReceivedFromEntity(fromEntity);
   a_condition.setRegexpXml(regexp);
 }
 
-anna::xml::Node* TestStepWait::asXML(anna::xml::Node* parent)
+anna::xml::Node* TestStepWaitDiameter::asXML(anna::xml::Node* parent)
 throw() {
   anna::xml::Node* result = TestStep::asXML(parent);
-  //parent->createChild("TestStepWait");
+  //parent->createChild("TestStepWaitDiameter");
   std::string msg = "", xmlmsg = "";
 
   // Condition
@@ -616,26 +671,35 @@ throw() {
   return result;
 }
 
-bool TestStepWait::do_execute() throw() {
+bool TestStepWaitDiameter::do_execute() throw() {
   return a_completed;
 }
 
-void TestStepWait::do_complete() throw() {
+void TestStepWaitDiameter::do_complete() throw() {
   //a_testCase->process(); // next() not invoked; we only want to reactivate the test case
   // avoid stack overflow: we will process the test case externally when incoming message is fulfilled (TestCase.cpp), and TestManager is noticed
 }
 
-bool TestStepWait::fulfilled(const anna::DataBlock &db/*, bool matchSessionId*/) throw() {
+bool TestStepWaitDiameter::fulfilled(const anna::DataBlock &db/*, bool matchSessionId*/) throw() {
   if (a_condition.comply(db/*, matchSessionId*/)) {
     a_message = db; // store matched
     complete();
+
+    if (TestManager::instantiate().getDumpStdout()) {
+      std::cout << "Fulfilled Wait diameter Test Step" << std::endl;
+    }
+
     return true;
   }
 
+  if (TestManager::instantiate().getDumpStdout()) {
+    std::cout << "NOT Fulfilled Wait diameter Test Step" << std::endl;
+  }
+
   return false;
 }
 
-void TestStepWait::do_reset() throw() {
+void TestStepWaitDiameter::do_reset() throw() {
   a_message.clear();
   a_clientSession = NULL;
   a_serverSession = NULL;
@@ -689,6 +753,10 @@ bool TestStepCmd::do_execute() throw() {
 
 void TestStepCmd::do_complete() throw() {
 
+  if (TestManager::instantiate().getDumpStdout()) {
+    std::cout << "Executed Command Test Step (" << a_script << ") [rc=" << a_resultCode << "]" << std::endl;
+  }
+
   a_threadRunning = false;
   if (a_threadDeprecated) {
     a_threadDeprecated = false;
@@ -724,3 +792,25 @@ void TestStepCmd::do_reset() throw() {
   a_childPid = -1;
 }
 
+anna::xml::Node* TestStepIpLimit::asXML(anna::xml::Node* parent)
+throw() {
+  anna::xml::Node* result = TestStep::asXML(parent);
+  std::string limit = (a_ipLimit != UINT_MAX) ? anna::functions::asString(a_ipLimit) : "<no limit>";
+  result->createAttribute("IpLimit", limit);
+
+  return result;
+}
+
+bool TestStepIpLimit::do_execute() throw() {
+  TestManager::instantiate().setInProgressLimit(a_ipLimit);
+  complete();
+  return true; // go next
+}
+
+void TestStepIpLimit::do_complete() throw() {
+  if (TestManager::instantiate().getDumpStdout()) {
+    std::string limit = (a_ipLimit != UINT_MAX) ? anna::functions::asString(a_ipLimit) : "<no limit>";
+    std::cout << "Executed IpLimit Test Step (value = " << limit << ")" << std::endl;
+  }
+}
+