5 echo 'CoreFX test runner script.'
7 echo 'Typical Tizen command:'
8 echo ' corefx/runtest.sh'
9 echo ' --testRootDir="/opt/usr/corefx-tc/tests"'
10 echo ' --coreOverlayDir="/opt/usr/corefx-tc/coreroot"'
11 echo ' --outerloop=on/off'
12 echo ' --netcoreDir="/usr/share/dotnet.tizen/netcoreapp"'
13 echo ' --copy-netcore-to-coreroot'
14 echo ' --outputDir="/opt/usr/corefx-tc/results"'
15 echo ' --tmpDir="/opt/usr/corefx-tc/tmp"'
18 echo 'Required arguments:'
19 echo ' --testRootDir=<path> : Root directory of the test build (default: /opt/usr/corefx-tc/tests).'
20 echo ' --coreOverlayDir=<path> : Directory containing CLR and FX (default: /opt/usr/corefx-tc/coreroot).'
21 echo " --outerloop=<value> : OuterLoop category: on/off"
23 echo 'Optional arguments:'
24 echo ' --runner=<runner> : Runner for tests (dotnet or corerun, default: dotnet)'
25 echo ' --netcoreDir=<path> : Netcore (CLR and FX) system dir (default: /usr/share/dotnet.tizen/netcoreapp).'
26 echo ' --copy-netcore-to-coreroot : Copy netcore (CLR and FX) from netcore system dir to coreroot.'
27 echo ' --testDir=<path> : Run tests only in the specified directory. The path is relative to the directory'
28 echo ' specified by --testRootDir. Multiple of this switch may be specified.'
29 echo ' --testDirFile=<path> : Run tests only in the directories specified by the file at <path>. Paths are listed'
30 echo ' one line, relative to the directory specified by --testRootDir.'
31 echo ' --num-procs=<N> : Run N test processes at the same time (default is 1).'
32 echo ' -h, --help : Show usage information.'
33 echo ' --outputDir : Dir to save results to (default: /opt/usr/corefx-tc/results).'
34 echo ' --tmpDir : Local tmp dir (default: /opt/usr/corefx-tc/tmp).'
35 echo ' --user : User under which to run tests (default: $USER if not empty, else root).'
36 echo ' This is needed because sdb shell <script> does not set USER env variable.'
37 echo ' --pal-debug : Enable PAL_OUTPUTDEBUGSTRING=1 which prints pal debug messages to stderr (e.g. messages from Environment.FailFast).'
40 function print_results {
42 echo "======================="
44 echo "======================="
45 echo "# Overlay : $coreOverlayDir"
46 echo "# Tests Discovered : $countTotalTests"
47 echo "# Passed : $countPassedTests"
48 echo "# Errored : $countErroredTests"
49 echo "# Failed : $countFailedTests"
50 echo "# Skipped : $countSkippedTests"
52 echo "# Errored dlls : $countErroredDlls"
53 echo "======================="
56 # Initialize counters for bookkeeping.
64 # Variables for running tests in the background
65 ((maxProcesses = 1)) # long tests delay process creation, use a few more processors
68 declare -a testDirPaths
77 for (( i=0; i<$maxProcesses; i++ )); do
79 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
82 if ! kill -0 $pid 2>/dev/null; then
86 processIds[$i]=$pidNone
94 function get_available_process_index {
97 for (( i=0; i<$maxProcesses; i++ )); do
99 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
106 function finish_test {
108 local testScriptExitCode=$?
109 local finishedProcessIndex=$waitProcessIndex
112 local dirName=${testDirPaths[$finishedProcessIndex]}
113 local testProject=`basename $dirName`
114 local outputFilePath="$testsOutputDir/$testProject/log.out"
116 local resultsStr=$(grep -a "Total:.*Errors:.*Failed:.*Skipped:.*Time:" $outputFilePath)
118 if [ "$resultsStr" == "" ]; then
119 if [ $testScriptExitCode -ne 0 ]
121 echo "$testProject: dll errored, see log $outputFilePath"
122 countErroredDlls=$(($countErroredDlls+1))
124 # No appropriate tests were found in dll
125 echo "$testProject: no tests found, see log $outputFilePath"
128 local curTotal=$(echo $resultsStr | awk '{print $4}' | sed 's/,//')
129 local curErrored=$(echo $resultsStr | awk '{print $6}' | sed 's/,//')
130 local curFailed=$(echo $resultsStr | awk '{print $8}' | sed 's/,//')
131 local curSkipped=$(echo $resultsStr | awk '{print $10}' | sed 's/,//')
132 local curTime=$(echo $resultsStr | awk '{print $12}' | sed 's/s//')
133 local curPassed=$(echo $curTotal $curErrored $curFailed $curSkipped | awk '{print $1-$2-$3-$4}')
135 countTotalTests=$(echo $countTotalTests $curTotal | awk '{print $1+$2}')
136 countPassedTests=$(echo $countPassedTests $curPassed | awk '{print $1+$2}')
137 countErroredTests=$(echo $countErroredTests $curErrored | awk '{print $1+$2}')
138 countFailedTests=$(echo $countFailedTests $curFailed | awk '{print $1+$2}')
139 countSkippedTests=$(echo $countSkippedTests $curSkipped | awk '{print $1+$2}')
141 if [ $testScriptExitCode -ne 0 ]
143 echo "$testProject: failed, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
145 echo "$testProject: ok, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
150 function finish_remaining_tests {
151 # Finish the remaining tests in the order in which they were started
152 while ((processCount > 0)); do
157 function start_test {
158 local nextProcessIndex=$(get_available_process_index)
160 local testProject=`basename $dirName`
162 if ((nextProcessIndex == maxProcesses)); then
164 nextProcessIndex=$(get_available_process_index)
167 testDirPaths[$nextProcessIndex]=$dirName
169 if [ "$testProject" == "System.Runtime.InteropServices.Tests" ]; then
170 # Enable job control even for non-interactive shell for certain tests.
171 # This is needed to prevent ignore of SIGINT and SIGQUIT for background processes (i.e. corerun launch) by putting child processes in new process group without SIGINT and SIGQUIT ingore.
172 # SIGINT and SIGQUIT are used at least in System.Runtime.InteropServices.Tests.
176 run_test "$dirName" &
177 processIds[$nextProcessIndex]=$!
185 function handle_ctrl_c
188 echo "*** Stopping... ***"
190 exit $EXIT_CODE_EXCEPTION
193 # $1 is the path of list file
194 function read_array()
198 if [ ! -f "$1" ]; then
202 # bash in Mac OS X doesn't support 'readarray', so using alternate way instead.
203 # readarray -t theArray < "$1"
204 # Any line that starts with '#' is ignored.
205 while IFS='' read -r line || [ -n "$line" ]; do
206 if [[ $line != "#"* ]]; then
207 theArray[${#theArray[@]}]=$line
213 # Get a list of directories in which to scan for tests by reading the
214 # specified file line by line.
215 function set_test_directories {
216 local listFileName=$1
218 if [ ! -f "$listFileName" ]
220 echo "Test directories file not found at $listFileName"
221 exit $EXIT_CODE_EXCEPTION
223 testDirectories=($(read_array "$listFileName"))
226 # $1 is the name of the platform folder (e.g Unix.AnyCPU.Debug)
231 start_test $testFolder
235 # $1 is the path to the test folder
239 local testProject=`basename $1`
240 local outputDir="$testsOutputDir/$testProject"
244 local outputFilePath="$outputDir/log.out"
245 local outputXmlPath="$outputDir/testResults.xml"
247 if [ ! -d "$dirName" ]; then
248 echo "Nothing to test in $testProject" > $outputFilePath 2>&1
249 return $EXIT_CODE_EXCEPTION
252 if [ ! -e "$dirName/RunTests.sh" ]; then
253 echo "Cannot find $dirName/RunTests.sh" > $outputFilePath 2>&1
254 return $EXIT_CODE_EXCEPTION
259 ./RunTests.sh "$dotnetRunnerPath" "$outerloop" "$outputXmlPath" "$tmpDir" > $outputFilePath 2>&1
260 local testScriptExitCode=$?
262 return $testScriptExitCode
265 # Register the Ctrl-C handler
266 trap handle_ctrl_c INT
268 # Exit code constants
269 readonly EXIT_CODE_SUCCESS=0 # Script ran normally.
270 readonly EXIT_CODE_EXCEPTION=1 # Script exited because something exceptional happened (e.g. bad arguments, Ctrl-C interrupt).
271 readonly EXIT_CODE_TEST_FAILURE=2 # Script completed successfully, but one or more tests failed.
274 testRootDir="/opt/usr/corefx-tc/tests"
275 coreOverlayDir="/opt/usr/corefx-tc/coreroot/"
276 doCopyNetcoreToCoreroot=0
278 netcoreDir="/usr/share/dotnet.tizen/netcoreapp"
279 outputDir="/opt/usr/corefx-tc/results"
280 tmpDir="/opt/usr/corefx-tc/tmp"
282 if [ "$USER" == "" ]; then
291 exit $EXIT_CODE_SUCCESS
297 coreOverlayDir=${i#*=}
308 --copy-netcore-to-coreroot)
309 doCopyNetcoreToCoreroot=1
312 testDirectories[${#testDirectories[@]}]=${i#*=}
315 set_test_directories "${i#*=}"
318 ((maxProcesses = ${i#*=}))
330 export PAL_OUTPUTDEBUGSTRING="1"
333 echo "Unknown switch: $i"
335 exit $EXIT_CODE_SUCCESS
340 if [ "$runner" != "dotnet" ] && [ "$runner" != "corerun" ]; then
341 echo "--runner=dotnet or --runner=corerun is required."
343 exit $EXIT_CODE_EXCEPTION
346 if [ -z "$testRootDir" ]; then
347 echo "--testRootDir is required."
349 exit $EXIT_CODE_EXCEPTION
351 if [ ! -d "$testRootDir" ]; then
352 echo "Directory specified by --testRootDir does not exist: $testRootDir"
353 exit $EXIT_CODE_EXCEPTION
356 if [ -z "$coreOverlayDir" ]; then
357 echo "--coreOverlayDir is required."
359 exit $EXIT_CODE_EXCEPTION
361 if [ ! -d "$coreOverlayDir" ]; then
362 echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
363 exit $EXIT_CODE_EXCEPTION
366 if [ -z "$outerloop" ]; then
367 echo "--outerloop is required."
369 exit $EXIT_CODE_EXCEPTION
372 dotnetRunnerPath="$coreOverlayDir/$runner"
373 export CORE_ROOT="$coreOverlayDir"
375 export SUDO_USER="$user"
377 echo "! Make sure CLR/FX are copied to $coreOverlayDir !"
381 export LANG="en_US.UTF-8"
384 if [ $doCopyNetcoreToCoreroot == 1 ]; then
385 echo "Copying netcore ($netcoreDir) to coreroot ($coreOverlayDir)"
386 cp -r $netcoreDir/* $coreOverlayDir
389 echo "Cleanup old ni.dll"
390 for file in `find $testRootDir $coreOverlayDir -name "*.ni.*"`; do
394 testsOutputDir="$outputDir/tests"
395 mkdir -p $testsOutputDir
398 time_start=$(date +"%s")
399 if [ -z "$testDirectories" ]
401 # No test directories were specified, so run everything
402 testDirectories=( $(ls "$testRootDir/" | grep .Tests) )
405 for testDir in "${testDirectories[@]}"
407 run_tests "$testRootDir/$testDir"
410 finish_remaining_tests
413 time_end=$(date +"%s")
414 time_diff=$(($time_end-$time_start))
415 echo "$(($time_diff / 60)) minutes and $(($time_diff % 60)) seconds taken to run CoreFX tests."
417 if [ "$countErroredDlls" -gt 0 ] || [ "$countErroredTests" -gt 0 ] || [ "$countFailedTests" -gt 0 ]
419 exit $EXIT_CODE_TEST_FAILURE
422 exit $EXIT_CODE_SUCCESS