--- /dev/null
+#!/usr/bin/env bash
+
+export RUNTIME_PATH=${1%/}
+export EXECUTION_DIR=$(dirname "$0")
+
+exitcode_list[0]="Exited Successfully"
+exitcode_list[130]="SIGINT Ctrl-C occurred. Likely tests timed out."
+exitcode_list[131]="SIGQUIT Ctrl-\ occurred. Core dumped."
+exitcode_list[132]="SIGILL Illegal Instruction. Core dumped. Likely codegen issue."
+exitcode_list[133]="SIGTRAP Breakpoint hit. Core dumped."
+exitcode_list[134]="SIGABRT Abort. Managed or native assert, or runtime check such as heap corruption, caused call to abort(). Core dumped."
+exitcode_list[135]="IGBUS Unaligned memory access. Core dumped."
+exitcode_list[136]="SIGFPE Bad floating point arguments. Core dumped."
+exitcode_list[137]="SIGKILL Killed eg by kill"
+exitcode_list[139]="SIGSEGV Illegal memory access. Deref invalid pointer, overrunning buffer, stack overflow etc. Core dumped."
+exitcode_list[143]="SIGTERM Terminated. Usually before SIGKILL."
+exitcode_list[159]="SIGSYS Bad System Call."
+
+function print_info_from_core_file_using_lldb {
+ local core_file_name=$1
+ local executable_name=$2
+ local plugin_path_name="$RUNTIME_PATH/shared/Microsoft.NETCore.App/9.9.9/libsosplugin.so"
+
+ # check for existence of lldb on the path
+ hash lldb 2>/dev/null || { echo >&2 "lldb was not found. Unable to print core file."; return; }
+
+ # pe, clrstack, and dumpasync are defined in libsosplugin.so
+ if [ ! -f $plugin_path_name ]; then
+ echo $plugin_path_name cannot be found.
+ return
+ fi
+
+ echo ----- start =============== lldb Output =====================================================
+ echo Printing managed exceptions, managed call stacks, and async state machines.
+ lldb -O "settings set target.exec-search-paths $RUNTIME_PATH" -o "plugin load $plugin_path_name" -o "clrthreads -managedexception" -o "pe -nested" -o "clrstack -all -a -f" -o "dumpasync -roots" -o "quit" --core $core_file_name $executable_name
+ echo ----- end =============== lldb Output =======================================================
+}
+
+function print_info_from_core_file_using_gdb {
+ local core_file_name=$1
+ local executable_name=$2
+
+ # Check for the existence of GDB on the path
+ hash gdb 2>/dev/null || { echo >&2 "GDB was not found. Unable to print core file."; return; }
+
+ echo ----- start =============== GDB Output =====================================================
+ # Open the dump in GDB and print the stack from each thread. We can add more
+ # commands here if desired.
+ echo printing native stack.
+ gdb --batch -ex "thread apply all bt full" -ex "quit" $executable_name $core_file_name
+ echo ----- end =============== GDB Output =======================================================
+}
+
+function print_info_from_core_file {
+ local core_file_name=$1
+ local executable_name=$RUNTIME_PATH/$2
+
+ if ! [ -e $executable_name ]; then
+ echo "Unable to find executable $executable_name"
+ return
+ elif ! [ -e $core_file_name ]; then
+ echo "Unable to find core file $core_file_name"
+ return
+ fi
+ echo "Printing info from core file $core_file_name"
+ print_info_from_core_file_using_gdb $core_file_name $executable_name
+ print_info_from_core_file_using_lldb $core_file_name $executable_name
+}
+
+function copy_core_file_to_temp_location {
+ local core_file_name=$1
+
+ local storage_location="/tmp/coredumps"
+
+ # Create the directory (this shouldn't fail even if it already exists).
+ mkdir -p $storage_location
+
+ local new_location=$storage_location/core.$RANDOM
+
+ echo "Copying core file $core_file_name to $new_location in case you need it."
+ cp $core_file_name $new_location
+}
+
+if [ "$RUNTIME_PATH" == "" ]
+then
+echo error: RUNTIME_PATH is not defined. Usage: $0 RUNTIME_PATH
+exit -1
+fi
+
+# ========================= BEGIN Core File Setup ============================
+if [ "$(uname -s)" == "Darwin" ]; then
+ # On OS X, we will enable core dump generation only if there are no core
+ # files already in /cores/ at this point. This is being done to prevent
+ # inadvertently flooding the CI machines with dumps.
+ if [[ ! -d "/cores" || ! "$(ls -A /cores)" ]]; then
+ ulimit -c unlimited
+ fi
+elif [ "$(uname -s)" == "Linux" ]; then
+ # On Linux, we'll enable core file generation unconditionally, and if a dump
+ # is generated, we will print some useful information from it and delete the
+ # dump immediately.
+
+ if [ -e /proc/self/coredump_filter ]; then
+ # Include memory in private and shared file-backed mappings in the dump.
+ # This ensures that we can see disassembly from our shared libraries when
+ # inspecting the contents of the dump. See 'man core' for details.
+ echo -n 0x3F > /proc/self/coredump_filter
+ fi
+
+ ulimit -c unlimited
+fi
+# ========================= END Core File Setup ==============================
+
+# ========================= BEGIN Test Execution =============================
+echo ----- start $(date +"%T") =============== To repro directly: =====================================================
+echo pushd $EXECUTION_DIR
+echo "$RUNTIME_PATH/dotnet xunit.console.dll TEST_NAME_DLL -xml testResults.xml -nologo -notrait category=nonnetcoreapptests -notrait category=nonlinuxtests -notrait category=failing -notrait category=Outerloop"
+
+echo popd
+echo ===========================================================================================================
+pushd $EXECUTION_DIR
+$RUNTIME_PATH/dotnet xunit.console.dll TEST_NAME_DLL -xml testResults.xml -nologo -notrait category=nonnetcoreapptests -notrait category=nonlinuxtests -notrait category=failing -notrait category=Outerloop
+
+test_exitcode=$?
+popd
+echo ----- end $(date +"%T") ----- exit code $test_exitcode ----------------------------------------------------------
+
+if [ "${exitcode_list[$test_exitcode]}" != "" ]; then
+ echo exit code $test_exitcode means ${exitcode_list[$test_exitcode]}
+fi
+# ========================= END Test Execution ===============================
+
+# ======================= BEGIN Core File Inspection =========================
+pushd $EXECUTION_DIR >/dev/null
+if [[ "$(uname -s)" == "Linux" && $test_exitcode -ne 0 ]]; then
+ echo Looking around for any Linux dump...
+ # Depending on distro/configuration, the core files may either be named "core"
+ # or "core.<PID>" by default. We read /proc/sys/kernel/core_uses_pid to
+ # determine which it is.
+ core_name_uses_pid=0
+ if [ -e /proc/sys/kernel/core_uses_pid ] && [ "1" == $(cat /proc/sys/kernel/core_uses_pid) ]; then
+ core_name_uses_pid=1
+ fi
+
+ if [ $core_name_uses_pid == "1" ]; then
+ # We don't know what the PID of the process was, so let's look at all core
+ # files whose name matches core.NUMBER
+ echo Looking for files matching core.* ...
+ for f in core.*; do
+ [[ $f =~ core.[0-9]+ ]] && print_info_from_core_file "$f" "dotnet" && copy_core_file_to_temp_location "$f" && rm "$f"
+ done
+ elif [ -f core ]; then
+ echo found a dump named core in $EXECUTION_DIR !
+ print_info_from_core_file "core" "dotnet"
+ copy_core_file_to_temp_location "core"
+ rm "core"
+ else
+ echo ... found no dump in $PWD
+ fi
+fi
+popd >/dev/null
+# ======================== END Core File Inspection ==========================
+exit $test_exitcode
+
--- /dev/null
+#!/usr/bin/env bash
+
+wait_on_pids()
+{
+ # Wait on the last processes
+ for job in $1
+ do
+ wait $job
+ if [ "$?" -ne 0 ]
+ then
+ TestsFailed=$(($TestsFailed+1))
+ fi
+ done
+}
+
+usage()
+{
+ echo "Runs .NET CoreFX tests on FreeBSD, Linux, NetBSD or OSX"
+ echo "usage: run-test [options]"
+ echo
+ echo "Input sources:"
+ echo " --runtime <location> Location of root of the binaries directory"
+ echo " containing the FreeBSD, Linux, NetBSD or OSX runtime"
+ echo " default: <repo_root>/bin/testhost/netcoreapp-<OS>-<ConfigurationGroup>-<Arch>"
+ echo " --corefx-tests <location> Location of the root binaries location containing"
+ echo " the tests to run"
+ echo " default: <repo_root>/bin"
+ echo
+ echo "Flavor/OS/Architecture options:"
+ echo " --configurationGroup <config> ConfigurationGroup to run (Debug/Release)"
+ echo " default: Debug"
+ echo " --os <os> OS to run (FreeBSD, Linux, NetBSD or OSX)"
+ echo " default: detect current OS"
+ echo " --arch <Architecture> Architecture to run (x64, arm, armel, x86, arm64)"
+ echo " default: detect current architecture"
+ echo
+ echo "Execution options:"
+ echo " --sequential Run tests sequentially (default is to run in parallel)."
+ echo " --restrict-proj <regex> Run test projects that match regex"
+ echo " default: .* (all projects)"
+ echo " --useServerGC Enable Server GC for this test run"
+ echo " --test-dir <path> Run tests only in the specified directory. Path is relative to the directory"
+ echo " specified by --corefx-tests"
+ echo " --test-dir-file <path> Run tests only in the directories specified by the file at <path>. Paths are"
+ echo " listed one line, relative to the directory specified by --corefx-tests"
+ echo " --test-exclude-file <path> Do not run tests in the directories specified by the file at <path>. Paths are"
+ echo " listed one line, relative to the directory specified by --corefx-tests"
+ echo " --timeout <time> Specify a per-test timeout value (using 'timeout' tool syntax; default is 10 minutes (10m))"
+ echo
+ echo "Runtime Code Coverage options:"
+ echo " --coreclr-coverage Optional argument to get coreclr code coverage reports"
+ echo " --coreclr-objs <location> Location of root of the object directory"
+ echo " containing the FreeBSD, Linux, NetBSD or OSX coreclr build"
+ echo " default: <repo_root>/bin/obj/<OS>.x64.<ConfigurationGroup"
+ echo " --coreclr-src <location> Location of root of the directory"
+ echo " containing the coreclr source files"
+ echo
+ exit 1
+}
+
+# Handle Ctrl-C.
+function handle_ctrl_c {
+ local errorSource='handle_ctrl_c'
+
+ echo ""
+ echo "Cancelling test execution."
+ exit $TestsFailed
+}
+
+# Register the Ctrl-C handler
+trap handle_ctrl_c INT
+
+ProjectRoot="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+# Location parameters
+# OS/ConfigurationGroup defaults
+ConfigurationGroup="Debug"
+OSName=$(uname -s)
+case $OSName in
+ Darwin)
+ OS=OSX
+ ;;
+
+ FreeBSD)
+ OS=FreeBSD
+ ;;
+
+ Linux)
+ OS=Linux
+ ;;
+
+ NetBSD)
+ OS=NetBSD
+ ;;
+
+ *)
+ echo "Unsupported OS $OSName detected, configuring as if for Linux"
+ OS=Linux
+ ;;
+esac
+
+# Use uname to determine what the CPU is.
+CPUName=$(uname -p)
+# Some Linux platforms report unknown for platform, but the arch for machine.
+if [ "$CPUName" == "unknown" ]; then
+ CPUName=$(uname -m)
+fi
+
+case $CPUName in
+ i686)
+ echo "Unsupported CPU $CPUName detected, test might not succeed!"
+ __Arch=x86
+ ;;
+
+ x86_64)
+ __Arch=x64
+ ;;
+
+ armv7l)
+ __Arch=armel
+ ;;
+
+ aarch64)
+ __Arch=arm64
+ ;;
+ amd64)
+ __Arch=x64
+ ;;
+ *)
+ echo "Unknown CPU $CPUName detected, configuring as if for x64"
+ __Arch=x64
+ ;;
+esac
+
+# Misc defaults
+TestSelection=".*"
+TestsFailed=0
+
+ensure_binaries_are_present()
+{
+ if [ ! -d $Runtime ]
+ then
+ echo "error: Coreclr $OS binaries not found at $Runtime"
+ exit 1
+ fi
+}
+
+# $1 is the path of list file
+read_array()
+{
+ local theArray=()
+
+ while IFS='' read -r line || [ -n "$line" ]; do
+ theArray[${#theArray[@]}]=$line
+ done < "$1"
+ echo ${theArray[@]}
+}
+
+run_selected_tests()
+{
+ local selectedTests=()
+
+ if [ -n "$TestDirFile" ]; then
+ selectedTests=($(read_array "$TestDirFile"))
+ fi
+
+ if [ -n "$TestDir" ]; then
+ selectedTests[${#selectedTests[@]}]="$TestDir"
+ fi
+
+ run_all_tests ${selectedTests[@]/#/$CoreFxTests/}
+}
+
+# $1 is the name of the platform folder (e.g Unix.AnyCPU.Debug)
+run_all_tests()
+{
+ for testFolder in $@
+ do
+ run_test $testFolder &
+ pids="$pids $!"
+ numberOfProcesses=$(($numberOfProcesses+1))
+ if [ "$numberOfProcesses" -ge $maxProcesses ]; then
+ wait_on_pids "$pids"
+ numberOfProcesses=0
+ pids=""
+ fi
+ done
+
+ # Wait on the last processes
+ wait_on_pids "$pids"
+ pids=""
+}
+
+# $1 is the path to the test folder
+run_test()
+{
+ testProject=`basename $1`
+
+ # Check for project restrictions
+
+ if [[ ! $testProject =~ $TestSelection ]]; then
+ echo "Skipping $testProject"
+ exit 0
+ fi
+
+ if [ -n "$TestExcludeFile" ]; then
+ if grep -q $testProject "$TestExcludeFile" ; then
+ echo "Excluding $testProject"
+ exit 0
+ fi
+ fi
+
+ dirName="$1/netcoreapp-$OS-$ConfigurationGroup-$__Arch"
+ if [ ! -d "$dirName" ]; then
+ echo "Nothing to test in $testProject"
+ return
+ fi
+
+ if [ ! -e "$dirName/RunTests.sh" ]; then
+ echo "Cannot find $dirName/RunTests.sh"
+ return
+ fi
+
+ pushd $dirName > /dev/null
+
+ echo
+ echo "Running tests in $dirName"
+ echo "${TimeoutTool}./RunTests.sh $Runtime"
+ echo
+ ${TimeoutTool}./RunTests.sh "$Runtime"
+ exitCode=$?
+
+ if [ $exitCode -ne 0 ]
+ then
+ echo "error: One or more tests failed while running tests from '$fileNameWithoutExtension'. Exit code $exitCode."
+ fi
+
+ popd > /dev/null
+ exit $exitCode
+}
+
+coreclr_code_coverage()
+{
+ if [ ! "$OS" == "FreeBSD" ] && [ ! "$OS" == "Linux" ] && [ ! "$OS" == "NetBSD" ] && [ ! "$OS" == "OSX" ]
+ then
+ echo "error: Code Coverage not supported on $OS"
+ exit 1
+ fi
+
+ if [ "$CoreClrSrc" == "" ]
+ then
+ echo "error: Coreclr source files are required to generate code coverage reports"
+ echo "Coreclr source files root path can be passed using '--coreclr-src' argument"
+ exit 1
+ fi
+
+ local coverageDir="$ProjectRoot/artifacts/bin/Coverage"
+ local toolsDir="$coverageDir/tools"
+ local reportsDir="$coverageDir/reports"
+ local packageName="unix-code-coverage-tools.1.0.0.nupkg"
+ rm -rf $coverageDir
+ mkdir -p $coverageDir
+ mkdir -p $toolsDir
+ mkdir -p $reportsDir
+ pushd $toolsDir > /dev/null
+
+ echo "Pulling down code coverage tools"
+
+ which curl > /dev/null 2> /dev/null
+ if [ $? -ne 0 ]; then
+ wget -q -O $packageName https://www.myget.org/F/dotnet-buildtools/api/v2/package/unix-code-coverage-tools/1.0.0
+ else
+ curl -sSL -o $packageName https://www.myget.org/F/dotnet-buildtools/api/v2/package/unix-code-coverage-tools/1.0.0
+ fi
+
+ echo "Unzipping to $toolsDir"
+ unzip -q -o $packageName
+
+ # Invoke gcovr
+ chmod a+rwx ./gcovr
+ chmod a+rwx ./$OS/llvm-cov
+
+ echo
+ echo "Generating coreclr code coverage reports at $reportsDir/coreclr.html"
+ echo "./gcovr $CoreClrObjs --gcov-executable=$toolsDir/$OS/llvm-cov -r $CoreClrSrc --html --html-details -o $reportsDir/coreclr.html"
+ echo
+ ./gcovr $CoreClrObjs --gcov-executable=$toolsDir/$OS/llvm-cov -r $CoreClrSrc --html --html-details -o $reportsDir/coreclr.html
+ exitCode=$?
+ popd > /dev/null
+ exit $exitCode
+}
+
+# Parse arguments
+
+RunTestSequential=0
+((serverGC = 0))
+TimeoutTime=20m
+
+while [[ $# > 0 ]]
+do
+ opt="$1"
+ case $opt in
+ -h|--help)
+ usage
+ ;;
+ --runtime)
+ Runtime=$2
+ ;;
+ --corefx-tests)
+ CoreFxTests=$2
+ ;;
+ --restrict-proj)
+ TestSelection=$2
+ ;;
+ --configurationGroup)
+ ConfigurationGroup=$2
+ ;;
+ --os)
+ OS=$2
+ ;;
+ --arch)
+ __Arch=$2
+ ;;
+ --coreclr-coverage)
+ CoreClrCoverage=ON
+ ;;
+ --coreclr-objs)
+ CoreClrObjs=$2
+ ;;
+ --coreclr-src)
+ CoreClrSrc=$2
+ ;;
+ --sequential)
+ RunTestSequential=1
+ ;;
+ --useServerGC)
+ ((serverGC = 1))
+ ;;
+ --test-dir)
+ TestDir=$2
+ ;;
+ --test-dir-file)
+ TestDirFile=$2
+ ;;
+ --test-exclude-file)
+ TestExcludeFile=$2
+ ;;
+ --timeout)
+ TimeoutTime=$2
+ ;;
+ --outerloop)
+ OuterLoop=""
+ ;;
+ --IgnoreForCI)
+ IgnoreForCI="-notrait category=IgnoreForCI"
+ ;;
+ *)
+ ;;
+ esac
+ shift
+done
+
+# Compute paths to the binaries if they haven't already been computed
+
+if [ "$Runtime" == "" ]
+then
+ Runtime="$ProjectRoot/artifacts/bin/testhost/netcoreapp-$OS-$ConfigurationGroup-$__Arch"
+fi
+
+if [ "$CoreFxTests" == "" ]
+then
+ CoreFxTests="$ProjectRoot/artifacts/bin"
+fi
+
+# Check parameters up front for valid values:
+
+if [ ! "$ConfigurationGroup" == "Debug" ] && [ ! "$ConfigurationGroup" == "Release" ]
+then
+ echo "error: ConfigurationGroup should be Debug or Release"
+ exit 1
+fi
+
+if [ ! "$OS" == "FreeBSD" ] && [ ! "$OS" == "Linux" ] && [ ! "$OS" == "NetBSD" ] && [ ! "$OS" == "OSX" ]
+then
+ echo "error: OS should be FreeBSD, Linux, NetBSD or OSX"
+ exit 1
+fi
+
+export CORECLR_SERVER_GC="$serverGC"
+export PAL_OUTPUTDEBUGSTRING="1"
+
+if [ "$LANG" == "" ]
+then
+ export LANG="en_US.UTF-8"
+fi
+
+# Is the 'timeout' tool available?
+TimeoutTool=
+if hash timeout 2>/dev/null ; then
+ TimeoutTool="timeout --kill-after=30s $TimeoutTime "
+fi
+
+ensure_binaries_are_present
+
+# Walk the directory tree rooted at src bin/tests/$OS.AnyCPU.$ConfigurationGroup/
+
+TestsFailed=0
+numberOfProcesses=0
+
+if [ $RunTestSequential -eq 1 ]
+then
+ maxProcesses=1;
+else
+ if [ `uname` = "NetBSD" ] || [ `uname` = "FreeBSD" ]; then
+ maxProcesses=$(($(getconf NPROCESSORS_ONLN)+1))
+ else
+ maxProcesses=$(($(getconf _NPROCESSORS_ONLN)+1))
+ fi
+fi
+
+if [ -n "$TestDirFile" ] || [ -n "$TestDir" ]
+then
+ run_selected_tests
+else
+ run_all_tests "$CoreFxTests/tests/"*.Tests
+fi
+
+if [ "$CoreClrCoverage" == "ON" ]
+then
+ coreclr_code_coverage
+fi
+
+if [ "$TestsFailed" -gt 0 ]
+then
+ echo "$TestsFailed test(s) failed"
+else
+ echo "All tests passed."
+fi
+
+exit $TestsFailed