summaryrefslogtreecommitdiff
path: root/tests/runparallel.sh
blob: 697d3a00192368a55f3f1c29c8b4e27bef6fec18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/usr/bin/env bash

function print_usage {
    echo ''
    echo 'CoreCLR parallel test runner script.'
    echo ''
    echo 'Required arguments:'
    echo '  --testRootDir=<path>             : Root directory of the test build (e.g. coreclr/bin/tests/Windows_NT.x64.Debug).'
    echo '  --coreOverlayDir=<path>          : Directory containing core binaries and test dependencies. If not specified, the'
    echo '                                     default is testRootDir/Tests/coreoverlay. This switch overrides --coreClrBinDir,'
    echo '                                     --mscorlibDir, --coreFxBinDir, and --coreFxNativeBinDir.'
    echo '  --playlist=<path>                : Run only the tests that are specified in the file at <path>, in the same format as'
    echo ''
    echo 'Optional arguments:'
    echo '  -h|--help                        : Show usage information.'
    echo '  --test-env                       : Script to set environment variables for tests'
    echo ''
}

function print_results {
    echo -e \
       "Results @ $(date +%r)\n\t"\
       "Pass:$countPassedTests\t"\
       "Fail:$countFailedTests\n\t"\
       "Finish:$countFinishedTests\t"\
       "Incomplete: $countIncompleteTests\n\t"\
       "Total: $countTotalTests"
}

function update_results {
    # Initialize counters for bookkeeping.
    countTotalTests=$(wc -l < $playlistFile)

    countFinishedTests=$(cd results.int; grep -r 'RUN_TEST_EXIT_CODE' . | wc -l)
    countPassedTests=$(cd results.int; grep -r 'RUN_TEST_EXIT_CODE=0' . | wc -l)
    countFailedTests=$((countFinishedTests - countPassedTests))
    countIncompleteTests=$((countTotalTests - countFinishedTests))

    print_results
}

function print_elapsed_time {
    time_end=$(date +"%s")
    time_diff=$(($time_end-$time_start))
    echo "$(($time_diff / 60)) minutes and $(($time_diff % 60)) seconds taken to run CoreCLR tests."
}



# Handle Ctrl-C. We will stop execution and print the results that
# we gathered so far.
function handle_ctrl_c {
    local errorSource='handle_ctrl_c'

    echo ""
    echo "*** Stopping... ***"

    update_results
    echo "$errorSource" "Test run aborted by Ctrl+C."

    print_elapsed_time

    exit 1
}

function cleanup
{
    kill -TERM % >/dev/null
    mv results.int results.$(date +%F_%I%M%p)
}


prep_test() {
    # This function runs in a background process. It should not echo anything, and should not use global variables.

    #remove any NI
    rm -f $(dirname "$1")/*.ni.*
}

run_test() {
    # This function runs in a background process. It should not echo anything, and should not use global variables.

    local scriptFilePath=$1

    local scriptFileName=$(basename "$scriptFilePath")
    local outputFileName=$PWD/results.int/${scriptFilePath////.}

    nice "$scriptFilePath" -debug=$(which time) >"$outputFileName" 2>&1

    echo RUN_TEST_EXIT_CODE="$?" >>"$outputFileName"
}

# Argument variables
testRootDir=
coreOverlayDir=
testEnv=
playlistFile=

for i in "$@"
do
    case $i in
        -h|--help)
            print_usage
            exit $EXIT_CODE_SUCCESS
            ;;
        --coreOverlayDir=*)# Exit code constants
            coreOverlayDir=${i#*=}
            ;;
        --playlist=*)
            playlistFile=${i#*=}
            ;;
        --testRootDir=*)
            testRootDir=${i#*=}
            ;;
        --test-env=*)
            testEnv=${i#*=}
            ;;
        *)
            echo "Unknown switch: $i"
            print_usage
            exit $EXIT_CODE_SUCCESS
            ;;
    esac
done

if [ -z "$coreOverlayDir" ]; then
    echo "--coreOverlayDir is required."
    print_usage
    exit $EXIT_CODE_EXCEPTION
fi

if [ ! -d "$coreOverlayDir" ]; then
    echo "Directory specified by --coreOverlayDir does not exist: $coreOverlayDir"
    exit $EXIT_CODE_EXCEPTION
fi

if [ -z "$playlistFile" ]; then
    echo "--playlist is required."
    print_usage
    exit $EXIT_CODE_EXCEPTION
fi

if [ ! -e "$playlistFile" ]; then
    echo "File specified by --playlist does not exist: $playlistFile"
    exit $EXIT_CODE_EXCEPTION
fi

if [ -z "$testRootDir" ]; then
    echo "--testRootDir is required."
    print_usage
    exit $EXIT_CODE_EXCEPTION
fi

if [ ! -d "$testRootDir" ]; then
    echo "Directory specified by --testRootDir does not exist: $testRootDir"
    exit $EXIT_CODE_EXCEPTION
fi

if [ ! -z "$testEnv" ] && [ ! -e "$testEnv" ]; then
    echo "File specified by --playlist does not exist: $testEnv"
    exit $EXIT_CODE_EXCEPTION
fi

export CORE_ROOT="$coreOverlayDir"
export __TestEnv=$testEnv


# Variables for running tests in the background
if [ `uname` = "NetBSD" ]; then
    NumProc=$(getconf NPROCESSORS_ONLN)
else
    NumProc=$(getconf _NPROCESSORS_ONLN)
fi

export TIME='<Command time="%U %S %e" mem="%M %t %K" swap="%W %c %w" fault="%F %R %k %r %s" IO="%I %O" exit="%x"/>'

export -f prep_test
export -f run_test

cd $testRootDir
time_start=$(date +"%s")

rm -rf results.int/* results.int

echo "Prepping tests $(date +%r)"
xargs -d "\n" -P $NumProc -I{} bash -c prep_test  {} < $playlistFile


trap cleanup EXIT
mkdir results.int
echo $$ > results.int/pid
cp $testEnv results.int

trap handle_ctrl_c INT TERM

xargs -d "\n" -P $NumProc -I{} bash -c 'run_test "{}" >/dev/null 2>&1' < $playlistFile &

while true
do
    update_results
    sleep 20 &
    wait -n %
    if (( $(jobs %xargs 2>/dev/null | wc -l) == 0 )) ;
    then
        break
    fi

    jobs -p > /dev/null
done

update_results

print_elapsed_time