5 echo 'CoreCLR test runner script.'
6 echo 'Script uses next files if they exist:'
7 echo ' unsupportedTests.txt'
8 echo ' unsupportedCrossgenLibs.txt'
9 echo ' unsupportedCrossgenTests.txt'
11 echo 'Typical Tizen command:'
12 echo ' coreclr/tests/runtest.sh'
14 echo ' --testRootDir="/opt/usr/coreclr-tc"'
15 echo ' --coreOverlayDir="/opt/usr/coreclr-tc/coreroot"'
16 echo ' --netcoreDir="/usr/share/dotnet.tizen/netcoreapp"'
17 echo ' --copy-netcore-to-coreroot'
18 echo ' --xunitOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.xml"'
19 echo ' --testsPassOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.pass.txt"'
20 echo ' --testsSkipOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.skip.txt"'
21 echo ' --testsFailOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.fail.txt"'
22 echo ' --libsCrossgenPassOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.pass.txt"'
23 echo ' --libsCrossgenSkipOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.skip.txt"'
24 echo ' --libsCrossgenFailOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.fail.txt"'
25 echo ' --crossgen2options="--jitpath /opt/usr/coreclr-tc/coreroot/libclrjit.so --targetarch armel --parallelism 4 -O"'
27 echo 'Required arguments:'
28 echo ' --arch=<arch> : Target arch (for TW targets "armel" should be passed instead of "arm64", for TM use "armel"; allowed values: "arm", "armel", "arm64", "x64", "x86", "riscv64").'
29 echo ' --testRootDir=<path> : Root directory of the test build (default: /opt/usr/coreclr-tc).'
30 echo ' --coreOverlayDir=<path> : Directory containing CLR and FX (default: /opt/usr/coreclr-tc/coreroot).'
32 echo 'Optional arguments:'
33 echo ' --netcoreDir=<path> : Netcore (CLR and FX) system dir (default: /usr/share/dotnet.tizen/netcoreapp).'
34 echo ' --copy-netcore-to-coreroot : Copy netcore (CLR and FX) from netcore system dir to coreroot.'
35 echo ' --testDir=<path> : Run tests only in the specified directory. The path is relative to the directory'
36 echo ' specified by --testRootDir. Multiple of this switch may be specified.'
37 echo ' --testDirFile=<path> : Run tests only in the directories specified by the file at <path>. Paths are listed'
38 echo ' one line, relative to the directory specified by --testRootDir.'
39 echo ' --num-procs=<N> : Run N test processes at the same time (default is 1).'
40 echo ' -v, --verbose : Show output from each test.'
41 echo ' -h, --help : Show usage information.'
42 echo ' --xunitOutputPath=<path> : Create xUnit XML report at the specifed path (default: <test root dir>/coreclrtests.xml)'
43 echo ' --testsPassOutputPath=<path> : Create pass report at the specifed path (default: <test root dir>/coreclrtests.pass.txt)'
44 echo ' --testsSkipOutputPath=<path> : Create skip report at the specifed path (default: <test root dir>/coreclrtests.skip.txt)'
45 echo ' --testsFailOutputPath=<path> : Create fail report at the specifed path (default: <test root dir>/coreclrtests.fail.txt)'
46 echo ' --test-env : Script to set environment variables for tests.'
48 echo 'Optional arguments with "export COMPlus_..." meaning:'
49 echo ' --jitstress=<n> : Runs the tests with COMPlus_JitStress=n'
50 echo ' --jitstressregs=<n> : Runs the tests with COMPlus_JitStressRegs=n'
51 echo ' --gcstresslevel=<n> : Runs the tests with COMPlus_GCStress=n'
54 echo ' --mcj : Runs the tests with COMPlus_MultiCoreJitProfile=<some_tmp_path> COMPlus_MultiCoreJitMinNumCpus=1 (each test is launched 2 times: first launch to gather profile, second launch to use profile)'
55 echo ' --mcj-no-profile-gather : Runs the tests with COMPlus_MultiCoreJitNoProfileGather=1 on the second mcj launch'
58 echo ' --crossgen-libs : Precompiles system libs.'
59 echo ' --crossgen-tests : Precompiles tests.'
60 echo ' --crossgenoptions : Options passed to crossgen.'
61 echo ' --allow-crossgen-fails : Allow crossgen to ignore compilation fails.'
62 echo ' --crossgen-lib=<path> : Precompile only specified lib. The path is absolute.'
63 echo ' --libsCrossgenPassOutputPath=<path> : Create crossgen pass report at the specifed path (default: <test root dir>/crossgenlibs.pass.txt)'
64 echo ' --libsCrossgenSkipOutputPath=<path> : Create crossgen skip report at the specifed path (default: <test root dir>/crossgenlibs.skip.txt)'
65 echo ' --libsCrossgenFailOutputPath=<path> : Create crossgen fail report at the specifed path (default: <test root dir>/crossgenlibs.fail.txt)'
68 echo ' --crossgen2options : Options passed to crossgen2 (default: --jitpath /opt/usr/coreclr-tc/coreroot/libclrjit.so --targetarch armel)'
69 echo ' --crossgen2-libs : Use crossgen2 for compilation of system libs.'
70 echo ' --crossgen2-tests : Use crossgen2 for compilation of tests.'
71 echo ' --crossgen-spc-first : Crossgen System.Private.CoreLib.dll before other dlls.'
74 function print_results {
76 echo "======================="
78 echo "======================="
79 echo "# Overlay : $coreOverlayDir"
80 echo "# Tests Discovered : $countTotalTests"
81 echo "# Passed : $countPassedTests"
82 echo "# Failed : $countFailedTests"
83 echo "# Skipped : $countSkippedTests"
84 echo "======================="
87 # Initialize counters for bookkeeping.
93 # Variables for xUnit-style XML output. XML format: https://xunit.github.io/docs/format-xml-v2.html
97 # Variables for text file output. These can be passed back to runtest.sh using the "--playlist" argument
98 # to rerun specific tests.
102 libsCrossgenPassOutputPath=
103 libsCrossgenFailOutputPath=
104 libsCrossgenSkipOutputPath=
106 function xunit_output_begin {
107 if [ -z "$xunitOutputPath" ]; then
108 xunitOutputPath=$testRootDir/coreclrtests.xml
110 xunitTestOutputPath=${xunitOutputPath}.test
111 if [ -f "$xunitOutputPath" ]; then
112 rm -f -r "$xunitOutputPath"
114 if [ -f "$xunitTestOutputPath" ]; then
115 rm -f -r "$xunitTestOutputPath"
119 function xunit_output_add_test {
123 # <test .../> <!-- Write this element here -->
125 local scriptFilePath=$1
126 local outputFilePath=$2
127 local testResult=$3 # Pass, Fail, or Skip
128 local testScriptExitCode=$4
129 local testRunningTime=$5
131 local testPath=${scriptFilePath%.sh} # Remove trailing ".sh"
132 local testDir=$(dirname "$testPath")
133 local testName=$(basename "$testPath")
135 # Replace '/' with '.'
136 testPath=$(echo "$testPath" | tr / .)
137 testDir=$(echo "$testDir" | tr / .)
143 line="${line} name=\"${testPath}\""
144 line="${line} type=\"${testDir}\""
145 line="${line} method=\"${testName}\""
146 line="${line} result=\"${testResult}\""
147 if [ -n "$testRunningTime" ] && [ "$testResult" != "Skip" ]; then
148 line="${line} time=\"${testRunningTime}\""
151 if [ "$testResult" == "Pass" ]; then
153 echo "$line" >>"$xunitTestOutputPath"
158 echo "$line" >>"$xunitTestOutputPath"
161 if [ "$testResult" == "Skip" ]; then
162 line="${line}<reason><![CDATA[$(cat "$outputFilePath")]]></reason>"
163 echo "$line" >>"$xunitTestOutputPath"
165 line="${line}<failure exception-type=\"Exit code: ${testScriptExitCode}\">"
166 echo "$line" >>"$xunitTestOutputPath"
169 line="${line}<message>"
170 echo "$line" >>"$xunitTestOutputPath"
172 line="${line}<![CDATA["
173 echo "$line" >>"$xunitTestOutputPath"
174 cat "$outputFilePath" >>"$xunitTestOutputPath"
177 echo "$line" >>"$xunitTestOutputPath"
179 line="${line}</message>"
180 echo "$line" >>"$xunitTestOutputPath"
183 line="${line}</failure>"
184 echo "$line" >>"$xunitTestOutputPath"
188 line="${line}</test>"
189 echo "$line" >>"$xunitTestOutputPath"
192 function xunit_output_end {
194 local errorMessage=$2
197 if [ -z "$errorSource" ]; then
203 echo '<?xml version="1.0" encoding="utf-8"?>' >>"$xunitOutputPath"
204 echo '<assemblies>' >>"$xunitOutputPath"
210 line="${line}<assembly"
211 line="${line} name=\"CoreClrTestAssembly\""
212 line="${line} total=\"${countTotalTests}\""
213 line="${line} passed=\"${countPassedTests}\""
214 line="${line} failed=\"${countFailedTests}\""
215 line="${line} skipped=\"${countSkippedTests}\""
216 line="${line} errors=\"${errorCount}\""
218 echo "$line" >>"$xunitOutputPath"
222 line="${line}<collection"
223 line="${line} name=\"CoreClrTestCollection\""
224 line="${line} total=\"${countTotalTests}\""
225 line="${line} passed=\"${countPassedTests}\""
226 line="${line} failed=\"${countFailedTests}\""
227 line="${line} skipped=\"${countSkippedTests}\""
229 echo "$line" >>"$xunitOutputPath"
231 # <test .../> <test .../> ...
232 if [ -f "$xunitTestOutputPath" ]; then
233 cat "$xunitTestOutputPath" >>"$xunitOutputPath"
234 rm -f "$xunitTestOutputPath"
239 line="${line}</collection>"
240 echo "$line" >>"$xunitOutputPath"
242 if [ -n "$errorSource" ]; then
245 line="${line}<errors>"
246 echo "$line" >>"$xunitOutputPath"
251 line="${line} type=\"TestHarnessError\""
252 line="${line} name=\"${errorSource}\""
254 echo "$line" >>"$xunitOutputPath"
258 line="${line}<failure>${errorMessage}</failure>"
259 echo "$line" >>"$xunitOutputPath"
263 line="${line}</error>"
264 echo "$line" >>"$xunitOutputPath"
268 line="${line}</errors>"
269 echo "$line" >>"$xunitOutputPath"
274 line="${line}</assembly>"
275 echo "$line" >>"$xunitOutputPath"
278 echo '</assemblies>' >>"$xunitOutputPath"
281 function text_file_output_begin {
282 if [ -z "$testsPassOutputPath" ]; then
283 testsPassOutputPath=$testRootDir/coreclrtests.pass.txt
285 if [ -f "$testsPassOutputPath" ]; then
286 rm -f "$testsPassOutputPath"
288 if [ -z "$testsFailOutputPath" ]; then
289 testsFailOutputPath=$testRootDir/coreclrtests.fail.txt
291 if [ -f "$testsFailOutputPath" ]; then
292 rm -f "$testsFailOutputPath"
294 if [ -z "$testsSkipOutputPath" ]; then
295 testsSkipOutputPath=$testRootDir/coreclrtests.skip.txt
297 if [ -f "$testsSkipOutputPath" ]; then
298 rm -f "$testsSkipOutputPath"
301 if [ -z "$libsCrossgenPassOutputPath" ]; then
302 libsCrossgenPassOutputPath=$testRootDir/crossgenlibs.pass.txt
304 if [ -f "$libsCrossgenPassOutputPath" ]; then
305 rm -f "$libsCrossgenPassOutputPath"
307 if [ -z "$libsCrossgenFailOutputPath" ]; then
308 libsCrossgenFailOutputPath=$testRootDir/crossgenlibs.fail.txt
310 if [ -f "$libsCrossgenFailOutputPath" ]; then
311 rm -f "$libsCrossgenFailOutputPath"
313 if [ -z "$libsCrossgenSkipOutputPath" ]; then
314 libsCrossgenSkipOutputPath=$testRootDir/crossgenlibs.skip.txt
316 if [ -f "$libsCrossgenSkipOutputPath" ]; then
317 rm -f "$libsCrossgenSkipOutputPath"
321 function text_file_output_add_test {
322 local scriptFilePath=$1
323 local testResult=$2 # Pass, Fail, or Skip
325 if [ "$testResult" == "Pass" ]; then
326 echo "$scriptFilePath" >>"$testsPassOutputPath"
327 elif [ "$testResult" == "Skip" ]; then
328 echo "$scriptFilePath" >>"$testsSkipOutputPath"
330 echo "$scriptFilePath" >>"$testsFailOutputPath"
334 function exit_with_error {
336 local errorMessage=$2
339 if [ -z "$printUsage" ]; then
344 xunit_output_end "$errorSource" "$errorMessage"
345 if ((printUsage != 0)); then
348 exit $EXIT_CODE_EXCEPTION
351 # Handle Ctrl-C. We will stop execution and print the results that
352 # we gathered so far.
353 function handle_ctrl_c {
354 local errorSource='handle_ctrl_c'
357 echo "*** Stopping... ***"
359 exit_with_error "$errorSource" "Test run aborted by Ctrl+C."
362 # Register the Ctrl-C handler
363 trap handle_ctrl_c INT
365 # Variables for unsupported and failing tests
366 declare -a unsupportedCrossGenLibs
367 declare -a unsupportedCrossGenTests
368 declare -a unsupportedTests
370 # Get an array of items by reading the specified file line by line.
371 function read_array {
374 if [ ! -f "$1" ]; then
378 # bash in Mac OS X doesn't support 'readarray', so using alternate way instead.
379 # readarray -t theArray < "$1"
380 # Any line that starts with '#' is ignored.
381 while IFS='' read -r line || [ -n "$line" ]; do
382 if [[ $line != "#"* ]]; then
383 theArray[${#theArray[@]}]=$line
389 function load_unsupported_tests {
390 # Load the list of tests that are not supported on this platform
391 unsupportedTests=($(read_array "$(dirname "$0")/unsupportedTests.txt"))
392 # Load the list of libs that are not supported for crossgen on this platform
393 unsupportedCrossGenLibs=($(read_array "$(dirname "$0")/unsupportedCrossgenLibs.txt"))
394 # Load the list of test that are not supported for crossgen on this platform
395 unsupportedCrossGenTests=($(read_array "$(dirname "$0")/unsupportedCrossgenTests.txt"))
398 function is_unsupported_crossgen_lib {
399 for unsupported in "${unsupportedCrossGenLibs[@]}"; do
400 if [ "$1" == "$unsupported" ]; then
407 function is_unsupported_test {
408 for unsupported in "${unsupportedTests[@]}"; do
409 if [ "$1" == "$unsupported" ]; then
414 if [ $doCrossgenTests == 1 ] || [ $doCrossgen2Tests == 1 ]; then
415 for unsupported in "${unsupportedCrossGenTests[@]}"; do
416 if [ "$1" == "$unsupported" ]; then
425 function crossgen_file {
430 # ni.dll are created as ni.dll.tmp in order to not interfere
431 # with crossgen2 at first, then moved to ni.dll all at once at the end
432 # (logic is similar to https://github.com/dotnet/runtime/pull/57341/)
433 local tmp_ni_path=$(echo $dll_path | sed 's/.dll$/.ni.dll.tmp/')
435 echo "Precompiling $dll_path to $tmp_ni_path"
437 if [ $doCrossgenLibs == 1 ]; then
438 ${overlayDir}/crossgen /in $dll_path /out $tmp_ni_path $CrossGenOptions /p ${overlayDir}:${overlayDir}/crossgen2 &>$dll_path.out
439 elif [ $doCrossgen2Libs == 1 ]; then
440 ${overlayDir}/corerun ${overlayDir}/crossgen2/crossgen2.dll $CrossGen2Options -o:$tmp_ni_path $dll_path -r:${overlayDir}/*.dll -r:${overlayDir}/crossgen2/*.dll &>$dll_path.out
444 if [[ $exitCode != 0 ]]; then
445 echo Crossgen fail for $dll_path.
446 echo "$dll_path" >> "$libsCrossgenFailOutputPath"
450 if [ $CrossGenAllowFail == 0 ]; then
454 echo Crossgen success $dll_path.
455 echo "$dll_path" >> "$libsCrossgenPassOutputPath"
457 if [[ "${name}" == "System.Private.CoreLib.dll" ]]; then
458 # SPC.ni.dll can be used directly without ni.dll.tmp
459 # (because SPC doesn't use any dependencies)
460 mv $dll_path $dll_path.bak
461 mv $tmp_ni_path $dll_path
468 function precompile_overlay_assemblies {
469 local overlayDir=$CORE_ROOT
471 if [ $doCopyNetcoreToCoreroot == 1 ]; then
472 echo "Copying netcore ($netcoreDir) to coreroot ($overlayDir)"
473 cp -r $netcoreDir/* $overlayDir
476 echo Cleanup old ni.dll
477 for file in `find $testRootDir -name "*.ni.*"`; do
481 test -f $overlayDir/System.Private.CoreLib.dll.Backup && mv $overlayDir/System.Private.CoreLib.dll.Backup $overlayDir/System.Private.CoreLib.dll
482 test -f $overlayDir/System.Private.CoreLib.dll.bak && mv $overlayDir/System.Private.CoreLib.dll.bak $overlayDir/System.Private.CoreLib.dll
484 if [ $doCrossgenLibs == 0 ] && [ $doCrossgen2Libs == 0 ]; then
485 echo Skipping crossgen of libs.
488 echo Precompiling libs
491 if [ $doCrossgenSPCFirst == 1 ]; then
492 local dll_path=$overlayDir/System.Private.CoreLib.dll
493 local name=$(basename $dll_path)
494 crossgen_file $overlayDir $dll_path $name
497 if [ -z "$crossgenLibs" ]; then
498 # No libs to crossgen were specified, so crossgen everything in the overlay
499 filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -type f)
501 # Otherwise, compile only specified libs
502 filesToPrecompile=$(echo "${crossgenLibs[@]}")
505 for fileToPrecompile in ${filesToPrecompile}
507 local dll_path=${fileToPrecompile}
508 local name=$(basename $dll_path)
510 if [[ "$name" == "System.Private.CoreLib.dll" && "$doCrossgenSPCFirst" == "1" ]]; then
514 if is_unsupported_crossgen_lib "${name}"; then
515 echo Skipping crossgen for $dll_path.
516 echo "$dll_path" >> "$libsCrossgenSkipOutputPath"
520 crossgen_file $overlayDir $dll_path $name
523 # Copy ni.dll all at once
524 for tmp_ni_path in `find $overlayDir -name "*.ni.dll.tmp"`; do
525 local ni_dll_path=$(echo $tmp_ni_path | sed 's/.ni.dll.tmp$/.ni.dll/')
527 echo "Moving $tmp_ni_path to $ni_dll_path"
528 mv $tmp_ni_path $ni_dll_path
532 function skip_unsupported_test {
533 # This function runs in a background process. It should not echo anything, and should not use global variables. This
534 # function is analogous to run_test, and causes the test to be skipped with the message below.
536 local scriptFilePath=$1
537 local outputFilePath=$2
539 echo "Not supported on this platform or in this mode." >"$outputFilePath"
540 return 2 # skip the test
544 # This function runs in a background process. It should not echo anything, and should not use global variables.
546 local scriptFilePath=$1
547 local outputFilePath=$2
549 # Switch to directory where the script is
550 cd "$(dirname "$scriptFilePath")"
552 local scriptFileName=$(basename "$scriptFilePath")
553 local outputFileName=$(basename "$outputFilePath")
555 echo "" > "$outputFileName" 2>&1
557 if [ $useMulticoreJit == 1 ]; then
558 export COMPlus_MultiCoreJitProfile="`pwd`/mcj_profile.dat"
559 export COMPlus_MultiCoreJitMinNumCpus="1"
560 echo "MULTICOREJIT: 1st launch" >> "$outputFileName" 2>&1
562 "./$scriptFileName" >> "$outputFileName" 2>&1
563 local testScriptExitCode=$?
565 if [ $testScriptExitCode == 0 ]; then
566 if [ $useMulticoreJitNoProfileGather == 1 ]; then
567 export COMPlus_MultiCoreJitNoProfileGather="1"
570 echo "" >> "$outputFileName" 2>&1
571 echo "MULTICOREJIT: 2nd launch" >> "$outputFileName" 2>&1
573 return $testScriptExitCode
577 if [ $doCrossgenTests == 1 ]; then
581 if [ $doCrossgen2Tests == 1 ]; then
582 export RunCrossGen2=1
585 "./$scriptFileName" >> "$outputFileName" 2>&1
586 local testScriptExitCode=$?
588 return $testScriptExitCode
591 # Variables for running tests in the background
592 ((maxProcesses = 1)) # long tests delay process creation, use a few more processors
595 declare -a scriptFilePaths
596 declare -a outputFilePaths
597 declare -a processIds
598 declare -a testStartTimes
606 for (( i=0; i<$maxProcesses; i++ )); do
607 pid=${processIds[$i]}
608 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
611 if ! kill -0 $pid 2>/dev/null; then
615 processIds[$i]=$pidNone
623 function get_available_process_index {
626 for (( i=0; i<$maxProcesses; i++ )); do
627 pid=${processIds[$i]}
628 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
635 function finish_test {
637 local testScriptExitCode=$?
638 local finishedProcessIndex=$waitProcessIndex
641 local scriptFilePath=${scriptFilePaths[$finishedProcessIndex]}
642 local outputFilePath=${outputFilePaths[$finishedProcessIndex]}
643 local scriptFileName=$(basename "$scriptFilePath")
646 local testRunningTime=
649 if ((verbose == 1)); then
650 header=$(printf "[%4d]" $countTotalTests)
653 testEndTime=$(date +%s)
654 testRunningTime=$(( $testEndTime - ${testStartTimes[$finishedProcessIndex]} ))
655 header=$header$(printf "[%4ds]" $testRunningTime)
657 if [ $useMulticoreJit == 1 ]; then
658 header="$header[mcj]"
662 case $testScriptExitCode in
664 let countPassedTests++
666 if ((verbose == 1)); then
667 echo "PASSED - ${header}${scriptFilePath}"
669 echo " - ${header}${scriptFilePath}"
673 let countSkippedTests++
675 echo "SKIPPED - ${header}${scriptFilePath}"
678 let countFailedTests++
680 echo "FAILED - ${header}${scriptFilePath}"
683 let countTotalTests++
685 if ((verbose == 1 || testScriptExitCode != 0)); then
686 while IFS='' read -r line || [ -n "$line" ]; do
688 done <"$outputFilePath"
691 xunit_output_add_test "$scriptFilePath" "$outputFilePath" "$testResult" "$testScriptExitCode" "$testRunningTime"
692 text_file_output_add_test "$scriptFilePath" "$testResult"
695 function finish_remaining_tests {
696 # Finish the remaining tests in the order in which they were started
697 while ((processCount > 0)); do
703 local scriptFilePath=$1
704 local scriptFileDir=$(dirname "$scriptFilePath")
706 test "$verbose" == 1 && echo "Preparing $scriptFilePath"
708 # Add executable file mode bit if needed
709 chmod +x "$scriptFilePath"
712 rm -rf $scriptFileDir/lock
714 # remove mcj profiles
715 rm -rf $scriptFileDir/mcj_profile.dat*
718 function start_test {
719 local nextProcessIndex=$(get_available_process_index)
720 local scriptFilePath=$1
722 if ((nextProcessIndex == maxProcesses)); then
724 nextProcessIndex=$(get_available_process_index)
727 scriptFilePaths[$nextProcessIndex]=$scriptFilePath
728 local scriptFileName=$(basename "$scriptFilePath")
729 local outputFilePath=$(dirname "$scriptFilePath")/${scriptFileName}.out
730 outputFilePaths[$nextProcessIndex]=$outputFilePath
732 testStartTimes[$nextProcessIndex]=$(date +%s)
734 test "$verbose" == 1 && echo "Starting $scriptFilePath"
735 if is_unsupported_test "$scriptFilePath"; then
736 skip_unsupported_test "$scriptFilePath" "$outputFilePath" &
738 run_test "$scriptFilePath" "$outputFilePath" &
740 processIds[$nextProcessIndex]=$!
745 # Get a list of directories in which to scan for tests by reading the
746 # specified file line by line.
747 function set_test_directories {
748 local errorSource='set_test_directories'
750 local listFileName=$1
752 if [ ! -f "$listFileName" ]
754 exit_with_error "$errorSource" "Test directories file not found at $listFileName"
756 testDirectories=($(read_array "$listFileName"))
759 function run_tests_in_directory {
761 local skipScriptsInDir=$2
765 # Need to skip scripts in testDir since they are not tests
766 if [[ "$skipScriptsInDir" == "1" ]]; then
770 # Recursively search through directories for .sh files to prepare them.
771 # Note: This needs to occur before any test runs as some of the .sh files
772 # depend on other .sh files
773 echo "Preparing tests..."
774 for scriptFilePath in $(find "$testDir" -mindepth ${minDepth} -type f -iname '*.sh' | sort)
776 prep_test "${scriptFilePath:2}"
778 echo "The tests have been prepared"
779 # Recursively search through directories for .sh files to run.
780 for scriptFilePath in $(find "$testDir" -mindepth ${minDepth} -type f -iname '*.sh' | sort)
782 start_test "${scriptFilePath:2}"
786 # Exit code constants
787 readonly EXIT_CODE_SUCCESS=0 # Script ran normally.
788 readonly EXIT_CODE_EXCEPTION=1 # Script exited because something exceptional happened (e.g. bad arguments, Ctrl-C interrupt).
789 readonly EXIT_CODE_TEST_FAILURE=2 # Script completed successfully, but one or more tests failed.
792 testRootDir="/opt/usr/coreclr-tc/"
793 coreOverlayDir="/opt/usr/coreclr-tc/coreroot/"
794 doCopyNetcoreToCoreroot=0
795 netcoreDir="/usr/share/dotnet.tizen/netcoreapp"
808 useMulticoreJitNoProfileGather=0
818 exit $EXIT_CODE_SUCCESS
838 --crossgen-spc-first)
842 crossgenOpts="$crossgenOpts ${i#*=}"
844 --crossgen2options=*)
845 crossgen2Opts="$crossgen2Opts ${i#*=}"
847 --allow-crossgen-fails)
851 crossgenLibs[${#crossgenLibs[@]}]=${i#*=}
854 export COMPlus_JitStress=${i#*=}
857 export COMPlus_JitStressRegs=${i#*=}
862 --mcj-no-profile-gather)
863 useMulticoreJitNoProfileGather=1
869 coreOverlayDir=${i#*=}
874 --copy-netcore-to-coreroot)
875 doCopyNetcoreToCoreroot=1
878 testDirectories[${#testDirectories[@]}]=${i#*=}
881 set_test_directories "${i#*=}"
884 ((maxProcesses = ${i#*=}))
890 export COMPlus_GCStress=${i#*=}
893 xunitOutputPath=${i#*=}
895 --testsPassOutputPath=*)
896 testsPassOutputPath=${i#*=}
898 --testsSkipOutputPath=*)
899 testsSkipOutputPath=${i#*=}
901 --testsFailOutputPath=*)
902 testsFailOutputPath=${i#*=}
904 --libsCrossgenPassOutputPath=*)
905 libsCrossgenPassOutputPath=${i#*=}
907 --libsCrossgenSkipOutputPath=*)
908 libsCrossgenSkipOutputPath=${i#*=}
910 --libsCrossgenFailOutputPath=*)
911 libsCrossgenFailOutputPath=${i#*=}
914 echo "Unknown switch: $i"
916 exit $EXIT_CODE_SUCCESS
921 if [ -z "$ARCH" ]; then
922 echo "--arch is required."
924 exit $EXIT_CODE_EXCEPTION
926 if [ "$ARCH" != "arm" ] && [ "$ARCH" != "armel" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "riscv64" ]; then
927 echo "Unsupported value for --arch: $ARCH"
929 exit $EXIT_CODE_EXCEPTION
932 if [ -z "$testRootDir" ]; then
933 echo "--testRootDir is required."
935 exit $EXIT_CODE_EXCEPTION
937 if [ ! -d "$testRootDir" ]; then
938 echo "Directory specified by --testRootDir does not exist: $testRootDir"
939 exit $EXIT_CODE_EXCEPTION
942 if [ -z "$coreOverlayDir" ]; then
943 echo "--coreOverlayDir is required."
945 exit $EXIT_CODE_EXCEPTION
947 if [ ! -d "$coreOverlayDir" ]; then
948 echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
949 exit $EXIT_CODE_EXCEPTION
952 export CORE_ROOT="$coreOverlayDir"
954 # Default values for crossgen2 options
955 if [ "$crossgen2Opts" == "" ]; then
956 crossgen2Opts="--jitpath $coreOverlayDir/libclrjit.so --targetarch $ARCH"
959 export CrossGenOptions="$crossgenOpts"
960 export CrossGen2Options="$crossgen2Opts"
961 export CrossGen2OptionsR2RTest="--crossgen2-jitpath $coreOverlayDir/libclrjit.so --target-arch $ARCH"
963 echo "! Make sure CLR/FX are copied to $coreOverlayDir !"
965 echo "Running on CPU-$ARCH"
968 text_file_output_begin
969 load_unsupported_tests
970 precompile_overlay_assemblies
972 export __TestEnv=$testEnv
975 time_start=$(date +"%s")
976 if [ -z "$testDirectories" ]
978 # No test directories were specified, so run everything in the current
979 # directory and its subdirectories.
980 run_tests_in_directory "." 1
982 # Otherwise, run all the tests in each specified test directory.
983 for testDir in "${testDirectories[@]}"
985 if [ ! -d "$testDir" ]; then
986 echo "Test directory does not exist: $testDir"
988 run_tests_in_directory "./$testDir" 0
993 finish_remaining_tests
996 time_end=$(date +"%s")
997 time_diff=$(($time_end-$time_start))
998 echo "$(($time_diff / 60)) minutes and $(($time_diff % 60)) seconds taken to run CoreCLR tests."
1002 if ((countFailedTests > 0)); then
1003 exit $EXIT_CODE_TEST_FAILURE
1006 exit $EXIT_CODE_SUCCESS