[Tizen] Select ICU build time version
[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 '  --netcoreDir=<path>              : Netcore (CLR and FX) system dir (default: /usr/share/dotnet.tizen/netcoreapp).'
25     echo '  --copy-netcore-to-coreroot       : Copy netcore (CLR and FX) from netcore system dir to coreroot.'
26     echo '  --testDir=<path>                 : Run tests only in the specified directory. The path is relative to the directory'
27     echo '                                     specified by --testRootDir. Multiple of this switch may be specified.'
28     echo '  --testDirFile=<path>             : Run tests only in the directories specified by the file at <path>. Paths are listed'
29     echo '                                     one line, relative to the directory specified by --testRootDir.'
30     echo '  --num-procs=<N>                  : Run N test processes at the same time (default is 1).'
31     echo '  -h, --help                       : Show usage information.'
32     echo '  --outputDir                      : Dir to save results to (default: /opt/usr/corefx-tc/results).'
33     echo '  --tmpDir                         : Local tmp dir (default: /opt/usr/corefx-tc/tmp).'
34     echo '  --user                           : User under which to run tests (default: root). This is needed because sdb shell <script> does not set USER env variable'
35     echo '  --pal-debug                      : Enable PAL_OUTPUTDEBUGSTRING=1 which prints pal debug messages to stderr (e.g. messages from Environment.FailFast)'
36 }
37
38 function print_results {
39     echo ""
40     echo "======================="
41     echo "     Test Results"
42     echo "======================="
43     echo "# Overlay          : $coreOverlayDir"
44     echo "# Tests Discovered : $countTotalTests"
45     echo "# Passed           : $countPassedTests"
46     echo "# Errored          : $countErroredTests"
47     echo "# Failed           : $countFailedTests"
48     echo "# Skipped          : $countSkippedTests"
49     echo "#"
50     echo "# Errored dlls     : $countErroredDlls"
51     echo "======================="
52 }
53
54 # Initialize counters for bookkeeping.
55 countTotalTests=0
56 countPassedTests=0
57 countErroredTests=0
58 countFailedTests=0
59 countSkippedTests=0
60 countErroredDlls=0
61
62 # Variables for running tests in the background
63 ((maxProcesses = 1)) # long tests delay process creation, use a few more processors
64
65 ((processCount = 0))
66 declare -a testDirPaths
67 declare -a processIds
68 waitProcessIndex=
69 pidNone=0
70
71 function waitany {
72     local pid
73     local exitcode
74     while true; do
75         for (( i=0; i<$maxProcesses; i++ )); do
76             pid=${processIds[$i]}
77             if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
78                 continue
79             fi
80             if ! kill -0 $pid 2>/dev/null; then
81                 wait $pid
82                 exitcode=$?
83                 waitProcessIndex=$i
84                 processIds[$i]=$pidNone
85                 return $exitcode
86             fi
87         done
88         sleep 0.1
89     done
90 }
91
92 function get_available_process_index {
93     local pid
94     local i=0
95     for (( i=0; i<$maxProcesses; i++ )); do
96         pid=${processIds[$i]}
97         if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
98             break
99         fi
100     done
101     echo $i
102 }
103
104 function finish_test {
105     waitany
106     local testScriptExitCode=$?
107     local finishedProcessIndex=$waitProcessIndex
108     ((--processCount))
109
110     local dirName=${testDirPaths[$finishedProcessIndex]}
111     local testProject=`basename $dirName`
112     local outputFilePath="$testsOutputDir/$testProject/log.out"
113
114     local resultsStr=$(grep "Total:.*Errors:.*Failed:.*Skipped:.*Time:" $outputFilePath)
115
116     if [ "$resultsStr" == "" ]; then
117         if [ $testScriptExitCode -ne 0 ]
118         then
119             echo "$testProject: dll errored, see log $outputFilePath"
120             countErroredDlls=$(($countErroredDlls+1))
121         else
122             # No appropriate tests were found in dll
123             echo "$testProject: no tests found, see log $outputFilePath"
124         fi
125     else
126         local curTotal=$(echo $resultsStr | awk '{print $4}' | sed 's/,//')
127         local curErrored=$(echo $resultsStr | awk '{print $6}' | sed 's/,//')
128         local curFailed=$(echo $resultsStr | awk '{print $8}' | sed 's/,//')
129         local curSkipped=$(echo $resultsStr | awk '{print $10}' | sed 's/,//')
130         local curTime=$(echo $resultsStr | awk '{print $12}' | sed 's/s//')
131         local curPassed=$(echo $curTotal $curErrored $curFailed $curSkipped | awk '{print $1-$2-$3-$4}')
132
133         countTotalTests=$(echo $countTotalTests $curTotal | awk '{print $1+$2}')
134         countPassedTests=$(echo $countPassedTests $curPassed | awk '{print $1+$2}')
135         countErroredTests=$(echo $countErroredTests $curErrored | awk '{print $1+$2}')
136         countFailedTests=$(echo $countFailedTests $curFailed | awk '{print $1+$2}')
137         countSkippedTests=$(echo $countSkippedTests $curSkipped | awk '{print $1+$2}')
138
139         if [ $testScriptExitCode -ne 0 ]
140         then
141             echo "$testProject: failed, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
142         else
143             echo "$testProject: ok, Total:$curTotal Passed:$curPassed Errored:$curErrored Failed:$curFailed Skipped:$curSkipped Time:$curTime, see log $outputFilePath"
144         fi
145     fi
146 }
147
148 function finish_remaining_tests {
149     # Finish the remaining tests in the order in which they were started
150     while ((processCount > 0)); do
151         finish_test
152     done
153 }
154
155 function start_test {
156     local nextProcessIndex=$(get_available_process_index)
157     local dirName="$1"
158     local testProject=`basename $dirName`
159
160     if ((nextProcessIndex == maxProcesses)); then
161         finish_test
162         nextProcessIndex=$(get_available_process_index)
163     fi
164
165     testDirPaths[$nextProcessIndex]=$dirName
166
167     run_test "$dirName" &
168     processIds[$nextProcessIndex]=$!
169
170     ((++processCount))
171 }
172
173 # Handle Ctrl-C.
174 function handle_ctrl_c
175 {
176     echo ""
177     echo "*** Stopping... ***"
178     print_results
179     exit $EXIT_CODE_EXCEPTION
180 }
181
182 # $1 is the path of list file
183 function read_array()
184 {
185     local theArray=()
186
187     if [ ! -f "$1" ]; then
188         return
189     fi
190
191     # bash in Mac OS X doesn't support 'readarray', so using alternate way instead.
192     # readarray -t theArray < "$1"
193     # Any line that starts with '#' is ignored.
194     while IFS='' read -r line || [ -n "$line" ]; do
195         if [[ $line != "#"* ]]; then
196             theArray[${#theArray[@]}]=$line
197         fi
198     done < "$1"
199     echo ${theArray[@]}
200 }
201
202 # Get a list of directories in which to scan for tests by reading the
203 # specified file line by line.
204 function set_test_directories {
205     local listFileName=$1
206
207     if [ ! -f "$listFileName" ]
208     then
209         echo "Test directories file not found at $listFileName"
210         exit $EXIT_CODE_EXCEPTION
211     fi
212     testDirectories=($(read_array "$listFileName"))
213 }
214
215 # $1 is the name of the platform folder (e.g Unix.AnyCPU.Debug)
216 function run_tests()
217 {
218     for testFolder in $@
219     do
220        start_test $testFolder
221     done
222 }
223
224 # $1 is the path to the test folder
225 function run_test()
226 {
227     local dirName="$1"
228     local testProject=`basename $1`
229     local outputDir="$testsOutputDir/$testProject"
230
231     mkdir -p $outputDir
232
233     local outputFilePath="$outputDir/log.out"
234     local outputXmlPath="$outputDir/testResults.xml"
235
236     if [ ! -d "$dirName" ]; then
237         echo "Nothing to test in $testProject" > $outputFilePath 2>&1
238         return $EXIT_CODE_EXCEPTION
239     fi
240
241     if [ ! -e "$dirName/RunTests.sh" ]; then
242         echo "Cannot find $dirName/RunTests.sh" > $outputFilePath 2>&1
243         return $EXIT_CODE_EXCEPTION
244     fi
245
246     cd $dirName
247
248     ./RunTests.sh "$coreOverlayDir" "$outerloop" "$outputXmlPath" "$tmpDir" > $outputFilePath 2>&1
249     local testScriptExitCode=$?
250
251     return $testScriptExitCode
252 }
253
254 # Register the Ctrl-C handler
255 trap handle_ctrl_c INT
256
257 # Exit code constants
258 readonly EXIT_CODE_SUCCESS=0       # Script ran normally.
259 readonly EXIT_CODE_EXCEPTION=1     # Script exited because something exceptional happened (e.g. bad arguments, Ctrl-C interrupt).
260 readonly EXIT_CODE_TEST_FAILURE=2  # Script completed successfully, but one or more tests failed.
261
262 # Argument variables
263 testRootDir="/opt/usr/corefx-tc/tests"
264 coreOverlayDir="/opt/usr/corefx-tc/coreroot/"
265 doCopyNetcoreToCoreroot=0
266 netcoreDir="/usr/share/dotnet.tizen/netcoreapp"
267 outputDir="/opt/usr/corefx-tc/results"
268 tmpDir="/opt/usr/corefx-tc/tmp"
269 user="root"
270
271 for i in "$@"
272 do
273     case $i in
274         -h|--help)
275             print_usage
276             exit $EXIT_CODE_SUCCESS
277             ;;
278         --testRootDir=*)
279             testRootDir=${i#*=}
280             ;;
281         --coreOverlayDir=*)
282             coreOverlayDir=${i#*=}
283             ;;
284         --outerloop=*)
285             outerloop=${i#*=}
286             ;;
287         --netcoreDir=*)
288             netcoreDir=${i#*=}
289             ;;
290         --copy-netcore-to-coreroot)
291             doCopyNetcoreToCoreroot=1
292             ;;
293         --testDir=*)
294             testDirectories[${#testDirectories[@]}]=${i#*=}
295             ;;
296         --testDirFile=*)
297             set_test_directories "${i#*=}"
298             ;;
299         --num-procs=*)
300             ((maxProcesses = ${i#*=}))
301             ;;
302         --outputDir=*)
303             outputDir=${i#*=}
304             ;;
305         --tmpDir=*)
306             tmpDir=${i#*=}
307             ;;
308         --user=*)
309             user=${i#*=}
310             ;;
311         --pal-debug)
312             export PAL_OUTPUTDEBUGSTRING="1"
313             ;;
314         *)
315             echo "Unknown switch: $i"
316             print_usage
317             exit $EXIT_CODE_SUCCESS
318             ;;
319     esac
320 done
321
322 if [ -z "$testRootDir" ]; then
323     echo "--testRootDir is required."
324     print_usage
325     exit $EXIT_CODE_EXCEPTION
326 fi
327 if [ ! -d "$testRootDir" ]; then
328     echo "Directory specified by --testRootDir does not exist: $testRootDir"
329     exit $EXIT_CODE_EXCEPTION
330 fi
331
332 if [ -z "$coreOverlayDir" ]; then
333     echo "--coreOverlayDir is required."
334     print_usage
335     exit $EXIT_CODE_EXCEPTION
336 fi
337 if [ ! -d "$coreOverlayDir" ]; then
338     echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
339     exit $EXIT_CODE_EXCEPTION
340 fi
341
342 if [ -z "$outerloop" ]; then
343     echo "--outerloop is required."
344     print_usage
345     exit $EXIT_CODE_EXCEPTION
346 fi
347
348 export CORE_ROOT="$coreOverlayDir"
349 export USER="$user"
350 export SUDO_USER="$user"
351
352 echo "! Make sure CLR/FX are copied to $coreOverlayDir !"
353
354 if [ "$LANG" == "" ]
355 then
356     export LANG="en_US.UTF-8"
357 fi
358
359 if [ $doCopyNetcoreToCoreroot == 1 ]; then
360     echo "Copying netcore ($netcoreDir) to coreroot ($coreOverlayDir)"
361     cp $netcoreDir/* $coreOverlayDir
362 fi
363
364 echo "Cleanup old ni.dll"
365 for file in `find $testRootDir $coreOverlayDir -name "*.ni.*"`; do
366     rm $file
367 done
368
369 testsOutputDir="$outputDir/tests"
370 mkdir -p $testsOutputDir
371 mkdir -p $tmpDir
372
373 time_start=$(date +"%s")
374 if [ -z "$testDirectories" ]
375 then
376     # No test directories were specified, so run everything
377     testDirectories=( $(ls "$testRootDir/" | grep .Tests) )
378 fi
379
380 for testDir in "${testDirectories[@]}"
381 do
382     run_tests "$testRootDir/$testDir"
383 done
384
385 finish_remaining_tests
386 print_results
387
388 time_end=$(date +"%s")
389 time_diff=$(($time_end-$time_start))
390 echo "$(($time_diff / 60)) minutes and $(($time_diff % 60)) seconds taken to run CoreFX tests."
391
392 if [ "$countErroredDlls" -gt 0 ] || [ "$countErroredTests" -gt 0 ] || [ "$countFailedTests" -gt 0 ]
393 then
394     exit $EXIT_CODE_TEST_FAILURE
395 fi
396
397 exit $EXIT_CODE_SUCCESS