[Tizen] separate PIC and PIE to fix x86_64 build error
[platform/upstream/dotnet/runtime.git] / runtest_fx.sh
1 #!/usr/bin/env bash
2
3 function print_usage {
4     echo ''
5     echo 'CoreFX test runner script.'
6     echo ''
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"'
16     echo '    --user="root"'
17     echo ''
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"
22     echo ''
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).'
38 }
39
40 function print_results {
41     echo ""
42     echo "======================="
43     echo "     Test Results"
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"
51     echo "#"
52     echo "# Errored dlls     : $countErroredDlls"
53     echo "======================="
54 }
55
56 # Initialize counters for bookkeeping.
57 countTotalTests=0
58 countPassedTests=0
59 countErroredTests=0
60 countFailedTests=0
61 countSkippedTests=0
62 countErroredDlls=0
63
64 # Variables for running tests in the background
65 ((maxProcesses = 1)) # long tests delay process creation, use a few more processors
66
67 ((processCount = 0))
68 declare -a testDirPaths
69 declare -a processIds
70 waitProcessIndex=
71 pidNone=0
72
73 function waitany {
74     local pid
75     local exitcode
76     while true; do
77         for (( i=0; i<$maxProcesses; i++ )); do
78             pid=${processIds[$i]}
79             if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
80                 continue
81             fi
82             if ! kill -0 $pid 2>/dev/null; then
83                 wait $pid
84                 exitcode=$?
85                 waitProcessIndex=$i
86                 processIds[$i]=$pidNone
87                 return $exitcode
88             fi
89         done
90         sleep 0.1
91     done
92 }
93
94 function get_available_process_index {
95     local pid
96     local i=0
97     for (( i=0; i<$maxProcesses; i++ )); do
98         pid=${processIds[$i]}
99         if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
100             break
101         fi
102     done
103     echo $i
104 }
105
106 function finish_test {
107     waitany
108     local testScriptExitCode=$?
109     local finishedProcessIndex=$waitProcessIndex
110     ((--processCount))
111
112     local dirName=${testDirPaths[$finishedProcessIndex]}
113     local testProject=`basename $dirName`
114     local outputFilePath="$testsOutputDir/$testProject/log.out"
115
116     local resultsStr=$(grep -a "Total:.*Errors:.*Failed:.*Skipped:.*Time:" $outputFilePath)
117
118     if [ "$resultsStr" == "" ]; then
119         if [ $testScriptExitCode -ne 0 ]
120         then
121             echo "$testProject: dll errored, see log $outputFilePath"
122             countErroredDlls=$(($countErroredDlls+1))
123         else
124             # No appropriate tests were found in dll
125             echo "$testProject: no tests found, see log $outputFilePath"
126         fi
127     else
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}')
134
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}')
140
141         if [ $testScriptExitCode -ne 0 ]
142         then
143             echo "$testProject: failed, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
144         else
145             echo "$testProject: ok, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
146         fi
147     fi
148 }
149
150 function finish_remaining_tests {
151     # Finish the remaining tests in the order in which they were started
152     while ((processCount > 0)); do
153         finish_test
154     done
155 }
156
157 function start_test {
158     local nextProcessIndex=$(get_available_process_index)
159     local dirName="$1"
160     local testProject=`basename $dirName`
161
162     if ((nextProcessIndex == maxProcesses)); then
163         finish_test
164         nextProcessIndex=$(get_available_process_index)
165     fi
166
167     testDirPaths[$nextProcessIndex]=$dirName
168
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.
173         set -m
174     fi
175
176     run_test "$dirName" &
177     processIds[$nextProcessIndex]=$!
178
179     set +m
180
181     ((++processCount))
182 }
183
184 # Handle Ctrl-C.
185 function handle_ctrl_c
186 {
187     echo ""
188     echo "*** Stopping... ***"
189     print_results
190     exit $EXIT_CODE_EXCEPTION
191 }
192
193 # $1 is the path of list file
194 function read_array()
195 {
196     local theArray=()
197
198     if [ ! -f "$1" ]; then
199         return
200     fi
201
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
208         fi
209     done < "$1"
210     echo ${theArray[@]}
211 }
212
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
217
218     if [ ! -f "$listFileName" ]
219     then
220         echo "Test directories file not found at $listFileName"
221         exit $EXIT_CODE_EXCEPTION
222     fi
223     testDirectories=($(read_array "$listFileName"))
224 }
225
226 # $1 is the name of the platform folder (e.g Unix.AnyCPU.Debug)
227 function run_tests()
228 {
229     for testFolder in $@
230     do
231        start_test $testFolder
232     done
233 }
234
235 # $1 is the path to the test folder
236 function run_test()
237 {
238     local dirName="$1"
239     local testProject=`basename $1`
240     local outputDir="$testsOutputDir/$testProject"
241
242     mkdir -p $outputDir
243
244     local outputFilePath="$outputDir/log.out"
245     local outputXmlPath="$outputDir/testResults.xml"
246
247     if [ ! -d "$dirName" ]; then
248         echo "Nothing to test in $testProject" > $outputFilePath 2>&1
249         return $EXIT_CODE_EXCEPTION
250     fi
251
252     if [ ! -e "$dirName/RunTests.sh" ]; then
253         echo "Cannot find $dirName/RunTests.sh" > $outputFilePath 2>&1
254         return $EXIT_CODE_EXCEPTION
255     fi
256
257     cd $dirName
258
259     ./RunTests.sh "$dotnetRunnerPath" "$outerloop" "$outputXmlPath" "$tmpDir" > $outputFilePath 2>&1
260     local testScriptExitCode=$?
261
262     return $testScriptExitCode
263 }
264
265 # Register the Ctrl-C handler
266 trap handle_ctrl_c INT
267
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.
272
273 # Argument variables
274 testRootDir="/opt/usr/corefx-tc/tests"
275 coreOverlayDir="/opt/usr/corefx-tc/coreroot/"
276 doCopyNetcoreToCoreroot=0
277 runner="dotnet"
278 netcoreDir="/usr/share/dotnet.tizen/netcoreapp"
279 outputDir="/opt/usr/corefx-tc/results"
280 tmpDir="/opt/usr/corefx-tc/tmp"
281 user="$USER"
282 if [ "$USER" == "" ]; then
283   user="root"
284 fi
285
286 for i in "$@"
287 do
288     case $i in
289         -h|--help)
290             print_usage
291             exit $EXIT_CODE_SUCCESS
292             ;;
293         --testRootDir=*)
294             testRootDir=${i#*=}
295             ;;
296         --coreOverlayDir=*)
297             coreOverlayDir=${i#*=}
298             ;;
299         --outerloop=*)
300             outerloop=${i#*=}
301             ;;
302         --runner=*)
303             runner=${i#*=}
304             ;;
305         --netcoreDir=*)
306             netcoreDir=${i#*=}
307             ;;
308         --copy-netcore-to-coreroot)
309             doCopyNetcoreToCoreroot=1
310             ;;
311         --testDir=*)
312             testDirectories[${#testDirectories[@]}]=${i#*=}
313             ;;
314         --testDirFile=*)
315             set_test_directories "${i#*=}"
316             ;;
317         --num-procs=*)
318             ((maxProcesses = ${i#*=}))
319             ;;
320         --outputDir=*)
321             outputDir=${i#*=}
322             ;;
323         --tmpDir=*)
324             tmpDir=${i#*=}
325             ;;
326         --user=*)
327             user=${i#*=}
328             ;;
329         --pal-debug)
330             export PAL_OUTPUTDEBUGSTRING="1"
331             ;;
332         *)
333             echo "Unknown switch: $i"
334             print_usage
335             exit $EXIT_CODE_SUCCESS
336             ;;
337     esac
338 done
339
340 if [ "$runner" != "dotnet" ] && [ "$runner" != "corerun" ]; then
341     echo "--runner=dotnet or --runner=corerun is required."
342     print_usage
343     exit $EXIT_CODE_EXCEPTION
344 fi
345
346 if [ -z "$testRootDir" ]; then
347     echo "--testRootDir is required."
348     print_usage
349     exit $EXIT_CODE_EXCEPTION
350 fi
351 if [ ! -d "$testRootDir" ]; then
352     echo "Directory specified by --testRootDir does not exist: $testRootDir"
353     exit $EXIT_CODE_EXCEPTION
354 fi
355
356 if [ -z "$coreOverlayDir" ]; then
357     echo "--coreOverlayDir is required."
358     print_usage
359     exit $EXIT_CODE_EXCEPTION
360 fi
361 if [ ! -d "$coreOverlayDir" ]; then
362     echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
363     exit $EXIT_CODE_EXCEPTION
364 fi
365
366 if [ -z "$outerloop" ]; then
367     echo "--outerloop is required."
368     print_usage
369     exit $EXIT_CODE_EXCEPTION
370 fi
371
372 dotnetRunnerPath="$coreOverlayDir/$runner"
373 export CORE_ROOT="$coreOverlayDir"
374 export USER="$user"
375 export SUDO_USER="$user"
376
377 echo "! Make sure CLR/FX are copied to $coreOverlayDir !"
378
379 if [ "$LANG" == "" ]
380 then
381     export LANG="en_US.UTF-8"
382 fi
383
384 if [ $doCopyNetcoreToCoreroot == 1 ]; then
385     echo "Copying netcore ($netcoreDir) to coreroot ($coreOverlayDir)"
386     cp -r $netcoreDir/* $coreOverlayDir
387 fi
388
389 echo "Cleanup old ni.dll"
390 for file in `find $testRootDir $coreOverlayDir -name "*.ni.*"`; do
391     rm $file
392 done
393
394 testsOutputDir="$outputDir/tests"
395 mkdir -p $testsOutputDir
396 mkdir -p $tmpDir
397
398 time_start=$(date +"%s")
399 if [ -z "$testDirectories" ]
400 then
401     # No test directories were specified, so run everything
402     testDirectories=( $(ls "$testRootDir/" | grep .Tests) )
403 fi
404
405 for testDir in "${testDirectories[@]}"
406 do
407     run_tests "$testRootDir/$testDir"
408 done
409
410 finish_remaining_tests
411 print_results
412
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."
416
417 if [ "$countErroredDlls" -gt 0 ] || [ "$countErroredTests" -gt 0 ] || [ "$countFailedTests" -gt 0 ]
418 then
419     exit $EXIT_CODE_TEST_FAILURE
420 fi
421
422 exit $EXIT_CODE_SUCCESS