Skip to content

Commit 04dc6a6

Browse files
committed
check-test script for bot, same one as used for software layer
1 parent b3d8ce3 commit 04dc6a6

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed

bot/check-test.sh

+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
#!/bin/bash
2+
#
3+
# Dummy script that only creates test result file for the bot, without actually checking anything
4+
#
5+
# This script is part of the EESSI software layer, see
6+
# https://github.com/EESSI/software-layer.git
7+
#
8+
# author: Kenneth Hoste (HPC-UGent)
9+
#
10+
# license: GPLv2
11+
#
12+
job_dir=${PWD}
13+
job_out="slurm-${SLURM_JOB_ID}.out"
14+
job_test_result_file="_bot_job${SLURM_JOB_ID}.test"
15+
16+
# Check that job output file is found
17+
[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for job output file(s) matching '"${job_out}"'"
18+
if [[ -f ${job_out} ]]; then
19+
SLURM_OUTPUT_FOUND=1
20+
[[ ${VERBOSE} -ne 0 ]] && echo " found slurm output file '"${job_out}"'"
21+
else
22+
SLURM_OUTPUT_FOUND=0
23+
[[ ${VERBOSE} -ne 0 ]] && echo " Slurm output file '"${job_out}"' NOT found"
24+
fi
25+
26+
# ReFrame prints e.g.
27+
#[----------] start processing checks
28+
#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:rome+default
29+
#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:genoa+default
30+
#[ RUN ] GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=1_cpn_2_nodes %module_name=GROMACS/2021.3-foss-2021a /f4194106 @snellius:genoa+default
31+
#[ FAIL ] (1/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:genoa+default
32+
#==> test failed during 'sanity': test staged in '/scratch-shared/casparl/reframe_output/staging/snellius/genoa/default/GROMACS_EESSI_d597cff4'
33+
#[ OK ] (2/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=2_nodes %module_name=GROMACS/2021.3-foss-2021a /d597cff4 @snellius:rome+default
34+
#P: perf: 8.441 ns/day (r:0, l:None, u:None)
35+
#[ FAIL ] (3/3) GROMACS_EESSI %benchmark_info=HECBioSim/Crambin %nb_impl=cpu %scale=1_cpn_2_nodes %module_name=GROMACS/2021.3-foss-2021a /f4194106 @snellius:genoa+default
36+
#==> test failed during 'sanity': test staged in '/scratch-shared/casparl/reframe_output/staging/snellius/genoa/default/GROMACS_EESSI_f4194106'
37+
#[----------] all spawned checks have finished
38+
#[ FAILED ] Ran 3/3 test case(s) from 2 check(s) (2 failure(s), 0 skipped, 0 aborted)
39+
40+
# We will grep for the last and final line, since this reflects the overall result
41+
# Specifically, we grep for FAILED, since this is also what we print if a step in the test script itself fails
42+
FAILED=-1
43+
if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then
44+
GP_failed='\[\s*FAILED\s*\].*Ran .* test case'
45+
grep_reframe_failed=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_failed}")
46+
[[ $? -eq 0 ]] && FAILED=1 || FAILED=0
47+
# have to be careful to not add searched for pattern into slurm out file
48+
[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_failed}"'"
49+
[[ ${VERBOSE} -ne 0 ]] && echo "${grep_reframe_failed}"
50+
fi
51+
52+
# Here, we grep for 'ERROR:', which is printed if a fatal_error is encountered when executing the test step
53+
# I.e. this is an error in execution of the run_tests.sh itself, NOT in running the actual tests
54+
ERROR=-1
55+
if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then
56+
GP_error='ERROR: '
57+
grep_out=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_error}")
58+
[[ $? -eq 0 ]] && ERROR=1 || ERROR=0
59+
# have to be careful to not add searched for pattern into slurm out file
60+
[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_error}"'"
61+
[[ ${VERBOSE} -ne 0 ]] && echo "${grep_out}"
62+
fi
63+
64+
SUCCESS=-1
65+
# Grep for the success pattern, so we can report the amount of tests run
66+
if [[ ${SLURM_OUTPUT_FOUND} -eq 1 ]]; then
67+
GP_success='\[\s*PASSED\s*\].*Ran .* test case'
68+
grep_reframe_success=$(grep -v "^>> searching for " ${job_dir}/${job_out} | grep "${GP_success}")
69+
[[ $? -eq 0 ]] && SUCCESS=1 || SUCCESS=0
70+
# have to be careful to not add searched for pattern into slurm out file
71+
[[ ${VERBOSE} -ne 0 ]] && echo ">> searching for '"${GP_success}"'"
72+
[[ ${VERBOSE} -ne 0 ]] && echo "${grep_reframe_success}"
73+
fi
74+
75+
if [[ ! -z ${grep_reframe_failed} ]]; then
76+
grep_reframe_result=${grep_reframe_failed}
77+
else
78+
# Grep the entire output of ReFrame, so that we can report it in the foldable section of the test report
79+
GP_success_full='(?s)\[----------\] start processing checks.*?\[==========\] Finished on [a-zA-Z0-9 ]*'
80+
# Grab the full ReFrame report, than cut the irrelevant parts
81+
# Note that the character limit for messages in github is around 65k, so cutting is important
82+
grep_reframe_success_full=$( \
83+
grep -v "^>> searching for " ${job_dir}/${job_out} | \
84+
# Use -z
85+
grep -Pzo "${GP_success_full}" | \
86+
# Replace null character with newline, to undo the -z option
87+
sed 's/\x00/\n/g' | \
88+
# Remove the [ RUN ] lines from reframe, they are not very informative
89+
grep -v -P '\[\s*RUN\s*]' | \
90+
# Remove the line '[----------] all spawned checks have finished'
91+
grep -v '\[-*\]' | \
92+
# Remove the line '[==========] Finished on Mon Oct 7 21'
93+
grep -v '\[=*\]' | \
94+
# Remove blank line(s) from the report
95+
grep -v '^$' | \
96+
# Remove warnings about the local spawner not supporting memory requests
97+
grep -v 'WARNING\: hooks\.req_memory_per_node does not support the scheduler you configured .local.*$' | \
98+
# Strip color coding characters
99+
sed 's/\x1B\[[0-9;]*m//g' | \
100+
# Replace all newline characters with <br/>
101+
sed ':a;N;$!ba;s/\n/<br\/>/g' | \
102+
# Replace % with %%. Use \%\% to interpret both %% as (non-special) characters
103+
sed 's/\%/\%\%/g' \
104+
)
105+
# TODO (optional): we could impose a character limit here, and truncate if too long
106+
# (though we should do that before inserting the <br/> statements).
107+
# If we do, we should probably re-append the final summary, e.g.
108+
# [ PASSED ] Ran 10/10 test case(s) from 10 check(s) (0 failure(s), 0 skipped, 0 aborted)
109+
# so that that is always displayed
110+
# However, that's not implemented yet - let's see if this ever even becomes an issue
111+
grep_reframe_result=${grep_reframe_success_full}
112+
fi
113+
echo "grep_reframe_result: ${grep_reframe_result}"
114+
115+
echo "[TEST]" > ${job_test_result_file}
116+
if [[ ${SLURM_OUTPUT_FOUND} -eq 0 ]]; then
117+
summary=":cry: FAILURE"
118+
reason="Job output file not found, cannot check test results."
119+
status="FAILURE"
120+
# Should come before general errors: if SUCCESS==1, it indicates the test suite ran succesfully
121+
# regardless of other things that might have gone wrong
122+
elif [[ ${SUCCESS} -eq 1 ]]; then
123+
summary=":grin: SUCCESS"
124+
reason=""
125+
status="SUCCESS"
126+
# Should come before general errors: if FAILED==1, it indicates the test suite ran
127+
# otherwise the pattern wouldn't have been there
128+
elif [[ ${FAILED} -eq 1 ]]; then
129+
summary=":cry: FAILURE"
130+
reason="EESSI test suite produced failures."
131+
status="FAILURE"
132+
elif [[ ${ERROR} -eq 1 ]]; then
133+
summary=":cry: FAILURE"
134+
reason="EESSI test suite was not run, test step itself failed to execute."
135+
status="FAILURE"
136+
else
137+
summary=":cry: FAILURE"
138+
reason="Failed for unknown reason"
139+
status="FAILURE"
140+
fi
141+
142+
143+
echo "[TEST]" > ${job_test_result_file}
144+
echo -n "comment_description = " >> ${job_test_result_file}
145+
146+
# Use template for writing PR comment with details
147+
# construct and write complete PR comment details: implements third alternative
148+
comment_template="<details>__SUMMARY_FMT__<dl>__REASON_FMT____REFRAME_FMT____DETAILS_FMT__</dl></details>"
149+
comment_success_item_fmt=":white_check_mark: __ITEM__"
150+
comment_failure_item_fmt=":x: __ITEM__"
151+
152+
# Initialize comment_description
153+
comment_description=${comment_template}
154+
155+
# Now, start replacing template items one by one
156+
comment_summary_fmt="<summary>__SUMMARY__ _(click triangle for details)_</summary>"
157+
comment_summary="${comment_summary_fmt/__SUMMARY__/${summary}}"
158+
comment_description=${comment_description/__SUMMARY_FMT__/${comment_summary}}
159+
160+
161+
# Only add if there is a reason (e.g. no reason for successful runs)
162+
if [[ ! -z ${reason} ]]; then
163+
comment_reason_fmt="<dt>_Reason_</dt><dd>__REASONS__</dd>"
164+
reason_details="${comment_reason_fmt/__REASONS__/${reason}}"
165+
comment_description=${comment_description/__REASON_FMT__/${reason_details}}
166+
else
167+
comment_description=${comment_description/__REASON_FMT__/""}
168+
fi
169+
170+
# Only add if there is a reframe summary (e.g. no reframe summary if reframe wasn't launched succesfully)
171+
echo "ReFrame result:"
172+
echo "${grep_reframe_result}"
173+
if [[ ! -z ${grep_reframe_result} ]]; then
174+
comment_reframe_fmt="<dt>_ReFrame Summary_</dt><dd>__REFRAME_SUMMARY__</dd>"
175+
reframe_summary=${comment_reframe_fmt/__REFRAME_SUMMARY__/${grep_reframe_result}}
176+
comment_description=${comment_description/__REFRAME_FMT__/${reframe_summary}}
177+
else
178+
comment_description=${comment_description/__REFRAME_FMT__/""}
179+
fi
180+
181+
# Declare functions
182+
function print_br_item() {
183+
format="${1}"
184+
item="${2}"
185+
echo -n "${format//__ITEM__/${item}}<br/>"
186+
}
187+
188+
function success() {
189+
format="${comment_success_item_fmt}"
190+
item="$1"
191+
print_br_item "${format}" "${item}"
192+
}
193+
194+
function failure() {
195+
format="${comment_failure_item_fmt}"
196+
item="$1"
197+
print_br_item "${format}" "${item}"
198+
}
199+
200+
function add_detail() {
201+
actual=${1}
202+
expected=${2}
203+
success_msg="${3}"
204+
failure_msg="${4}"
205+
if [[ ${actual} -eq ${expected} ]]; then
206+
success "${success_msg}"
207+
else
208+
failure "${failure_msg}"
209+
fi
210+
}
211+
212+
# first construct comment_details_list, abbreviated comment_details_list
213+
# then use it to set comment_details
214+
comment_details_list=""
215+
216+
success_msg="job output file <code>${job_out}</code>"
217+
failure_msg="no job output file <code>${job_out}</code>"
218+
comment_details_list=${comment_details_list}$(add_detail ${SLURM_OUTPUT_FOUND} 1 "${success_msg}" "${failure_msg}")
219+
220+
success_msg="no message matching <code>${GP_error}</code>"
221+
failure_msg="found message matching <code>${GP_error}</code>"
222+
comment_details_list=${comment_details_list}$(add_detail ${ERROR} 0 "${success_msg}" "${failure_msg}")
223+
224+
# Add an escape character to every *, for it to be printed correctly in the comment on GitHub
225+
GP_failed="${GP_failed//\*/\\*}"
226+
success_msg="no message matching <code>""${GP_failed}""</code>"
227+
failure_msg="found message matching <code>""${GP_failed}""</code>"
228+
comment_details_list=${comment_details_list}$(add_detail ${FAILED} 0 "${success_msg}" "${failure_msg}")
229+
230+
comment_details_fmt="<dt>_Details_</dt><dd>__DETAILS_LIST__</dd>"
231+
comment_details="${comment_details_fmt/__DETAILS_LIST__/${comment_details_list}}"
232+
comment_description=${comment_description/__DETAILS_FMT__/${comment_details}}
233+
234+
# Actually writing the comment description to the result file
235+
echo "${comment_description}" >> ${job_test_result_file}
236+
echo "status = ${status}" >> ${job_test_result_file}
237+
238+
exit 0

0 commit comments

Comments
 (0)