Skip to content

Commit 50b1310

Browse files
committed
First implementation of parallel testing
1 parent 8b165c5 commit 50b1310

File tree

1 file changed

+80
-24
lines changed

1 file changed

+80
-24
lines changed

test/run_generator_tests.sh

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,37 +46,35 @@ TEST_COUNTER=1
4646
# whether or not to delete everything except logs (default is to delete)
4747
KEEP_ONLY_LOGS=1
4848

49+
# Number of workers for parallel test runs
50+
JOBS=${JOBS:-8}
51+
echo "Running tests with up to ${JOBS} parallel jobs"
4952
# Prepare some colored output
5053
SRED="\033[0;31m"
5154
SGREEN="\033[0;32m"
5255
SEND="\033[0m"
5356

54-
5557
echo_green()
5658
{
5759
echo -e "${SGREEN}${*}${SEND}"
5860
}
5961

60-
6162
echo_red()
6263
{
6364
echo -e "${SRED}${*}${SEND}"
6465
}
6566

66-
6767
# Prevent the script from being soured to omit unexpected surprises when exit is used
6868
SCRIPT_NAME="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
6969
if [ "${SCRIPT_NAME}" != "$(basename ${BASH_SOURCE[0]})" ] ; then
7070
echo_red "This script cannot not be sourced" >&2
7171
return 1
7272
fi
7373

74-
7574
##################################
7675
# Core and utility functionality #
7776
##################################
7877

79-
8078
get_test_script_path_for_ini()
8179
{
8280
local ini_path=${1}
@@ -132,7 +130,7 @@ exec_test()
132130
[[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; }
133131
# run the simulation, fail if not successful
134132
echo "### Testing base o2-sim executable ###" >> ${LOG_FILE_SIM}
135-
o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 4 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1
133+
o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 1 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1
136134
RET=${?}
137135
[[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; }
138136

@@ -151,6 +149,13 @@ exec_test()
151149
return ${RET}
152150
}
153151

152+
wait_for_slot()
153+
{
154+
# Wait until the number of background jobs is within the limit
155+
while (( $(jobs -r | wc -l) >= JOBS )) ; do
156+
sleep 0.1
157+
done
158+
}
154159

155160
check_generators()
156161
{
@@ -169,31 +174,37 @@ check_generators()
169174
local look_for=$(grep " ${g}.*\(\)" ${test_script})
170175
local has_trigger="$(grep Trigger${g} ${ini_path})"
171176
[[ -z "${look_for}" ]] && continue
172-
echo -n "Test ${TEST_COUNTER}: ${ini_path} with generator ${g}"
173177
tested_any=1
174178
# prepare the test directory
175179
local test_dir=${TEST_COUNTER}_$(basename ${ini})_${g}_dir
176180
rm -rf ${test_dir} 2> /dev/null
177181
mkdir ${test_dir}
178-
pushd ${test_dir} > /dev/null
179-
# one single test
180-
exec_test ${ini_path} ${g} ${has_trigger}
181-
RET=${?}
182-
popd > /dev/null
183-
if [[ "${RET}" != "0" ]] ; then
184-
echo_red " -> FAILED"
185-
ret_this=${RET}
186-
else
187-
echo_green " -> PASSED"
188-
fi
182+
local test_num=${TEST_COUNTER}
189183
((TEST_COUNTER++))
184+
185+
# Wait for an available slot before starting a new test
186+
wait_for_slot
187+
188+
echo "Test ${test_num}: ${ini_path} with generator ${g} - STARTED"
189+
# Run test in background
190+
(
191+
cd ${test_dir}
192+
exec_test ${ini_path} ${g} ${has_trigger}
193+
exit $?
194+
) &
195+
local pid=$!
196+
197+
# Store test information in global arrays
198+
test_pids+=(${pid})
199+
test_numbers+=(${test_num})
200+
test_generators+=(${g})
201+
test_ini_paths+=("${ini_path}")
190202
fi
191203
done
192204
[[ -z "${tested_any}" ]] && { echo_red "No test scenario was found for any generator. There must be at least one generator to be tested." ; ret_this=1 ; }
193205
return ${ret_this}
194206
}
195207

196-
197208
add_ini_files_from_macros()
198209
{
199210
# given a list of macros, collect all INI files which contain at least one of them
@@ -216,7 +227,6 @@ add_ini_files_from_macros()
216227
done
217228
}
218229

219-
220230
get_root_includes()
221231
{
222232
# check if some R__ADD_INCLUDE_PATH is used in the including macro and check the included file against that
@@ -236,7 +246,6 @@ get_root_includes()
236246
echo ${full_includes}
237247
}
238248

239-
240249
find_including_macros()
241250
{
242251
# figure out the macros that INCLUDE macros that have changed, so that in turn we can check
@@ -283,7 +292,6 @@ find_including_macros()
283292
echo ${including_macros}
284293
}
285294

286-
287295
add_ini_files_from_tests()
288296
{
289297
# Collect also those INI files for which the test has been changed
@@ -302,7 +310,6 @@ add_ini_files_from_tests()
302310
done
303311
}
304312

305-
306313
collect_ini_files()
307314
{
308315
# Collect all INI files which have changed
@@ -336,7 +343,6 @@ collect_ini_files()
336343
add_ini_files_from_tests ${macros}
337344
}
338345

339-
340346
get_git_repo_directory()
341347
{
342348
local repo=
@@ -469,6 +475,12 @@ pushd ${TEST_PARENT_DIR} > /dev/null
469475
# global return code to be returned at the end
470476
ret_global=0
471477

478+
# Global arrays to track all test jobs (across all INI files)
479+
declare -a test_pids
480+
declare -a test_numbers
481+
declare -a test_generators
482+
declare -a test_ini_paths
483+
472484
# check each of the INI files
473485
for ini in ${ini_files_full_paths} ; do
474486

@@ -495,6 +507,50 @@ for ini in ${ini_files_full_paths} ; do
495507
[[ "${fail_immediately}" == "1" ]] && break
496508
fi
497509
done
510+
511+
# Wait for all test jobs to complete and collect results
512+
total_tests=${#test_pids[@]}
513+
completed=0
514+
while (( completed < total_tests )) ; do
515+
# Wait for any background job to complete
516+
wait -n
517+
RET=$?
518+
519+
# Find which job completed by checking which PID no longer exists
520+
for idx in "${!test_pids[@]}" ; do
521+
pid="${test_pids[$idx]}"
522+
if ! kill -0 ${pid} 2>/dev/null ; then
523+
# This job has completed, get its actual exit status
524+
wait ${pid} 2>/dev/null
525+
RET=$?
526+
527+
test_num="${test_numbers[$idx]}"
528+
generator="${test_generators[$idx]}"
529+
ini_path="${test_ini_paths[$idx]}"
530+
531+
if [[ "${RET}" != "0" ]] ; then
532+
echo_red "Test ${test_num}: ${ini_path} with generator ${generator} -> FAILED"
533+
ret_global=${RET}
534+
if [[ "${fail_immediately}" == "1" ]] ; then
535+
# Kill remaining background jobs
536+
for remaining_pid in "${test_pids[@]}" ; do
537+
kill ${remaining_pid} 2>/dev/null
538+
done
539+
completed=${total_tests}
540+
break
541+
fi
542+
else
543+
echo_green "Test ${test_num}: ${ini_path} with generator ${generator} -> PASSED"
544+
fi
545+
546+
# Remove this job from tracking
547+
unset test_pids[$idx]
548+
((completed++))
549+
break
550+
fi
551+
done
552+
done
553+
498554
# return to where we came from
499555
popd > /dev/null
500556

0 commit comments

Comments
 (0)