Comments and popen solution (commented)
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 20 Sep 2015 19:43:31 +0000 (21:43 +0200)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Sun, 20 Sep 2015 19:43:31 +0000 (21:43 +0200)
example/diameter/launcher/testing/TestStep.cpp
example/diameter/launcher/testing/TestStep.hpp

index bf56391..491ec65 100644 (file)
@@ -16,7 +16,6 @@
 #include <stdlib.h>    // exit
 #include <sys/wait.h>  // waitpid, pid_t, WNOHANG
 
-
 // Project
 #include <anna/xml/Compiler.hpp>
 #include <anna/core/util/Millisecond.hpp>
@@ -39,7 +38,7 @@
 namespace {
 
   void handle_sigchld(int sig) {
-    while (waitpid((pid_t)(-1), 0, WNOHANG|WNOWAIT) > 0) {}
+    while (waitpid((pid_t)(-1 /* any child (the only) */), 0, WNOHANG|WNOWAIT) > 0) {}
   }
 
   void cmdRunOnThread (TestStepCmd *step, const std::string &cmd) {
@@ -47,33 +46,46 @@ namespace {
     // Thread running:
     step->setThreadRunning(true);
 
-    // Result code:
-    int rc = 1;
+    int status = -2;
 
     struct sigaction sa;
     sa.sa_handler = &handle_sigchld;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
     if (sigaction(SIGCHLD, &sa, 0) != -1) {
-      rc = system(cmd.c_str());
+      status = system(cmd.c_str());
+     /* POPEN version:
+      char readbuf[256];
+      FILE *fp = popen(cmd.c_str(), "r");
+      if (fp) {
+        while(fgets(readbuf, sizeof(readbuf), fp))
+          step->appendOutput("\n");
+          step->appendOutput(readbuf);
+          status = pclose(fp);
+      }
+      else {
+        status = -1;
+      }
+      */
     }
     else {
       perror(0);
     }
+    // This can be implemented portably and somewhat more concisely with the signal function if you prefer:
+    // if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
+    //   perror(0);
+    //   exit(1);
+    // }
 
-    if (rc < 0) {
+    if (status < 0) {
       char buf[256];
       char const * str = strerror_r(errno, buf, 256);
-      step->setErrorMsg(anna::functions::asString("errno = %d(%s)", errno, str));
-      //std::terminate;
-    }
-    else {
-      rc >>= 8; // divide by 256
+      step->setErrorMsg(anna::functions::asString("errno = %d (%s)", errno, str));
     }
 
-    step->setResultCode(rc);
+    step->setResultCode(WEXITSTATUS(status)); // rc = status >>= 8; // divide by 256
     step->complete();
-    // TODO: timeout the system call
+    // TODO: terminate thread when deprecated (RT signal ?)
     // TODO: mutex the step while setting data here !!
   }
 }
@@ -458,7 +470,6 @@ throw() {
 
   result->createAttribute("Script", (a_script != "") ? a_script:"<no script>");
   result->createAttribute("Parameters", (a_parameters != "") ? a_parameters:"<no parameters>");
-  result->createAttribute("CommandInProgress", a_threadRunning ? "yes":"no");
   if (a_errorMsg != "") result->createAttribute("ErrorMessage", a_errorMsg);
   if (!a_threadRunning && a_resultCode != -2) {
     result->createAttribute("ResultCode", a_resultCode);
@@ -469,7 +480,7 @@ throw() {
 }
 
 bool TestStepCmd::do_execute() throw() {
-  if (!a_threadRunning) {
+  if (!a_threadRunning /* || a_threadDeprecated DO NOT WANT TO OVERLAP ... */) {
     // Special tags to replace:
     std::string cmd = getScript();
     cmd += " ";
@@ -486,7 +497,8 @@ bool TestStepCmd::do_execute() throw() {
     a_thread.detach();
   }
 
-  return false; // don't go next (wait complete)
+  return false; // don't go next (wait complete): If system function on thread stucks, then the reset test case will stuck here forever.
+                // We must implement a interrupt procedure for the thread on reset call... TODO !      
 }
 
 void TestStepCmd::do_complete() throw() {
@@ -495,6 +507,8 @@ void TestStepCmd::do_complete() throw() {
   if (a_threadDeprecated) {
     a_threadDeprecated = false;
     do_reset();
+    setErrorMsg(anna::functions::asString("Step %d deprecated due to previous reset for Test Case %llu", getNumber(), a_testCase->getId()));
+    a_testCase->setState(TestCase::State::Failed);
     return; // ignore TODO: interrupt the thread to avoid execution of the script
   }
 
index 38f40b6..1cb062d 100644 (file)
@@ -213,7 +213,7 @@ class TestStepCmd : public TestStep {
   bool a_threadDeprecated;
   int a_resultCode;
   std::string a_errorMsg;
-  //std::string a_output;
+  //std::string a_output; // for POPEN
 
   public:
     TestStepCmd(TestCase *testCase) : TestStep(testCase), a_threadRunning(false), a_threadDeprecated(false), a_resultCode(-2)/*, a_output("")*/, a_errorMsg("") { a_type = Type::Cmd; }
@@ -228,7 +228,7 @@ class TestStepCmd : public TestStep {
     int getResultCode() const throw() { return a_resultCode; }
     void setErrorMsg(const std::string &em) throw() { a_errorMsg = em; }
     const std::string &getErrorMsg() const throw() { return a_errorMsg; }
-    //void setOutput(const std::string &output) throw() { a_output = output; }
+    //void appendOutput(const std::string &output) throw() { a_output += output; }
     //const std::string &getOutput() const throw() { return a_output; }
 
     void setScript(const std::string &script) throw() { a_script = script; }