Added test-harness timeout check 20/246620/2
authorDavid Steele <david.steele@samsung.com>
Mon, 2 Nov 2020 13:40:22 +0000 (13:40 +0000)
committerDavid Steele <david.steele@samsung.com>
Mon, 2 Nov 2020 14:02:05 +0000 (14:02 +0000)
Change-Id: I36f6fb38f647559091f729b4b1e0e7f9b389b79c

automated-tests/src/dali-adaptor/dali-test-suite-utils/test-harness.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-harness.h

index 0b814e7..b53630d 100644 (file)
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <testcase.h>
+
+#include <time.h>
 #include <unistd.h>
 
+#include <chrono>
 #include <cstring>
 #include <map>
 #include <vector>
@@ -31,6 +34,8 @@ namespace TestHarness
 {
 typedef std::map<int32_t, TestCase> RunningTestCases;
 
+const double MAXIMUM_CHILD_LIFETIME(60.0f); // 1 minute
+
 const char* basename(const char* path)
 {
   const char* ptr   = path;
@@ -247,25 +252,42 @@ int32_t RunAllInParallel(const char* processName, ::testcase tc_array[], bool re
       else // Parent process
       {
         TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+        tc.startTime = std::chrono::steady_clock::now();
+
         children[pid] = tc;
         nextTestCase++;
         numRunningChildren++;
       }
     }
 
-    // Wait for the next child to finish
-
+    // Check to see if any children have finished yet
     int32_t status   = 0;
-    int32_t childPid = waitpid(-1, &status, 0);
-    if(childPid == -1)
+    int32_t childPid = waitpid(-1, &status, WNOHANG);
+    if(childPid == 0)
+    {
+      // No children have finished.
+      // Check if any have exceeded execution time
+      auto endTime = std::chrono::steady_clock::now();
+
+      for(auto& tc : children)
+      {
+        std::chrono::steady_clock::duration timeSpan = endTime - tc.second.startTime;
+        std::chrono::duration<double>       seconds  = std::chrono::duration_cast<std::chrono::duration<double>>(timeSpan);
+        if(seconds.count() > MAXIMUM_CHILD_LIFETIME)
+        {
+          // Kill the child process. A subsequent call to waitpid will process signal result below.
+          kill(tc.first, SIGKILL);
+        }
+      }
+    }
+    else if(childPid == -1) // waitpid errored
     {
       perror("waitpid");
       exit(EXIT_STATUS_WAITPID_FAILED);
     }
-
-    if(WIFEXITED(status))
+    else // a child has finished
     {
-      if(childPid > 0)
+      if(WIFEXITED(status))
       {
         int32_t testResult = WEXITSTATUS(status);
         if(testResult)
@@ -280,14 +302,11 @@ int32_t RunAllInParallel(const char* processName, ::testcase tc_array[], bool re
         }
         numRunningChildren--;
       }
-    }
-
-    else if(WIFSIGNALED(status) || WIFSTOPPED(status))
-    {
-      status = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status);
 
-      if(childPid > 0)
+      else if(WIFSIGNALED(status) || WIFSTOPPED(status))
       {
+        status = WIFSIGNALED(status) ? WTERMSIG(status) : WSTOPSIG(status);
+
         RunningTestCases::iterator iter = children.find(childPid);
         if(iter != children.end())
         {
index c4b5e03..b210918 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <testcase.h>
 
+#include <chrono>
 #include <cstdint>
 
 namespace TestHarness
@@ -39,29 +40,34 @@ const int32_t MAX_NUM_CHILDREN(16);
 
 struct TestCase
 {
-  int32_t     testCase;
-  const char* testCaseName;
+  int32_t                               testCase;
+  const char*                           testCaseName;
+  std::chrono::steady_clock::time_point startTime;
 
   TestCase()
   : testCase(0),
-    testCaseName(NULL)
+    testCaseName(NULL),
+    startTime()
   {
   }
 
   TestCase(int32_t tc, const char* name)
   : testCase(tc),
-    testCaseName(name)
+    testCaseName(name),
+    startTime()
   {
   }
   TestCase(const TestCase& rhs)
   : testCase(rhs.testCase),
-    testCaseName(rhs.testCaseName)
+    testCaseName(rhs.testCaseName),
+    startTime(rhs.startTime)
   {
   }
   TestCase& operator=(const TestCase& rhs)
   {
     testCase     = rhs.testCase;
     testCaseName = rhs.testCaseName;
+    startTime    = rhs.startTime;
     return *this;
   }
 };