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'
10 echo ' unsupportedGCStressTests.txt'
12 echo 'Typical Tizen command:'
13 echo ' coreclr/tests/runtest.sh'
15 echo ' --testRootDir="/opt/usr/coreclr-tc"'
16 echo ' --coreOverlayDir="/opt/usr/coreclr-tc/coreroot"'
17 echo ' --netcoreDir="/usr/share/dotnet.tizen/netcoreapp"'
18 echo ' --copy-netcore-to-coreroot'
19 echo ' --xunitOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.xml"'
20 echo ' --testsPassOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.pass.txt"'
21 echo ' --testsSkipOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.skip.txt"'
22 echo ' --testsFailOutputPath="/opt/usr/coreclr-tc/results/coreclrtests.fail.txt"'
23 echo ' --libsCrossgenPassOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.pass.txt"'
24 echo ' --libsCrossgenSkipOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.skip.txt"'
25 echo ' --libsCrossgenFailOutputPath="/opt/usr/coreclr-tc/results/crossgenlibs.fail.txt"'
26 echo ' --crossgen2options="--jitpath /opt/usr/coreclr-tc/coreroot/libclrjit.so --targetarch armel --parallelism 4 -O"'
28 echo 'Required arguments:'
29 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").'
30 echo ' --testRootDir=<path> : Root directory of the test build (default: /opt/usr/coreclr-tc).'
31 echo ' --coreOverlayDir=<path> : Directory containing CLR and FX (default: /opt/usr/coreclr-tc/coreroot).'
33 echo 'Optional arguments:'
34 echo ' --netcoreDir=<path> : Netcore (CLR and FX) system dir (default: /usr/share/dotnet.tizen/netcoreapp).'
35 echo ' --copy-netcore-to-coreroot : Copy netcore (CLR and FX) from netcore system dir to coreroot.'
36 echo ' --testDir=<path> : Run tests only in the specified directory. The path is relative to the directory'
37 echo ' specified by --testRootDir. Multiple of this switch may be specified.'
38 echo ' --testDirFile=<path> : Run tests only in the directories specified by the file at <path>. Paths are listed'
39 echo ' one line, relative to the directory specified by --testRootDir.'
40 echo ' --num-procs=<N> : Run N test processes at the same time (default is 1).'
41 echo ' -v, --verbose : Show output from each test.'
42 echo ' -h, --help : Show usage information.'
43 echo ' --xunitOutputPath=<path> : Create xUnit XML report at the specifed path (default: <test root dir>/coreclrtests.xml)'
44 echo ' --testsPassOutputPath=<path> : Create pass report at the specifed path (default: <test root dir>/coreclrtests.pass.txt)'
45 echo ' --testsSkipOutputPath=<path> : Create skip report at the specifed path (default: <test root dir>/coreclrtests.skip.txt)'
46 echo ' --testsFailOutputPath=<path> : Create fail report at the specifed path (default: <test root dir>/coreclrtests.fail.txt)'
47 echo ' --test-env : Script to set environment variables for tests.'
49 echo 'Optional arguments with "export COMPlus_..." meaning:'
50 echo ' --jitstress=<n> : Runs the tests with COMPlus_JitStress=n'
51 echo ' --jitstressregs=<n> : Runs the tests with COMPlus_JitStressRegs=n'
52 echo ' --gcstresslevel=<n> : Runs the tests with COMPlus_GCStress=n'
55 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)'
56 echo ' --mcj-no-profile-gather : Runs the tests with COMPlus_MultiCoreJitNoProfileGather=1 on the second mcj launch'
59 echo ' --crossgen-libs : Precompiles system libs.'
60 echo ' --crossgen-tests : Precompiles tests.'
61 echo ' --crossgenoptions : Options passed to crossgen.'
62 echo ' --allow-crossgen-fails : Allow crossgen to ignore compilation fails.'
63 echo ' --crossgen-lib=<path> : Precompile only specified lib. The path is absolute.'
64 echo ' --libsCrossgenPassOutputPath=<path> : Create crossgen pass report at the specifed path (default: <test root dir>/crossgenlibs.pass.txt)'
65 echo ' --libsCrossgenSkipOutputPath=<path> : Create crossgen skip report at the specifed path (default: <test root dir>/crossgenlibs.skip.txt)'
66 echo ' --libsCrossgenFailOutputPath=<path> : Create crossgen fail report at the specifed path (default: <test root dir>/crossgenlibs.fail.txt)'
69 echo ' --crossgen2options : Options passed to crossgen2 (default: --jitpath /opt/usr/coreclr-tc/coreroot/libclrjit.so --targetarch armel)'
70 echo ' --crossgen2-libs : Use crossgen2 for compilation of system libs.'
71 echo ' --crossgen2-tests : Use crossgen2 for compilation of tests.'
72 echo ' --crossgen-spc-first : Crossgen System.Private.CoreLib.dll before other dlls.'
75 function print_results {
77 echo "======================="
79 echo "======================="
80 echo "# Overlay : $coreOverlayDir"
81 echo "# Tests Discovered : $countTotalTests"
82 echo "# Passed : $countPassedTests"
83 echo "# Failed : $countFailedTests"
84 echo "# Skipped : $countSkippedTests"
85 echo "======================="
88 # Initialize counters for bookkeeping.
94 # Variables for xUnit-style XML output. XML format: https://xunit.github.io/docs/format-xml-v2.html
98 # Variables for text file output. These can be passed back to runtest.sh using the "--playlist" argument
99 # to rerun specific tests.
103 libsCrossgenPassOutputPath=
104 libsCrossgenFailOutputPath=
105 libsCrossgenSkipOutputPath=
107 function xunit_output_begin {
108 if [ -z "$xunitOutputPath" ]; then
109 xunitOutputPath=$testRootDir/coreclrtests.xml
111 xunitTestOutputPath=${xunitOutputPath}.test
112 if [ -f "$xunitOutputPath" ]; then
113 rm -f -r "$xunitOutputPath"
115 if [ -f "$xunitTestOutputPath" ]; then
116 rm -f -r "$xunitTestOutputPath"
120 function xunit_output_add_test {
124 # <test .../> <!-- Write this element here -->
126 local scriptFilePath=$1
127 local outputFilePath=$2
128 local testResult=$3 # Pass, Fail, or Skip
129 local testScriptExitCode=$4
130 local testRunningTime=$5
132 local testPath=${scriptFilePath%.sh} # Remove trailing ".sh"
133 local testDir=$(dirname "$testPath")
134 local testName=$(basename "$testPath")
136 # Replace '/' with '.'
137 testPath=$(echo "$testPath" | tr / .)
138 testDir=$(echo "$testDir" | tr / .)
144 line="${line} name=\"${testPath}\""
145 line="${line} type=\"${testDir}\""
146 line="${line} method=\"${testName}\""
147 line="${line} result=\"${testResult}\""
148 if [ -n "$testRunningTime" ] && [ "$testResult" != "Skip" ]; then
149 line="${line} time=\"${testRunningTime}\""
152 if [ "$testResult" == "Pass" ]; then
154 echo "$line" >>"$xunitTestOutputPath"
159 echo "$line" >>"$xunitTestOutputPath"
162 if [ "$testResult" == "Skip" ]; then
163 line="${line}<reason><![CDATA[$(cat "$outputFilePath")]]></reason>"
164 echo "$line" >>"$xunitTestOutputPath"
166 line="${line}<failure exception-type=\"Exit code: ${testScriptExitCode}\">"
167 echo "$line" >>"$xunitTestOutputPath"
170 line="${line}<message>"
171 echo "$line" >>"$xunitTestOutputPath"
173 line="${line}<![CDATA["
174 echo "$line" >>"$xunitTestOutputPath"
175 cat "$outputFilePath" >>"$xunitTestOutputPath"
178 echo "$line" >>"$xunitTestOutputPath"
180 line="${line}</message>"
181 echo "$line" >>"$xunitTestOutputPath"
184 line="${line}</failure>"
185 echo "$line" >>"$xunitTestOutputPath"
189 line="${line}</test>"
190 echo "$line" >>"$xunitTestOutputPath"
193 function xunit_output_end {
195 local errorMessage=$2
198 if [ -z "$errorSource" ]; then
204 echo '<?xml version="1.0" encoding="utf-8"?>' >>"$xunitOutputPath"
205 echo '<assemblies>' >>"$xunitOutputPath"
211 line="${line}<assembly"
212 line="${line} name=\"CoreClrTestAssembly\""
213 line="${line} total=\"${countTotalTests}\""
214 line="${line} passed=\"${countPassedTests}\""
215 line="${line} failed=\"${countFailedTests}\""
216 line="${line} skipped=\"${countSkippedTests}\""
217 line="${line} errors=\"${errorCount}\""
219 echo "$line" >>"$xunitOutputPath"
223 line="${line}<collection"
224 line="${line} name=\"CoreClrTestCollection\""
225 line="${line} total=\"${countTotalTests}\""
226 line="${line} passed=\"${countPassedTests}\""
227 line="${line} failed=\"${countFailedTests}\""
228 line="${line} skipped=\"${countSkippedTests}\""
230 echo "$line" >>"$xunitOutputPath"
232 # <test .../> <test .../> ...
233 if [ -f "$xunitTestOutputPath" ]; then
234 cat "$xunitTestOutputPath" >>"$xunitOutputPath"
235 rm -f "$xunitTestOutputPath"
240 line="${line}</collection>"
241 echo "$line" >>"$xunitOutputPath"
243 if [ -n "$errorSource" ]; then
246 line="${line}<errors>"
247 echo "$line" >>"$xunitOutputPath"
252 line="${line} type=\"TestHarnessError\""
253 line="${line} name=\"${errorSource}\""
255 echo "$line" >>"$xunitOutputPath"
259 line="${line}<failure>${errorMessage}</failure>"
260 echo "$line" >>"$xunitOutputPath"
264 line="${line}</error>"
265 echo "$line" >>"$xunitOutputPath"
269 line="${line}</errors>"
270 echo "$line" >>"$xunitOutputPath"
275 line="${line}</assembly>"
276 echo "$line" >>"$xunitOutputPath"
279 echo '</assemblies>' >>"$xunitOutputPath"
282 function text_file_output_begin {
283 if [ -z "$testsPassOutputPath" ]; then
284 testsPassOutputPath=$testRootDir/coreclrtests.pass.txt
286 if [ -f "$testsPassOutputPath" ]; then
287 rm -f "$testsPassOutputPath"
289 if [ -z "$testsFailOutputPath" ]; then
290 testsFailOutputPath=$testRootDir/coreclrtests.fail.txt
292 if [ -f "$testsFailOutputPath" ]; then
293 rm -f "$testsFailOutputPath"
295 if [ -z "$testsSkipOutputPath" ]; then
296 testsSkipOutputPath=$testRootDir/coreclrtests.skip.txt
298 if [ -f "$testsSkipOutputPath" ]; then
299 rm -f "$testsSkipOutputPath"
302 if [ -z "$libsCrossgenPassOutputPath" ]; then
303 libsCrossgenPassOutputPath=$testRootDir/crossgenlibs.pass.txt
305 if [ -f "$libsCrossgenPassOutputPath" ]; then
306 rm -f "$libsCrossgenPassOutputPath"
308 if [ -z "$libsCrossgenFailOutputPath" ]; then
309 libsCrossgenFailOutputPath=$testRootDir/crossgenlibs.fail.txt
311 if [ -f "$libsCrossgenFailOutputPath" ]; then
312 rm -f "$libsCrossgenFailOutputPath"
314 if [ -z "$libsCrossgenSkipOutputPath" ]; then
315 libsCrossgenSkipOutputPath=$testRootDir/crossgenlibs.skip.txt
317 if [ -f "$libsCrossgenSkipOutputPath" ]; then
318 rm -f "$libsCrossgenSkipOutputPath"
322 function text_file_output_add_test {
323 local scriptFilePath=$1
324 local testResult=$2 # Pass, Fail, or Skip
326 if [ "$testResult" == "Pass" ]; then
327 echo "$scriptFilePath" >>"$testsPassOutputPath"
328 elif [ "$testResult" == "Skip" ]; then
329 echo "$scriptFilePath" >>"$testsSkipOutputPath"
331 echo "$scriptFilePath" >>"$testsFailOutputPath"
335 function exit_with_error {
337 local errorMessage=$2
340 if [ -z "$printUsage" ]; then
345 xunit_output_end "$errorSource" "$errorMessage"
346 if ((printUsage != 0)); then
349 exit $EXIT_CODE_EXCEPTION
352 # Handle Ctrl-C. We will stop execution and print the results that
353 # we gathered so far.
354 function handle_ctrl_c {
355 local errorSource='handle_ctrl_c'
358 echo "*** Stopping... ***"
360 exit_with_error "$errorSource" "Test run aborted by Ctrl+C."
363 # Register the Ctrl-C handler
364 trap handle_ctrl_c INT
366 # Variables for unsupported and failing tests
367 declare -a unsupportedCrossGenLibs
368 declare -a unsupportedCrossGenTests
369 declare -a unsupportedTests
370 declare -a unsupportedGCStressTests
372 # Get an array of items by reading the specified file line by line.
373 function read_array {
376 if [ ! -f "$1" ]; then
380 # bash in Mac OS X doesn't support 'readarray', so using alternate way instead.
381 # readarray -t theArray < "$1"
382 # Any line that starts with '#' is ignored.
383 while IFS='' read -r line || [ -n "$line" ]; do
384 if [[ $line != "#"* ]]; then
385 theArray[${#theArray[@]}]=$line
391 function load_unsupported_tests {
392 # Load the list of tests that are not supported on this platform
393 unsupportedTests=($(read_array "$(dirname "$0")/unsupportedTests.txt"))
394 # Load the list of libs that are not supported for crossgen on this platform
395 unsupportedCrossGenLibs=($(read_array "$(dirname "$0")/unsupportedCrossgenLibs.txt"))
396 # Load the list of test that are not supported for crossgen on this platform
397 unsupportedCrossGenTests=($(read_array "$(dirname "$0")/unsupportedCrossgenTests.txt"))
398 # Load the list of tests that are not supported on this platform in GCStress mode
399 unsupportedGCStressTests=($(read_array "$(dirname "$0")/unsupportedGCStressTests.txt"))
402 function is_unsupported_crossgen_lib {
403 for unsupported in "${unsupportedCrossGenLibs[@]}"; do
404 if [ "$1" == "$unsupported" ]; then
411 function is_unsupported_test {
412 for unsupported in "${unsupportedTests[@]}"; do
413 if [ "$1" == "$unsupported" ]; then
418 if [ $doCrossgenTests == 1 ] || [ $doCrossgen2Tests == 1 ]; then
419 for unsupported in "${unsupportedCrossGenTests[@]}"; do
420 if [ "$1" == "$unsupported" ]; then
426 if [[ ! -z "$COMPlus_GCStress" ]] && [[ "$COMPlus_GCStress" -ne "0" ]]; then
427 for unsupported in "${unsupportedGCStressTests[@]}"; do
428 if [ "$1" == "$unsupported" ]; then
437 function crossgen_file {
442 # ni.dll are created as ni.dll.tmp in order to not interfere
443 # with crossgen2 at first, then moved to ni.dll all at once at the end
444 # (logic is similar to https://github.com/dotnet/runtime/pull/57341/)
445 local tmp_ni_path=$(echo $dll_path | sed 's/.dll$/.ni.dll.tmp/')
447 echo "Precompiling $dll_path to $tmp_ni_path"
449 if [ $doCrossgenLibs == 1 ]; then
450 ${overlayDir}/crossgen /in $dll_path /out $tmp_ni_path $CrossGenOptions /p ${overlayDir}:${overlayDir}/crossgen2 &>$dll_path.out
451 elif [ $doCrossgen2Libs == 1 ]; then
452 ${overlayDir}/corerun ${overlayDir}/crossgen2/crossgen2.dll $CrossGen2Options -o:$tmp_ni_path $dll_path -r:${overlayDir}/*.dll -r:${overlayDir}/crossgen2/*.dll &>$dll_path.out
456 if [[ $exitCode != 0 ]]; then
457 echo Crossgen fail for $dll_path.
458 echo "$dll_path" >> "$libsCrossgenFailOutputPath"
462 if [ $CrossGenAllowFail == 0 ]; then
466 echo Crossgen success $dll_path.
467 echo "$dll_path" >> "$libsCrossgenPassOutputPath"
469 if [[ "${name}" == "System.Private.CoreLib.dll" ]]; then
470 # SPC.ni.dll can be used directly without ni.dll.tmp
471 # (because SPC doesn't use any dependencies)
472 mv $dll_path $dll_path.bak
473 mv $tmp_ni_path $dll_path
480 function precompile_overlay_assemblies {
481 local overlayDir=$CORE_ROOT
483 if [ $doCopyNetcoreToCoreroot == 1 ]; then
484 echo "Copying netcore ($netcoreDir) to coreroot ($overlayDir)"
485 cp -r $netcoreDir/* $overlayDir
488 echo Cleanup old ni.dll
489 for file in `find $testRootDir -name "*.ni.*"`; do
493 test -f $overlayDir/System.Private.CoreLib.dll.Backup && mv $overlayDir/System.Private.CoreLib.dll.Backup $overlayDir/System.Private.CoreLib.dll
494 test -f $overlayDir/System.Private.CoreLib.dll.bak && mv $overlayDir/System.Private.CoreLib.dll.bak $overlayDir/System.Private.CoreLib.dll
496 if [ $doCrossgenLibs == 0 ] && [ $doCrossgen2Libs == 0 ]; then
497 echo Skipping crossgen of libs.
500 echo Precompiling libs
503 if [ $doCrossgenSPCFirst == 1 ]; then
504 local dll_path=$overlayDir/System.Private.CoreLib.dll
505 local name=$(basename $dll_path)
506 crossgen_file $overlayDir $dll_path $name
509 if [ -z "$crossgenLibs" ]; then
510 # No libs to crossgen were specified, so crossgen everything in the overlay
511 filesToPrecompile=$(find -L $overlayDir -iname \*.dll -not -iname \*.ni.dll -type f)
513 # Otherwise, compile only specified libs
514 filesToPrecompile=$(echo "${crossgenLibs[@]}")
517 for fileToPrecompile in ${filesToPrecompile}
519 local dll_path=${fileToPrecompile}
520 local name=$(basename $dll_path)
522 if [[ "$name" == "System.Private.CoreLib.dll" && "$doCrossgenSPCFirst" == "1" ]]; then
526 if is_unsupported_crossgen_lib "${name}"; then
527 echo Skipping crossgen for $dll_path.
528 echo "$dll_path" >> "$libsCrossgenSkipOutputPath"
532 crossgen_file $overlayDir $dll_path $name
535 # Copy ni.dll all at once
536 for tmp_ni_path in `find $overlayDir -name "*.ni.dll.tmp"`; do
537 local ni_dll_path=$(echo $tmp_ni_path | sed 's/.ni.dll.tmp$/.ni.dll/')
539 echo "Moving $tmp_ni_path to $ni_dll_path"
540 mv $tmp_ni_path $ni_dll_path
544 function skip_unsupported_test {
545 # This function runs in a background process. It should not echo anything, and should not use global variables. This
546 # function is analogous to run_test, and causes the test to be skipped with the message below.
548 local scriptFilePath=$1
549 local outputFilePath=$2
551 echo "Not supported on this platform or in this mode." >"$outputFilePath"
552 return 2 # skip the test
556 # This function runs in a background process. It should not echo anything, and should not use global variables.
558 local scriptFilePath=$1
559 local outputFilePath=$2
561 # Switch to directory where the script is
562 cd "$(dirname "$scriptFilePath")"
564 local scriptFileName=$(basename "$scriptFilePath")
565 local outputFileName=$(basename "$outputFilePath")
567 echo "" > "$outputFileName" 2>&1
569 if [ $useMulticoreJit == 1 ]; then
570 export COMPlus_MultiCoreJitProfile="`pwd`/mcj_profile.dat"
571 export COMPlus_MultiCoreJitMinNumCpus="1"
572 echo "MULTICOREJIT: 1st launch" >> "$outputFileName" 2>&1
574 "./$scriptFileName" >> "$outputFileName" 2>&1
575 local testScriptExitCode=$?
577 if [ $testScriptExitCode == 0 ]; then
578 if [ $useMulticoreJitNoProfileGather == 1 ]; then
579 export COMPlus_MultiCoreJitNoProfileGather="1"
582 echo "" >> "$outputFileName" 2>&1
583 echo "MULTICOREJIT: 2nd launch" >> "$outputFileName" 2>&1
585 return $testScriptExitCode
589 if [ $doCrossgenTests == 1 ]; then
593 if [ $doCrossgen2Tests == 1 ]; then
594 export RunCrossGen2=1
597 "./$scriptFileName" >> "$outputFileName" 2>&1
598 local testScriptExitCode=$?
600 return $testScriptExitCode
603 # Variables for running tests in the background
604 ((maxProcesses = 1)) # long tests delay process creation, use a few more processors
607 declare -a scriptFilePaths
608 declare -a outputFilePaths
609 declare -a processIds
610 declare -a testStartTimes
618 for (( i=0; i<$maxProcesses; i++ )); do
619 pid=${processIds[$i]}
620 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
623 if ! kill -0 $pid 2>/dev/null; then
627 processIds[$i]=$pidNone
635 function get_available_process_index {
638 for (( i=0; i<$maxProcesses; i++ )); do
639 pid=${processIds[$i]}
640 if [ -z "$pid" ] || [ "$pid" == "$pidNone" ]; then
647 function finish_test {
649 local testScriptExitCode=$?
650 local finishedProcessIndex=$waitProcessIndex
653 local scriptFilePath=${scriptFilePaths[$finishedProcessIndex]}
654 local outputFilePath=${outputFilePaths[$finishedProcessIndex]}
655 local scriptFileName=$(basename "$scriptFilePath")
658 local testRunningTime=
661 if ((verbose == 1)); then
662 header=$(printf "[%4d]" $countTotalTests)
665 testEndTime=$(date +%s)
666 testRunningTime=$(( $testEndTime - ${testStartTimes[$finishedProcessIndex]} ))
667 header=$header$(printf "[%4ds]" $testRunningTime)
669 if [ $useMulticoreJit == 1 ]; then
670 header="$header[mcj]"
674 case $testScriptExitCode in
676 let countPassedTests++
678 if ((verbose == 1)); then
679 echo "PASSED - ${header}${scriptFilePath}"
681 echo " - ${header}${scriptFilePath}"
685 let countSkippedTests++
687 echo "SKIPPED - ${header}${scriptFilePath}"
690 let countFailedTests++
692 echo "FAILED - ${header}${scriptFilePath}"
695 let countTotalTests++
697 if ((verbose == 1 || testScriptExitCode != 0)); then
698 while IFS='' read -r line || [ -n "$line" ]; do
700 done <"$outputFilePath"
703 xunit_output_add_test "$scriptFilePath" "$outputFilePath" "$testResult" "$testScriptExitCode" "$testRunningTime"
704 text_file_output_add_test "$scriptFilePath" "$testResult"
707 function finish_remaining_tests {
708 # Finish the remaining tests in the order in which they were started
709 while ((processCount > 0)); do
715 local scriptFilePath=$1
716 local scriptFileDir=$(dirname "$scriptFilePath")
718 test "$verbose" == 1 && echo "Preparing $scriptFilePath"
720 # Add executable file mode bit if needed
721 chmod +x "$scriptFilePath"
724 rm -rf $scriptFileDir/lock
726 # remove mcj profiles
727 rm -rf $scriptFileDir/mcj_profile.dat*
730 function start_test {
731 local nextProcessIndex=$(get_available_process_index)
732 local scriptFilePath=$1
734 if ((nextProcessIndex == maxProcesses)); then
736 nextProcessIndex=$(get_available_process_index)
739 scriptFilePaths[$nextProcessIndex]=$scriptFilePath
740 local scriptFileName=$(basename "$scriptFilePath")
741 local outputFilePath=$(dirname "$scriptFilePath")/${scriptFileName}.out
742 outputFilePaths[$nextProcessIndex]=$outputFilePath
744 testStartTimes[$nextProcessIndex]=$(date +%s)
746 test "$verbose" == 1 && echo "Starting $scriptFilePath"
747 if is_unsupported_test "$scriptFilePath"; then
748 skip_unsupported_test "$scriptFilePath" "$outputFilePath" &
750 run_test "$scriptFilePath" "$outputFilePath" &
752 processIds[$nextProcessIndex]=$!
757 # Get a list of directories in which to scan for tests by reading the
758 # specified file line by line.
759 function set_test_directories {
760 local errorSource='set_test_directories'
762 local listFileName=$1
764 if [ ! -f "$listFileName" ]
766 exit_with_error "$errorSource" "Test directories file not found at $listFileName"
768 testDirectories=($(read_array "$listFileName"))
771 function run_tests_in_directory {
773 local skipScriptsInDir=$2
777 # Need to skip scripts in testDir since they are not tests
778 if [[ "$skipScriptsInDir" == "1" ]]; then
782 # Recursively search through directories for .sh files to prepare them.
783 # Note: This needs to occur before any test runs as some of the .sh files
784 # depend on other .sh files
785 echo "Preparing tests..."
786 for scriptFilePath in $(find "$testDir" -mindepth ${minDepth} -type f -iname '*.sh' | sort)
788 prep_test "${scriptFilePath:2}"
790 echo "The tests have been prepared"
791 # Recursively search through directories for .sh files to run.
792 for scriptFilePath in $(find "$testDir" -mindepth ${minDepth} -type f -iname '*.sh' | sort)
794 start_test "${scriptFilePath:2}"
798 # Exit code constants
799 readonly EXIT_CODE_SUCCESS=0 # Script ran normally.
800 readonly EXIT_CODE_EXCEPTION=1 # Script exited because something exceptional happened (e.g. bad arguments, Ctrl-C interrupt).
801 readonly EXIT_CODE_TEST_FAILURE=2 # Script completed successfully, but one or more tests failed.
804 testRootDir="/opt/usr/coreclr-tc/"
805 coreOverlayDir="/opt/usr/coreclr-tc/coreroot/"
806 doCopyNetcoreToCoreroot=0
807 netcoreDir="/usr/share/dotnet.tizen/netcoreapp"
820 useMulticoreJitNoProfileGather=0
825 export COMPlus_MultiCoreJitProfile=
826 export COMPlus_MultiCoreJitMinNumCpus=
827 export COMPlus_MultiCoreJitNoProfileGather=
830 export COMPlus_JitStress=
831 export COMPlus_JitStressRegs=
832 export COMPlus_GCStress=
839 exit $EXIT_CODE_SUCCESS
859 --crossgen-spc-first)
863 crossgenOpts="$crossgenOpts ${i#*=}"
865 --crossgen2options=*)
866 crossgen2Opts="$crossgen2Opts ${i#*=}"
868 --allow-crossgen-fails)
872 crossgenLibs[${#crossgenLibs[@]}]=${i#*=}
875 export COMPlus_JitStress=${i#*=}
878 export COMPlus_JitStressRegs=${i#*=}
883 --mcj-no-profile-gather)
884 useMulticoreJitNoProfileGather=1
890 coreOverlayDir=${i#*=}
895 --copy-netcore-to-coreroot)
896 doCopyNetcoreToCoreroot=1
899 testDirectories[${#testDirectories[@]}]=${i#*=}
902 set_test_directories "${i#*=}"
905 ((maxProcesses = ${i#*=}))
911 export COMPlus_GCStress=${i#*=}
914 xunitOutputPath=${i#*=}
916 --testsPassOutputPath=*)
917 testsPassOutputPath=${i#*=}
919 --testsSkipOutputPath=*)
920 testsSkipOutputPath=${i#*=}
922 --testsFailOutputPath=*)
923 testsFailOutputPath=${i#*=}
925 --libsCrossgenPassOutputPath=*)
926 libsCrossgenPassOutputPath=${i#*=}
928 --libsCrossgenSkipOutputPath=*)
929 libsCrossgenSkipOutputPath=${i#*=}
931 --libsCrossgenFailOutputPath=*)
932 libsCrossgenFailOutputPath=${i#*=}
935 echo "Unknown switch: $i"
937 exit $EXIT_CODE_SUCCESS
942 if [ -z "$ARCH" ]; then
943 echo "--arch is required."
945 exit $EXIT_CODE_EXCEPTION
947 if [ "$ARCH" != "arm" ] && [ "$ARCH" != "armel" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "riscv64" ]; then
948 echo "Unsupported value for --arch: $ARCH"
950 exit $EXIT_CODE_EXCEPTION
953 if [ -z "$testRootDir" ]; then
954 echo "--testRootDir is required."
956 exit $EXIT_CODE_EXCEPTION
958 if [ ! -d "$testRootDir" ]; then
959 echo "Directory specified by --testRootDir does not exist: $testRootDir"
960 exit $EXIT_CODE_EXCEPTION
963 if [ -z "$coreOverlayDir" ]; then
964 echo "--coreOverlayDir is required."
966 exit $EXIT_CODE_EXCEPTION
968 if [ ! -d "$coreOverlayDir" ]; then
969 echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
970 exit $EXIT_CODE_EXCEPTION
973 export CORE_ROOT="$coreOverlayDir"
975 # Default values for crossgen2 options
976 if [ "$crossgen2Opts" == "" ]; then
977 crossgen2Opts="--jitpath $coreOverlayDir/libclrjit.so --targetarch $ARCH"
980 export CrossGenOptions="$crossgenOpts"
981 export CrossGen2Options="$crossgen2Opts"
982 export CrossGen2OptionsR2RTest="--crossgen2-jitpath $coreOverlayDir/libclrjit.so --target-arch $ARCH"
984 echo "! Make sure CLR/FX are copied to $coreOverlayDir !"
986 echo "Running on CPU-$ARCH"
989 text_file_output_begin
990 load_unsupported_tests
991 precompile_overlay_assemblies
993 export __TestEnv=$testEnv
996 time_start=$(date +"%s")
997 if [ -z "$testDirectories" ]
999 # No test directories were specified, so run everything in the current
1000 # directory and its subdirectories.
1001 run_tests_in_directory "." 1
1003 # Otherwise, run all the tests in each specified test directory.
1004 for testDir in "${testDirectories[@]}"
1006 if [ ! -d "$testDir" ]; then
1007 echo "Test directory does not exist: $testDir"
1009 run_tests_in_directory "./$testDir" 0
1014 finish_remaining_tests
1017 time_end=$(date +"%s")
1018 time_diff=$(($time_end-$time_start))
1019 echo "$(($time_diff / 60)) minutes and $(($time_diff % 60)) seconds taken to run CoreCLR tests."
1023 if ((countFailedTests > 0)); then
1024 exit $EXIT_CODE_TEST_FAILURE
1027 exit $EXIT_CODE_SUCCESS