From: David Steele Date: Thu, 4 Dec 2014 17:04:21 +0000 (+0000) Subject: Updated test harness behaviour X-Git-Tag: accepted/tizen/common/20141211.150149~1^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=869f6dc6c56e97f9bfb2460c84afa8d6ebf06ea5 Updated test harness behaviour See https://review.tizen.org/gerrit/#/c/31222/ for full details Change-Id: I3c55f3c2bda3c141a483dddccc60120fd9d634ac Signed-off-by: David Steele --- diff --git a/automated-tests/execute.sh b/automated-tests/execute.sh index 1c77009..04dbd1f 100755 --- a/automated-tests/execute.sh +++ b/automated-tests/execute.sh @@ -1,20 +1,31 @@ #!/bin/bash -TEMP=`getopt -o sr --long serial,rerun -n 'execute.sh' -- "$@"` +TEMP=`getopt -o hsr --long help,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 +function usage +{ + echo -e "Usage: execute.sh\t\tExecute test cases from all modules in parallel" + echo -e " execute.sh \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 " execute.sh \tFind and execute the given test case" + exit 2 +} + +opt_serial=0 opt_rerun="" while true ; do case "$1" in - -s|--serial) opt_parallel=0 ; shift ;; + -h|--help) usage ;; + -s|--serial) opt_serial=1 ; shift ;; -r|--rerun) opt_rerun="-r" ; shift ;; --) shift; break;; - *) echo "Internal error $1!" ; exit 1 ;; + *) echo "Internal error $1!" ; exit 1 ;; esac done @@ -25,6 +36,8 @@ function execute scripts/add_style.pl $1 } + + # Clean up old test results rm -f tct*core-tests.xml @@ -35,34 +48,59 @@ fi find build \( -name "*.gcda" \) -exec rm '{}' \; -if [ $opt_parallel = 1 ] ; then +ASCII_BOLD="\e[1m" +ASCII_RESET="\e[0m" +if [ $opt_serial = 1 ] ; then + # Run all test case executables serially, create XML output if [ -n "$1" ] ; then - if [ -f "build/src/$1/tct-$1-core" ] ; then - build/src/$1/tct-$1-core -p $opt_rerun - fi + execute $1 $* 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 + + echo -ne "$ASCII_BOLD" + echo -e "Executing $mod$ASCII_RESET" + execute $mod $* fi done fi + scripts/summarize.pl else - if [ -n "$1" ] ; then - execute $1 $* + # if $1 is an executable filename, execute it· + + 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` + do + echo -e "$ASCII_BOLD" + echo -e "Executing $mod$ASCII_RESET" + build/src/$mod/tct-$mod-core $opt_rerun + done + + elif [ -f "build/src/$1/tct-$1-core" ] ; then + # First argument is an executable filename - execute only that with any + # remaining arguments + module=$1 + shift; + build/src/$module/tct-$module-core $opt_rerun $* + else - for mod in `ls -1 src/ | grep -v CMakeList ` + # 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` do - if [ $mod != 'common' ] && [ $mod != 'manual' ]; then - echo EXECUTING $mod - execute $mod $* + output=`build/src/$mod/tct-$mod-core $1` + ret=$? + if [ $ret -ne 6 ] ; then + echo $output + if [ $ret -eq 0 ] ; then echo -e "\nPassed" ; fi + exit $ret fi done + echo $1 not found fi - - scripts/summarize.pl fi diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 78b995d..227f4af 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -17,6 +17,7 @@ SET(TC_SOURCES # Append list of test harness files (Won't get parsed for test cases) LIST(APPEND TC_SOURCES + ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-accessibility-manager.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.cpp diff --git a/automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp b/automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp index c80af33..0a37d05 100644 --- a/automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp +++ b/automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp @@ -1,192 +1,14 @@ -#include #include -#include "tct-dali-toolkit-internal-core.h" -#include #include -#include -#include -#include -#include -#include - -int RunTestCase( struct testcase_s& testCase ) -{ - int result = 1; - if( testCase.startup ) - { - testCase.startup(); - } - result = testCase.function(); - if( testCase.cleanup ) - { - testCase.cleanup(); - } - return result; -} - -#define MAX_NUM_CHILDREN 16 - -struct TestCase -{ - int testCase; - const char* testCaseName; - - TestCase() - : testCase(0), - testCaseName(NULL) - { - } - - 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 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; - - RunningTestCases children; - std::vector failedTestCases; - - // 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--; - } - } - - 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 +#include +#include "tct-dali-toolkit-internal-core.h" int main(int argc, char * const argv[]) { - int result = -1; + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; - const char* optString = "pr"; - bool optParallel(false); + const char* optString = "r"; bool optRerunFailed(false); int nextOpt = 0; @@ -195,26 +17,24 @@ int main(int argc, char * const argv[]) nextOpt = getopt( argc, argv, optString ); switch(nextOpt) { - case 'p': - optParallel = true; - break; case 'r': optRerunFailed = true; break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; } } while( nextOpt != -1 ); - if( optParallel ) + if( optind == argc ) // no testcase name in argument list { - result = RunAllInParallel(argv[0], optRerunFailed); + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); } else { - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return 2; - } - result = FindAndRunTestCase(argv[1]); + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); } return result; } diff --git a/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt b/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt index a41b335..f62490f 100644 --- a/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt @@ -53,6 +53,7 @@ SET(TC_SOURCES # Append list of test harness files (Won't get parsed for test cases) LIST(APPEND TC_SOURCES + ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-accessibility-manager.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp ../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.cpp diff --git a/automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp b/automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp index 9036241..c3f6586 100644 --- a/automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp +++ b/automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp @@ -1,192 +1,14 @@ -#include #include -#include "tct-dali-toolkit-unmanaged-core.h" -#include #include -#include -#include -#include -#include -#include - -int RunTestCase( struct testcase_s& testCase ) -{ - int result = 1; - if( testCase.startup ) - { - testCase.startup(); - } - result = testCase.function(); - if( testCase.cleanup ) - { - testCase.cleanup(); - } - return result; -} - -#define MAX_NUM_CHILDREN 16 - -struct TestCase -{ - int testCase; - const char* testCaseName; - - TestCase() - : testCase(0), - testCaseName(NULL) - { - } - - 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 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; - - RunningTestCases children; - std::vector failedTestCases; - - // 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--; - } - } - - 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 +#include +#include "tct-dali-toolkit-unmanaged-core.h" int main(int argc, char * const argv[]) { - int result = -1; + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; - const char* optString = "pr"; - bool optParallel(false); + const char* optString = "r"; bool optRerunFailed(false); int nextOpt = 0; @@ -195,26 +17,24 @@ int main(int argc, char * const argv[]) nextOpt = getopt( argc, argv, optString ); switch(nextOpt) { - case 'p': - optParallel = true; - break; case 'r': optRerunFailed = true; break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; } } while( nextOpt != -1 ); - if( optParallel ) + if( optind == argc ) // no testcase name in argument list { - result = RunAllInParallel(argv[0], optRerunFailed); + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); } else { - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return 2; - } - result = FindAndRunTestCase(argv[1]); + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); } return result; } diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index afe9242..0ebd611 100644 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -36,6 +36,7 @@ SET(TC_SOURCES # Append list of test harness files (Won't get parsed for test cases) LIST(APPEND TC_SOURCES + dali-toolkit-test-utils/test-harness.cpp dali-toolkit-test-utils/toolkit-accessibility-manager.cpp dali-toolkit-test-utils/toolkit-application.cpp dali-toolkit-test-utils/toolkit-clipboard.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp new file mode 100644 index 0000000..3fed0a2 --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test-harness.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace TestHarness +{ + +typedef std::map RunningTestCases; + +namespace +{ +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"; +} + + +int RunTestCase( struct ::testcase_s& testCase ) +{ + int result = EXIT_STATUS_TESTCASE_FAILED; + + try + { + if( testCase.startup ) + { + testCase.startup(); + } + result = testCase.function(); + if( testCase.cleanup ) + { + testCase.cleanup(); + } + } + catch (...) + { + printf("Caught exception in test case.\n"); + result = EXIT_STATUS_TESTCASE_ABORTED; + } + + return result; +} + +int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutput ) +{ + int testResult = EXIT_STATUS_TESTCASE_FAILED; + + int pid = fork(); + if( pid == 0 ) // Child process + { + if( suppressOutput ) + { + close(STDOUT_FILENO); + close(STDERR_FILENO); + } + exit( RunTestCase( testCase ) ); + } + else if(pid == -1) + { + perror("fork"); + exit(EXIT_STATUS_FORK_FAILED); + } + else // Parent process + { + int status = 0; + int childPid = waitpid(-1, &status, 0); + if( childPid == -1 ) + { + perror("waitpid"); + exit(EXIT_STATUS_WAITPID_FAILED); + } + if( WIFEXITED(status) ) + { + if( childPid > 0 ) + { + testResult = WEXITSTATUS(status); + if( testResult ) + { + printf("Test case %s failed: %d\n", testCase.name, testResult); + } + } + } + else if(WIFSIGNALED(status) ) + { + testResult = EXIT_STATUS_TESTCASE_ABORTED; + +#ifdef WCOREDUMP + if(WCOREDUMP(status)) + { + printf("Test case %s crashed\n", testCase.name); + } +#endif + printf("Test case %s exited with signal %s\n", testCase.name, strsignal(WTERMSIG(status))); + } + else if(WIFSTOPPED(status)) + { + printf("Test case %s stopped with signal %s\n", testCase.name, strsignal(WSTOPSIG(status))); + } + } + return testResult; +} + +void OutputStatistics( int numPasses, int numFailures ) +{ + const char* failureColor = GREEN_COLOR; + if( numFailures > 0 ) + { + failureColor = RED_COLOR; + } + 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 numFailures = 0; + int numPasses = 0; + + // 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 ); + if( result == 0 ) + { + numPasses++; + } + else + { + numFailures++; + } + } + + OutputStatistics(numPasses, numFailures); + + return numFailures; +} + + + +// Constantly runs up to MAX_NUM_CHILDREN processes +int RunAllInParallel( const char* processName, ::testcase tc_array[], bool reRunFailed) +{ + int numFailures = 0; + int numPasses = 0; + + RunningTestCases children; + std::vector failedTestCases; + + // 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( tc_array[nextTestCase].name || numRunningChildren > 0) + { + // Create more children (up to the max number or til the end of the array) + while( numRunningChildren < MAX_NUM_CHILDREN && tc_array[nextTestCase].name ) + { + 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(EXIT_STATUS_FORK_FAILED); + } + else // Parent process + { + TestCase tc(nextTestCase, tc_array[nextTestCase].name); + children[pid] = tc; + nextTestCase++; + numRunningChildren++; + } + } + + // Wait for the next child to finish + + int status=0; + int childPid = waitpid(-1, &status, 0); + if( childPid == -1 ) + { + perror("waitpid"); + exit(EXIT_STATUS_WAITPID_FAILED); + } + + 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--; + } + } + + else if( WIFSIGNALED(status) || WIFSTOPPED(status)) + { + status = WIFSIGNALED(status)?WTERMSIG(status):WSTOPSIG(status); + + if( childPid > 0 ) + { + RunningTestCases::iterator iter = children.find(childPid); + if( iter != children.end() ) + { + printf("Test case %s exited with signal %s\n", iter->second.testCaseName, strsignal(status)); + failedTestCases.push_back(iter->second.testCase); + } + else + { + printf("Unknown child process: %d signaled %s\n", childPid, strsignal(status)); + } + + numFailures++; + numRunningChildren--; + } + } + } + + OutputStatistics( numPasses, numFailures ); + + if( reRunFailed ) + { + for( unsigned int i=0; i\t\t Execute a test case\n" + " %s \t\t Execute all test cases in parallel\n" + " %s -r\t\t Execute all test cases in parallel, rerunning failed test cases\n", + program, program, program); +} + +} // namespace diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.h new file mode 100644 index 0000000..e6dc517 --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-harness.h @@ -0,0 +1,109 @@ +#ifndef TEST_HARNESS_H +#define TEST_HARNESS_H + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace TestHarness +{ + +enum ExitStatus +{ + EXIT_STATUS_TESTCASE_SUCCEEDED, // 0 + EXIT_STATUS_TESTCASE_FAILED, // 1 + EXIT_STATUS_TESTCASE_ABORTED, // 2 + EXIT_STATUS_FORK_FAILED, // 3 + EXIT_STATUS_WAITPID_FAILED, // 4 + EXIT_STATUS_BAD_ARGUMENT, // 5 + EXIT_STATUS_TESTCASE_NOT_FOUND // 6 +}; + +const int MAX_NUM_CHILDREN(16); + +struct TestCase +{ + int testCase; + const char* testCaseName; + + TestCase() + : testCase(0), + testCaseName(NULL) + { + } + + 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; + + } +}; + +/** + * Run a test case + * @param[in] testCase The Testkit-lite test case to run + */ +int RunTestCase( struct testcase_s& testCase ); + +/** + * Run all test cases in parallel + * @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 RunAllInParallel(const char* processName, testcase tc_array[], bool reRunFailed); + +/** + * 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); + +/** + * Find the named test case in the given array, and run it + * @param[in] tc_array The array of auto-generated testkit-lite test cases + * @param[in] testCaseName the name of the test case to run + * @return 0 on success + */ +int FindAndRunTestCase(::testcase tc_array[], const char* testCaseName); + +/** + * Display usage instructions for this program + * @param[in] program The name of this program + */ +void Usage(const char* program); + +} // namespace TestHarness + +#endif diff --git a/automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp b/automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp index 195627e..87b2f56 100644 --- a/automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp +++ b/automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp @@ -1,192 +1,14 @@ -#include #include -#include "tct-dali-toolkit-core.h" -#include #include -#include -#include -#include -#include -#include - -int RunTestCase( struct testcase_s& testCase ) -{ - int result = 1; - if( testCase.startup ) - { - testCase.startup(); - } - result = testCase.function(); - if( testCase.cleanup ) - { - testCase.cleanup(); - } - return result; -} - -#define MAX_NUM_CHILDREN 16 - -struct TestCase -{ - int testCase; - const char* testCaseName; - - TestCase() - : testCase(0), - testCaseName(NULL) - { - } - - 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 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; - - RunningTestCases children; - std::vector failedTestCases; - - // 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--; - } - } - - 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 +#include +#include "tct-dali-toolkit-core.h" int main(int argc, char * const argv[]) { - int result = -1; + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; - const char* optString = "pr"; - bool optParallel(false); + const char* optString = "r"; bool optRerunFailed(false); int nextOpt = 0; @@ -195,26 +17,24 @@ int main(int argc, char * const argv[]) nextOpt = getopt( argc, argv, optString ); switch(nextOpt) { - case 'p': - optParallel = true; - break; case 'r': optRerunFailed = true; break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; } } while( nextOpt != -1 ); - if( optParallel ) + if( optind == argc ) // no testcase name in argument list { - result = RunAllInParallel(argv[0], optRerunFailed); + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); } else { - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return 2; - } - result = FindAndRunTestCase(argv[1]); + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); } return result; }