Parallelized test case execution 26/31126/1
authorDavid Steele <david.steele@partner.samsung.com>
Mon, 1 Dec 2014 15:50:48 +0000 (15:50 +0000)
committerDavid Steele <david.steele@partner.samsung.com>
Mon, 1 Dec 2014 15:50:48 +0000 (15:50 +0000)
Changed build script to stop on error.

Change-Id: Id5cb74ebb3f5e5bc2b3362a8d5b67883ec18f6d0
Signed-off-by: David Steele <david.steele@partner.samsung.com>
automated-tests/build.sh
automated-tests/execute.sh
automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp
automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp
automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp

index 6c817ae851695ca505b1d42ac9535007539514d8..7c7584bff2ce3955fede793455ee5a96610928dd 100755 (executable)
@@ -1,5 +1,6 @@
 #!/bin/bash
 
+
 TEMP=`getopt -o rn --long rebuild,no-gen \
      -n 'genmake' -- "$@"`
 
@@ -43,6 +44,7 @@ else
     if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
         echo BUILDING $mod
         build $mod
+        if [ $? -ne 0 ]; then echo "Build failed" ; exit 1; fi
     fi
   done
 fi
index aedd93396b95d2a4fbc615e060e6e6a79448730c..1c77009a2f966c089917f687c79125459d0b8da9 100755 (executable)
@@ -1,5 +1,23 @@
 #!/bin/bash
 
+TEMP=`getopt -o sr --long serial,rerun -n 'execute.sh' -- "$@"`
+
+if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+opt_parallel=1
+opt_rerun=""
+while true ; do
+    case "$1" in
+        -s|--serial)   opt_parallel=0 ; shift ;;
+        -r|--rerun)    opt_rerun="-r" ; shift ;;
+        --) shift; break;;
+       *) echo "Internal error $1!" ; exit 1 ;;
+    esac
+done
+
 function execute
 {
     scripts/tctestsgen.sh $1 `pwd` desktop $2
@@ -15,20 +33,36 @@ if [ -d ../build/tizen ] ; then
     rm -f ../build/tizen/dali-core/.libs/*.gcda
 fi
 
-find build -name "*.gcda" -exec rm '{}' \;
+find build \( -name "*.gcda" \) -exec rm '{}' \;
 
-if [ -n "$1" ] ; then
-  echo EXECUTING ONLY $1
-  execute $*
+if [ $opt_parallel = 1 ] ; then
+
+    if [ -n "$1" ] ; then
+        if [ -f "build/src/$1/tct-$1-core" ] ; then
+            build/src/$1/tct-$1-core -p $opt_rerun
+        fi
+    else
+        for mod in `ls -1 src/ | grep -v CMakeList `
+        do
+            if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+                echo EXECUTING $mod
+                build/src/$mod/tct-$mod-core -p $opt_rerun
+            fi
+        done
+    fi
 
 else
-  for mod in `ls -1 src/ | grep -v CMakeList `
-  do
-    if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
-        echo EXECUTING $mod
-        execute $mod $*
+    if [ -n "$1" ] ; then
+        execute $1 $*
+    else
+        for mod in `ls -1 src/ | grep -v CMakeList `
+        do
+            if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+                echo EXECUTING $mod
+                execute $mod $*
+            fi
+        done
     fi
-  done
-fi
 
-scripts/summarize.pl
+    scripts/summarize.pl
+fi
index 2bbd96015162ccd2e797915211dd13241088e076..c80af33de348a3ffae55ef2c493c1aba098ebc5d 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-internal-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }
index b871625b546dad3bd9abc86ea118f55fadd6205b..9036241f293cc39eb5e4786985951ca57164fb71 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-unmanaged-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }
index d9c39e11c10ff454ef31f1d3306e42029c64f21b..195627e26ee366fe6d700dde45430415ece26f3f 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }