Upgraded test harness 16/59016/4
authorDavid Steele <david.steele@samsung.com>
Mon, 8 Feb 2016 11:50:10 +0000 (11:50 +0000)
committerDavid Steele <david.steele@samsung.com>
Tue, 9 Feb 2016 14:12:19 +0000 (14:12 +0000)
A new Serial mode has been added to the test harness that will run
test cases in serial without using Testkit Lite. This executes all
the dali test cases in ~35 seconds, and dumps the test case output
to stdout/stderr. It can be run using "execute.sh -S"

Have changed the Parallel mode to always re-run failing test cases,
causing it to display the failing checks.

All types of execution now write to summary.xml, and display a human
readable version of it before exiting.

execute.sh's exit status has been changed - 0 means no failures,
1 means there was a test case failure.

Ensured TestGLAbstraction initialization covers all member variables.

Changed Update/Render to check if it's required and to log a warning
if not. Test cases should avoid calling application.Update() or
application.Render() when not required.

Change-Id: I391cf76211ee22472c6b87e9f7ac255d3e147dd7
Signed-off-by: David Steele <david.steele@samsung.com>
17 files changed:
automated-tests/README.md
automated-tests/build.sh
automated-tests/execute.sh
automated-tests/scripts/output_summary.pl [new file with mode: 0755]
automated-tests/scripts/summarize.pl
automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.h
automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp

index 12d0769bfb1fc2e012d8232f9ef53699c002c111..6761a3b4542c4e500a6ee3f3b3b1b2e1caed3220 100644 (file)
@@ -80,29 +80,34 @@ Or without cleaning down the build area (Useful for fast build/run/debug cycles)
 Executing the tests
 -------------------
 
+To see a list of all of the options:
+
+    ./execute.sh -h
+
 To execute tests, cd into automated-tests and run
 
     ./execute.sh
 
 This will execute dali and dali-internal test sets. Note that the output summary for the first will be printed before running the second.
 
-By default the tests execute in parallel, which is faster but does not produce any test case output.  Use this to execute the tests in series:
+By default the tests execute in parallel, which is faster but does not produce any test case output files.  Use this to execute the tests in series and log test output to stdout/err
 
-    ./execute.sh -s
+    ./execute.sh -S
 
-To see the results, copy the style folder from web-tct_2.2.1_r1/tools/tct-mgr/style into automated-tests and run
+To use test kit lite, (which is very slow),
 
-    firefox --new-window summary.xml
+    ./execute.sh -s
 
-To see a list of all of the options:
+To see the test kit lite results, copy the style folder from web-tct_2.2.1_r1/tools/tct-mgr/style into automated-tests and run
 
-    ./execute.sh -h
+    firefox --new-window summary.xml
 
 To execute a subset of tests, you can run individual test sets, e.g.
 
-    ./execute.sh dali
+    ./execute.sh dali-toolkit
 
-To get coverage output, run
+To get coverage output (you need to first build dali libraries with
+--coverage), run
 
     ./coverage.sh
 
@@ -188,15 +193,15 @@ Debugging
 On desktop, you can debug the tests by running gdb on the test program:
 
     $ cd automated-tests
-    $ gdb build/src/dali/tct-dali-core
+    $ gdb build/src/dali-toolkit/tct-dali-toolkit-core
     gdb> r <TestCase>
 
 replace `<TestCase>` with the name of the failing testcase.
 
-For example, using testcase UtcDaliNinePatch01 from the dali-core test suite:
+For example, using testcase UtcDaliControlBackgroundProperties from the dali-toolkit test suite:
 
-    $ gdb build/src/dali/tct-dali-core
-    gdb> r UtcDaliNinePatch01
+    $ gdb build/src/dali-toolkit/tct-dali-toolkit-core
+    gdb> r UtcDaliControlBackgroundProperties
 
 
 On target, you can re-install the test RPM and associated debug RPMs manually using
@@ -206,7 +211,7 @@ On target, you can re-install the test RPM and associated debug RPMs manually us
 After installing the rpm and it's debug RPMs, you can find the executable in /opt/usr/bin/tct-dali-core. First ensure you have smack permissions set:
 
     chsmack -e "^" /usr/bin/gdb
-    chsmack -e "^" /opt/usr/bin/tct-dali-core/tct-dali-core
+    chsmack -e "^" /opt/usr/bin/tct-dali-toolkit-core/tct-dali-toolkit-core
 
 then run it under gdb as above.
 
index 7c7584bff2ce3955fede793455ee5a96610928dd..2f921352e3a6520e4d5c682acfd6e65ca00ea222 100755 (executable)
@@ -48,3 +48,6 @@ else
     fi
   done
 fi
+
+echo "Build succeeded"
+exit 0
index 04dbd1f45d302713d7851145ea535c21189b3c76..64e27eeab7584410cd3928f862e56cdddb1ca057 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-TEMP=`getopt -o hsr --long help,serial,rerun -n 'execute.sh' -- "$@"`
+TEMP=`getopt -o hsSm --long help,serial,tct,modules -n 'execute.sh' -- "$@"`
 
 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
 
@@ -9,41 +9,70 @@ eval set -- "$TEMP"
 
 function usage
 {
-    echo -e "Usage: execute.sh\t\tExecute test cases from all modules in parallel"
-    echo -e "       execute.sh <testmodule>\tExecute test cases from the given module in parallel"
-    echo -e "       execute.sh -s\t\tExecute test cases in serial using Testkit-Lite"
-    echo -e "       execute.sh -r\t\tExecute test cases in parallel, re-running failed test cases in serial afterwards"
+    echo -e "Usage: execute.sh [-s|-S|-r] [module|testcase]"
+    echo -e "       execute.sh\t\tExecute test cases from all modules in parallel"
+    echo -e "       execute.sh [module]\tExecute test cases from the given module in parallel"
+    echo -e "       execute.sh -s [module]\t\tExecute test cases in serial using Testkit-Lite"
+    echo -e "       execute.sh -S [module]\t\tExecute test cases in serial"
     echo -e "       execute.sh <testcase>\tFind and execute the given test case"
     exit 2
 }
 
-opt_serial=0
-opt_rerun=""
+opt_tct=0
+opt_serial=""
+opt_modules=0
 while true ; do
     case "$1" in
         -h|--help)     usage ;;
-        -s|--serial)   opt_serial=1 ; shift ;;
-        -r|--rerun)    opt_rerun="-r" ; shift ;;
+        -s|--tct)      opt_tct=1 ; shift ;;
+        -S|--serial)   opt_serial="-s" ; shift ;;
+        -m|--modules)  opt_modules=1 ; shift ;;
         --) shift; break;;
         *) echo "Internal error $1!" ; exit 1 ;;
     esac
 done
 
-function execute
+function execute_tct
 {
     scripts/tctestsgen.sh $1 `pwd` desktop $2
     testkit-lite -f `pwd`/tests.xml -o tct-${1}-core-tests.xml  -A --comm localhost
     scripts/add_style.pl $1
 }
 
+function summary_start
+{
+    start=`date +"%Y-%m-%d_%H_%M_%S"`
+    cat > summary.xml <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="./style/summary.xsl"?>
+<result_summary plan_name="Core">
+  <other xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" />
+  <summary test_plan_name="Dali">
+    <start_at>$start</start_at>
+    <end_at>$start</end_at>
+  </summary>
+EOF
+}
+
+function summary_end
+{
+    cat >> summary.xml <<EOF
+</result_summary>
+EOF
+}
 
+if [ $opt_modules == 1 ] ; then
+    modules= get_modules
+    echo $modules
+    exit 0
+fi
 
 # Clean up old test results
 rm -f tct*core-tests.xml
 
 # Clean up old coverage data
 if [ -d ../build/tizen ] ; then
-    rm -f ../build/tizen/dali-core/.libs/*.gcda
+    rm -f ../build/tizen/dali-toolkit/.libs/*.gcda
 fi
 
 find build \( -name "*.gcda" \) -exec rm '{}' \;
@@ -51,47 +80,56 @@ find build \( -name "*.gcda" \) -exec rm '{}' \;
 ASCII_BOLD="\e[1m"
 ASCII_RESET="\e[0m"
 
-if [ $opt_serial = 1 ] ; then
+modules=`ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual`
+if [ -f summary.xml ] ; then unlink summary.xml ; fi
+
+if [ $opt_tct == 1 ] ; then
+    # Use Test-kit lite
     # Run all test case executables serially, create XML output
     if [ -n "$1" ] ; then
-        execute $1 $*
+        execute_tct $1 $*
     else
-        for mod in `ls -1 src/ | grep -v CMakeList `
+        for mod in $modules
         do
             if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
 
                 echo -ne "$ASCII_BOLD"
                 echo -e "Executing $mod$ASCII_RESET"
-                execute $mod $*
+                execute_tct $mod $*
             fi
         done
     fi
 
     scripts/summarize.pl
+
 else
-    # if $1 is an executable filename, execute it·
+    # Execute test cases using own test harness
 
     if [ -z "$1" ] ; then
         # No arguments:
-        # Execute each test executable in turn, using parallel execution
-        for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual`
+        # Execute each test executable in turn (by default, runs tests in parallel)
+        summary_start
+        for mod in $modules
         do
             echo -e "$ASCII_BOLD"
             echo -e "Executing $mod$ASCII_RESET"
-            build/src/$mod/tct-$mod-core $opt_rerun
+            build/src/$mod/tct-$mod-core -r $opt_serial
         done
+        summary_end
 
     elif [ -f "build/src/$1/tct-$1-core" ] ; then
         # First argument is an executable filename - execute only that with any
         # remaining arguments
+        summary_start
         module=$1
         shift;
-        build/src/$module/tct-$module-core $opt_rerun $*
+        build/src/$module/tct-$module-core -r $opt_serial $*
+        summary_end
 
     else
        # First argument is not an executable. Is it a test case name?
        # Try executing each executable with the test case name until success/known failure
-        for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual`
+        for mod in $modules
         do
             output=`build/src/$mod/tct-$mod-core $1`
             ret=$?
@@ -104,3 +142,9 @@ else
         echo $1 not found
     fi
 fi
+
+if [ -f summary.xml ] ; then
+    scripts/output_summary.pl
+fi
+
+exit $?
diff --git a/automated-tests/scripts/output_summary.pl b/automated-tests/scripts/output_summary.pl
new file mode 100755 (executable)
index 0000000..dec392d
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+# Reads summary.xml and produces human readable output
+
+use strict;
+use XML::Parser;
+use Encode;
+use Getopt::Long;
+use Cwd;
+
+my $pwd = getcwd;
+my $text = "";
+my $module="";
+my %modules=();
+
+sub handle_start
+{
+    my ($p, $elt, %attrs) = @_;
+
+    if($elt =~ /suite/)
+    {
+        $module=$attrs{"name"};
+    }
+    if($elt =~ /_case/)
+    {
+        $text = "";
+    }
+}
+
+sub handle_end
+{
+  my ($p, $elt) = @_;
+  if($elt =~ /pass_case/)
+  {
+      $modules{$module}->{"pass"}=$text;
+      $text="";
+  }
+  elsif($elt =~ /fail_case/)
+  {
+      $modules{$module}->{"fail"}=$text;
+      $text="";
+  }
+}
+
+sub handle_char
+{
+  my ($p, $str) = @_;
+  $text .= $str;
+}
+
+my($parser) = new XML::Parser(Handlers => {Start => \&handle_start,
+                                           End   => \&handle_end,
+                                           Char  => \&handle_char});
+$parser->parsefile("summary.xml");
+
+my $RED_COLOR="\e[1;31m";
+my $GREEN_COLOR="\e[1;32m";
+my $ASCII_RESET="\e[0m";
+my $ASCII_BOLD="\e[1m";
+
+print "\n";
+my $totalFailures=0;
+foreach $module (keys(%modules))
+{
+    my $result_colour = $GREEN_COLOR;
+    if( $modules{$module}->{"fail"} )
+    {
+        $result_colour = $RED_COLOR;
+    }
+    my $numPasses = $modules{$module}->{"pass"};
+    my $numFailures = $modules{$module}->{"fail"};
+    $totalFailures += $numFailures;
+    print( "$ASCII_BOLD$module results:$ASCII_RESET\n" );
+    printf("Number of test passes:   %s%4d (%5.2f%%)%s\n", $ASCII_BOLD, $numPasses, 100.0 * $numPasses / ($numPasses+$numFailures),  $ASCII_RESET);
+    printf("%sNumber of test failures:%s %s%4d%s\n\n", $result_colour, $ASCII_RESET, $ASCII_BOLD, $numFailures, $ASCII_RESET);
+}
+
+exit $totalFailures == 0;
index c90eb89ccb2b80a8a0da193fd0269b42ac80f26d..82703763bffec7bcc64a4d380293b6a2d7f0ea2e 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
 
+# Generates an XML summary of test cases from Test-kit lite output XML.
+
 use strict;
 use XML::Parser;
 use Encode;
index 0a37d059844025258a5203132fe48701f073994e..fcf09c6b9f26aca336748ce821bb623633e9ffba 100644 (file)
@@ -8,8 +8,9 @@ int main(int argc, char * const argv[])
 {
   int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT;
 
-  const char* optString = "r";
-  bool optRerunFailed(false);
+  const char* optString = "rs";
+  bool optRerunFailed(true);
+  bool optRunSerially(false);
 
   int nextOpt = 0;
   do
@@ -20,6 +21,9 @@ int main(int argc, char * const argv[])
       case 'r':
         optRerunFailed = true;
         break;
+      case 's':
+        optRunSerially = true;
+        break;
       case '?':
         TestHarness::Usage(argv[0]);
         exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT);
@@ -29,7 +33,14 @@ int main(int argc, char * const argv[])
 
   if( optind == argc ) // no testcase name in argument list
   {
-    result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed);
+    if( optRunSerially )
+    {
+      result = TestHarness::RunAll( argv[0], tc_array );
+    }
+    else
+    {
+      result = TestHarness::RunAllInParallel( argv[0], tc_array, optRerunFailed );
+    }
   }
   else
   {
index 995e117af3ab1aca101900740bd765200bdda63b..5fb6e110700c896c08d953f96fa41e2dc143cf2d 100644 (file)
@@ -59,6 +59,9 @@ TestApplication::TestApplication( bool   initialize,
 
 void TestApplication::Initialize()
 {
+  // We always need the first update!
+  mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING;
+
   mCore = Dali::Integration::Core::New(
     mRenderController,
     mPlatformAbstraction,
@@ -153,11 +156,20 @@ void TestApplication::SetSurfaceWidth( unsigned int width, unsigned height )
 
 void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
 {
+  if( GetUpdateStatus() == 0 &&
+      mRenderStatus.NeedsUpdate() == false &&
+      ! GetRenderController().WasCalled(TestRenderController::RequestUpdateFunc) )
+  {
+    fprintf(stderr, "WARNING - Update not required\n");
+  }
+
   unsigned int nextVSyncTime = mLastVSyncTime + intervalMilliseconds;
   float elapsedSeconds = intervalMilliseconds / 1e3f;
 
   mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus );
 
+  GetRenderController().Initialize();
+
   mLastVSyncTime = nextVSyncTime;
 }
 
@@ -182,6 +194,15 @@ bool TestApplication::UpdateOnly( unsigned int intervalMilliseconds  )
   return mStatus.KeepUpdating();
 }
 
+bool TestApplication::GetRenderNeedsUpdate()
+{
+  return mRenderStatus.NeedsUpdate();
+}
+bool TestApplication::GetRenderHasRendered()
+{
+  return mRenderStatus.HasRendered();
+}
+
 bool TestApplication::RenderOnly( )
 {
   // Update Time values
index 3f61b93e9c4225a887750afff1bc6000b04da067..cb5a92cacc5b8a78d68b8fa926c7f31c47dd089d 100644 (file)
@@ -78,6 +78,8 @@ public:
   bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
   bool RenderOnly( );
   void ResetContext();
+  bool GetRenderNeedsUpdate();
+  bool GetRenderHasRendered();
 
 private:
   void DoUpdate( unsigned int intervalMilliseconds );
index d8af0424ac28784a99598f667e433239338b882c..4a12bdb1b4bdb0dba2b92a5b4909211cab36e233 100644 (file)
@@ -43,24 +43,19 @@ void TestGlAbstraction::Initialize()
   mIsRenderbufferResult = 0;
   mIsShaderResult = 0;
   mIsTextureResult = 0;
-  mVertexAttribArrayChanged = false;
-
+  mActiveTextureUnit = 0;
   mCheckFramebufferStatusResult = 0;
   mFramebufferStatus = 0;
   mFramebufferColorAttached = 0;
   mFramebufferDepthAttached = 0;
   mFramebufferStencilAttached = 0;
-
   mNumBinaryFormats = 0;
   mBinaryFormats = 0;
   mProgramBinaryLength = 0;
-  mGetProgramBinaryCalled = false;
 
-  mLastAutoTextureIdUsed = 0;
+  mVertexAttribArrayChanged = false;
+  mGetProgramBinaryCalled = false;
 
-  mLastShaderIdUsed = 0;
-  mLastProgramIdUsed = 0;
-  mLastUniformIdUsed = 0;
   mLastShaderCompiled = 0;
   mLastClearBitMask = 0;
   mClearCount = 0;
@@ -71,6 +66,10 @@ void TestGlAbstraction::Initialize()
   mLastBlendFuncDstRgb    = 0;
   mLastBlendFuncSrcAlpha  = 0;
   mLastBlendFuncDstAlpha  = 0;
+  mLastAutoTextureIdUsed = 0;
+  mLastShaderIdUsed = 0;
+  mLastProgramIdUsed = 0;
+  mLastUniformIdUsed = 0;
 
   mUniforms.clear();
   mProgramUniforms1i.clear();
@@ -78,6 +77,11 @@ void TestGlAbstraction::Initialize()
   mProgramUniforms2f.clear();
   mProgramUniforms3f.clear();
   mProgramUniforms4f.clear();
+
+  for( unsigned int i=0; i<MAX_ATTRIBUTE_CACHE_SIZE; ++i )
+  {
+    mVertexAttribArrayState[i] = false;
+  }
 }
 
 void TestGlAbstraction::PreRender()
index dea1c9078ca1983aff2314e282dac575bbbc2754..3d35394c5455c89a88d15d68d3404d23363340c8 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <sstream>
 #include <string>
+#include <cstring>
 #include <map>
 #include <cstdio>
 #include <cstring> // for strcmp
@@ -350,11 +351,11 @@ public:
   inline void DeleteTextures(GLsizei n, const GLuint* textures)
   {
     std::stringstream out;
-    out << n << ", " << textures << " = [" ;
+    out << n << ", " << textures << " = [";
 
     for(GLsizei i=0; i<n; i++)
     {
-      out << textures[i] << ", " ;
+      out << textures[i] << ", ";
       mDeletedTextureIds.push_back(textures[i]);
     }
     out << "]";
index 533355c79f70e110cdf27949926b0b13348f749c..65a884ee8a49bfedafde89877d9b827bcd236deb 100644 (file)
@@ -132,5 +132,10 @@ void TestGlSyncAbstraction::ResetTrace() { mTrace.Reset(); }
  */
 TraceCallStack& TestGlSyncAbstraction::GetTrace() { return mTrace; }
 
+int TestGlSyncAbstraction::GetNumberOfSyncObjects()
+{
+  return mSyncObjects.size();
+}
+
 
 } // Dali
index e2331765992c900327189745c9ab0e3feb903e3b..278bcd77859bcc1fb0197e6910280bcc5482b805 100644 (file)
@@ -100,6 +100,13 @@ public: // TEST FUNCTIONS
    */
   TraceCallStack& GetTrace();
 
+  /**
+   * Get the number of sync objects
+   *
+   * @return the number of sync objects
+   */
+  int GetNumberOfSyncObjects();
+
 private:
   typedef std::vector<TestSyncObject*>   SyncContainer;
   typedef SyncContainer::iterator SyncIter;
index 55beebc6bd7fece31358d17cc4cf46d89f05ef2e..332ddaadfd5f0426b9c1f0845166a76107d0c8ab 100644 (file)
@@ -29,15 +29,18 @@ namespace TestHarness
 
 typedef std::map<int, TestCase> RunningTestCases;
 
-namespace
+const char* basename(const char* path)
 {
-const char* RED_COLOR="\e[1;31m";
-const char* GREEN_COLOR="\e[1;32m";
-const char* ASCII_RESET="\e[0m";
-const char* ASCII_BOLD="\e[1m";
+  const char* ptr=path;
+  const char* slash=NULL;
+  for( ; *ptr != '\0' ; ++ptr )
+  {
+    if(*ptr == '/') slash=ptr;
+  }
+  if(slash != NULL) ++slash;
+  return slash;
 }
 
-
 int RunTestCase( struct ::testcase_s& testCase )
 {
   int result = EXIT_STATUS_TESTCASE_FAILED;
@@ -71,7 +74,24 @@ int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutpu
       close(STDOUT_FILENO);
       close(STDERR_FILENO);
     }
-    exit( RunTestCase( testCase ) );
+    else
+    {
+      printf("\n");
+      for(int i=0; i<80; ++i) printf("#");
+      printf("\nTC: %s\n", testCase.name);
+      fflush(stdout);
+    }
+
+    int status = RunTestCase( testCase );
+
+    if( ! suppressOutput )
+    {
+      fflush(stdout);
+      fflush(stderr);
+      fclose(stdout);
+      fclose(stderr);
+    }
+    exit( status );
   }
   else if(pid == -1)
   {
@@ -81,7 +101,7 @@ int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutpu
   else // Parent process
   {
     int status = 0;
-    int childPid = waitpid(-1, &status, 0);
+    int childPid = waitpid(pid, &status, 0);
     if( childPid == -1 )
     {
       perror("waitpid");
@@ -100,38 +120,55 @@ int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutpu
     }
     else if(WIFSIGNALED(status) )
     {
+      int signal = WTERMSIG(status);
       testResult = EXIT_STATUS_TESTCASE_ABORTED;
-
-#ifdef WCOREDUMP
-      if(WCOREDUMP(status))
+      if( signal == SIGABRT )
+      {
+        printf("Test case %s failed: test case asserted\n", testCase.name );
+      }
+      else
       {
-        printf("Test case %s failed: due to a crash\n", testCase.name);
+        printf("Test case %s failed: exit with signal %s\n", testCase.name, strsignal(WTERMSIG(status)));
       }
-#endif
-      printf("Test case %s failed: exit with signal %s\n", testCase.name, strsignal(WTERMSIG(status)));
     }
     else if(WIFSTOPPED(status))
     {
       printf("Test case %s failed: stopped with signal %s\n", testCase.name, strsignal(WSTOPSIG(status)));
     }
   }
+  fflush(stdout);
+  fflush(stderr);
   return testResult;
 }
 
-void OutputStatistics( int numPasses, int numFailures )
+void OutputStatistics( const char* processName, int numPasses, int numFailures )
 {
-  const char* failureColor = GREEN_COLOR;
-  if( numFailures > 0 )
+  FILE* fp=fopen("summary.xml", "a");
+  if( fp != NULL )
   {
-    failureColor = RED_COLOR;
+    fprintf( fp,
+             "  <suite name=\"%s\">\n"
+             "    <total_case>%d</total_case>\n"
+             "    <pass_case>%d</pass_case>\n"
+             "    <pass_rate>%5.2f</pass_rate>\n"
+             "    <fail_case>%d</fail_case>\n"
+             "    <fail_rate>%5.2f</fail_rate>\n"
+             "    <block_case>0</block_case>\n"
+             "    <block_rate>0.00</block_rate>\n"
+             "    <na_case>0</na_case>\n"
+             "    <na_rate>0.00</na_rate>\n"
+             "  </suite>\n",
+             basename(processName),
+             numPasses+numFailures,
+             numPasses,
+             (float)numPasses/(numPasses+numFailures),
+             numFailures,
+             (float)numFailures/(numPasses+numFailures) );
+    fclose(fp);
   }
-  printf("\rNumber of test passes:   %s%4d (%5.2f%%)%s\n", ASCII_BOLD, numPasses, 100.0f * (float)numPasses / (numPasses+numFailures),  ASCII_RESET);
-  printf("%sNumber of test failures:%s %s%4d%s\n", failureColor, ASCII_RESET, ASCII_BOLD, numFailures, ASCII_RESET);
-
 }
 
-
-int RunAll(const char* processName, ::testcase tc_array[], bool reRunFailed)
+int RunAll( const char* processName, ::testcase tc_array[] )
 {
   int numFailures = 0;
   int numPasses = 0;
@@ -139,7 +176,7 @@ int RunAll(const char* processName, ::testcase tc_array[], bool reRunFailed)
   // Run test cases in child process( to kill output/handle signals ), but run serially.
   for( unsigned int i=0; tc_array[i].name; i++)
   {
-    int result = RunTestCaseInChildProcess( tc_array[i], true );
+    int result = RunTestCaseInChildProcess( tc_array[i], false );
     if( result == 0 )
     {
       numPasses++;
@@ -150,13 +187,11 @@ int RunAll(const char* processName, ::testcase tc_array[], bool reRunFailed)
     }
   }
 
-  OutputStatistics(numPasses, numFailures);
+  OutputStatistics( processName, numPasses, numFailures);
 
   return numFailures;
 }
 
-
-
 // Constantly runs up to MAX_NUM_CHILDREN processes
 int RunAllInParallel(  const char* processName, ::testcase tc_array[], bool reRunFailed)
 {
@@ -250,7 +285,7 @@ int RunAllInParallel(  const char* processName, ::testcase tc_array[], bool reRu
     }
   }
 
-  OutputStatistics( numPasses, numFailures );
+  OutputStatistics( processName, numPasses, numFailures );
 
   if( reRunFailed )
   {
index e6dc5178de3310ab99750d8d93672f6131c0550c..53ac0b98023ffec5035449917150ac0642759130 100644 (file)
@@ -85,10 +85,9 @@ int RunAllInParallel(const char* processName, testcase tc_array[], bool reRunFai
  * Run all test cases in serial
  * @param[in] processName The name of this process
  * @param[in] tc_array The array of auto-generated testkit-lite test cases
- * @param[in] reRunFailed True if failed test cases should be re-run
  * @return 0 on success
  */
-int RunAll(const char* processName, testcase tc_array[], bool reRunFailed);
+int RunAll( const char* processName, testcase tc_array[] );
 
 /**
  * Find the named test case in the given array, and run it
index 921088bdd02d046acef28739f96020e2a09c2ae0..bda38d337cfffee1fdf187b30db7a9cee6ab8c99 100644 (file)
@@ -84,7 +84,6 @@ int TraceCallStack::CountMethod(std::string method) const
   return numCalls;
 }
 
-
 /**
  * Search for a method in the stack with the given parameter list
  * @param[in] method The name of the method
@@ -93,16 +92,27 @@ int TraceCallStack::CountMethod(std::string method) const
  */
 bool TraceCallStack::FindMethodAndParams(std::string method, std::string params) const
 {
-  bool found = false;
+  return FindIndexFromMethodAndParams( method, params ) > -1;
+}
+
+/**
+ * Search for a method in the stack with the given parameter list
+ * @param[in] method The name of the method
+ * @param[in] params A comma separated list of parameter values
+ * @return index in the stack where the method was found or -1 otherwise
+ */
+int TraceCallStack::FindIndexFromMethodAndParams(std::string method, std::string params) const
+{
+  int index = -1;
   for( size_t i=0; i < mCallStack.size(); i++ )
   {
     if( 0 == mCallStack[i][0].compare(method) && 0 == mCallStack[i][1].compare(params) )
     {
-      found = true;
+      index = i;
       break;
     }
   }
-  return found;
+  return index;
 }
 
 /**
index 25b77f885bbf8ad05359785043655781f9e9246c..d319487f47f0e83f380fb06f8169587bbb1d687d 100644 (file)
@@ -77,6 +77,14 @@ public:
    */
   bool FindMethodAndParams(std::string method, std::string params) const;
 
+  /**
+   * Search for a method in the stack with the given parameter list
+   * @param[in] method The name of the method
+   * @param[in] params A comma separated list of parameter values
+   * @return index in the stack where the method was found or -1 otherwise
+   */
+  int FindIndexFromMethodAndParams(std::string method, std::string params) const;
+
   /**
    * Test if the given method and parameters are at a given index in the stack
    * @param[in] index Index in the call stack
index 87b2f566592ab1beccced7ae51216981cad9c953..b603310336cbfd2bc046ccb561e1a3ba17847efc 100644 (file)
@@ -8,8 +8,9 @@ int main(int argc, char * const argv[])
 {
   int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT;
 
-  const char* optString = "r";
-  bool optRerunFailed(false);
+  const char* optString = "rs";
+  bool optRerunFailed(true);
+  bool optRunSerially(false);
 
   int nextOpt = 0;
   do
@@ -20,6 +21,9 @@ int main(int argc, char * const argv[])
       case 'r':
         optRerunFailed = true;
         break;
+      case 's':
+        optRunSerially = true;
+        break;
       case '?':
         TestHarness::Usage(argv[0]);
         exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT);
@@ -29,7 +33,14 @@ int main(int argc, char * const argv[])
 
   if( optind == argc ) // no testcase name in argument list
   {
-    result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed);
+    if( optRunSerially )
+    {
+      result = TestHarness::RunAll( argv[0], tc_array );
+    }
+    else
+    {
+      result = TestHarness::RunAllInParallel( argv[0], tc_array, optRerunFailed );
+    }
   }
   else
   {