ci_regression_test_dunetpc.sh
Go to the documentation of this file.
1 #!/usr/bin/env bash
2 
3 
4 function usage {
5  cat <<EOF
6  usage: $0 [options]
7  running CI tests for ${proj_PREFIX}_ci.
8  options:
9  --executable Define the executable to run
10  --nevents Define the number of events to process
11  --stage Define the stage number used to parse the right testmask column number
12  --fhicl Set the FHiCl file to use to run the test
13  --input-file Set the file on which you want to run the test
14  --reference-files Set the reference file used by the test, this can be a comma separated list
15  --outputs Define a list of pairs <output_stream>:<output_filename> using "," as separator
16  --stage-name Define the name of the test
17  --testmask Define the bit-mask to enable the different test phases
18  (currently there are 3 test phases: data_production; compare_data_products; compare_data_product_size.)
19  --update-ref-files Flag to activate the "Update Reference Files" mode
20  --input-files-to-fetch List of input files to be downloaded before to execute the data production
21  --reference-files-to-fetch List of reference files to be downloaded before the product comparison
22  --extra-function Define and extra function to run with list of required arguments; the elements need to be comma separated
23  --extra-options Define and extra options/arguments for the executable; the elements need to be comma separated
24 EOF
25 }
26 
27 function initialize
28 {
29  TASKSTRING="initialize"
30  ERRORSTRING="F~Error initializing the test~Check the log"
31  trap 'LASTERR=$?; FUNCTION_NAME=${FUNCNAME[0]:-main}; exitstatus ${LASTERR} trap ${LINENO}; exit ${LASTERR}' ERR
32 
33  echo "running CI tests for ${proj_PREFIX}_ci."
34  echo "ci_cur_exp_name: ${ci_cur_exp_name}"
35  echo
36  echo "initialize $@"
37 
38  #~~~~~~~~~~~~~~~ DEFAULT VALUES ~~~~~~~~~~~~~~~~
39  EXECUTABLE_NAME=no_executable_defined
40  NEVENTS=1
41  UPDATE_REF_FILE_ON=0
42  INPUT_FILE=""
43  INPUT_FILES_TO_FETCH=""
44  REFERENCE_FILES=""
45  REFERENCE_FILES_TO_FETCH=""
46  WORKSPACE=${WORKSPACE:-$PWD}
47  EXTRA_OPTIONS=""
48  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 
50  #~~~~~~~~~~~~~~~~~~~~~~GET VALUE FROM THE CI_TESTS.CFG ARGS SECTION~~~~~~~~~~~~~~~
51  while :
52  do
53  case "x$1" in
54  x-h|x--help) usage; exit;;
55  x--executable) EXECUTABLE_NAME="${2//,/ }"; shift; shift;;
56  x--nevents) NEVENTS="${2}"; shift; shift;;
57  x--stage) STAGE="${2}"; shift; shift;;
58  x--fhicl) FHiCL_FILE="${2}"; shift; shift;;
59  x--input-file) INPUT_FILE="${2}"; shift; shift;;
60  x--reference-files) REFERENCE_FILES="${2}"; shift; shift;;
61  x--outputs) OUTPUT_LIST="${2}"; OUTPUT_STREAM="${OUTPUT_LIST//,/ -o }"; shift; shift;;
62  x--stage-name) STAGE_NAME="${2}"; shift; shift;;
63  x--testmask) TESTMASK="${2}"; shift; shift;;
64  x--update-ref-files) UPDATE_REF_FILE_ON=1; shift;;
65  x--input-files-to-fetch) INPUT_FILES_TO_FETCH="${2}"; shift; shift;;
66  x--reference-files-to-fetch) REFERENCE_FILES_TO_FETCH="${2}"; shift; shift;;
67  x--extra-function) EXTRA_FUNCTION="${2}"; shift; shift;;
68  x--extra-options) EXTRA_OPTIONS="${2//,/ }"; shift; shift;;
69  x) break;;
70  x*) echo "Unknown argument $1"; usage; exit 1;;
71  esac
72  done
73 
74  if [ ${UPDATE_REF_FILE_ON} -gt 0 ]; then
75  echo -e "\n***************************************************"
76  echo "This CI build is running to update reference files:"
77  echo "- data product comparison is disabled"
78  echo "- number of events is set to 1"
79  echo "- existing reference files will not be used"
80  echo -e "***************************************************\n"
81  TESTMASK=""
82  if [[ "$(basename ${0})" != *"lariatsoft"* ]]; then
83  NEVENTS=1
84  fi
85  REFERENCE_FILES=""
86  REFERENCE_FILES_TO_FETCH=""
87  fi
88 
89  if [ -n "${INPUT_FILES_TO_FETCH}" ]; then
90  fetch_files input ${INPUT_FILES_TO_FETCH}
91  fi
92  if [ -n "${REFERENCE_FILES_TO_FETCH}" ]; then
93  fetch_files reference ${REFERENCE_FILES_TO_FETCH}
94  fi
95 
96  #~~~~~~~~~~~~~~~~~~~~~PARSE THE TESTMASK FILE TO UNDERSTAND WHICH FUNCTION TO RUN ~~~~~~~~~~~~
97  if [ -n "${TESTMASK}" ];then
98  check_data_production=${TESTMASK:0:1}
99  check_compare_names=$((${TESTMASK:1:1}&&${check_data_production}))
100  check_compare_size=$((${TESTMASK:2:1}&&${check_compare_names}))
101  else
102  check_data_production=1
103  check_compare_names=0
104  check_compare_size=0
105  fi
106 
107  echo "Input file: ${INPUT_FILE}"
108  echo "Output files: ${OUTPUT_LIST}"
109  echo "FHiCL file: ${FHiCL_FILE}"
110  echo "Testmask: ${TESTMASK}"
111  echo
112  echo -e "\nRunning\n `basename $0` $@"
113 
114  exitstatus $?
115 }
116 
117 
118 function fetch_files
119 {
120  old_taskstring="$TASKSTRING"
121  old_errorstring="$ERRORSTRING"
122  TASKSTRING="fetching $1 files"
123 
124  ERRORSTRING="F~Error in fetching $1 files~Check if the $1 files are available"
125 
126  echo "fetching $1 files for ${proj_PREFIX}_ci."
127  echo
128  echo "fetch_files $@"
129  echo
130 
131  maxretries_backup=$IFDH_CP_MAXRETRIES
132  debug_backup=$IFDH_DEBUG
133 
134  export IFDH_DEBUG=1
135  export IFDH_CP_MAXRETRIES=0
136 
137  for file in ${2//,/ }
138  do
139  echo "Command: ifdh cp -D $file ./"
140  ifdh cp -D $file ./ > fetch_inputs.log 2>&1
141  local copy_exit_code=$?
142 
143  if [[ $copy_exit_code -ne 0 ]]; then
144  echo "Failed to fetch $file"
145  exitstatus 211
146  fi
147  done
148 
149  export IFDH_DEBUG=$debug_backup
150  export IFDH_CP_MAXRETRIES=$maxretries_backup
151  exitstatus $copy_exit_code
152  TASKSTRING="$old_taskstring"
153  ERRORSTRING="$old_errorstring"
154 }
155 
156 
157 function data_production
158 {
159  TASKSTRING="data_production"
160  ERRORSTRING="F~Error in data production~Check the log"
161  trap 'LASTERR=$?; FUNCTION_NAME=${FUNCNAME[0]:-main}; exitstatus ${LASTERR} trap ${LINENO}; exit ${LASTERR}' ERR
162 
163  export TMPDIR=${PWD} #Temporary directory used by IFDHC
164 
165  #~~~~~~~~~~~~~IF THE TESTMASK VALUE IS SET TO 1 THEN RUN THE PRODUCTION OF THR DATA~~~~~~~~~~~~~~~~~~
166  if [[ "${1}" -eq 1 ]]
167  then
168  # This is LArIAT specific.
169  # The slicer stage has output filename in the form file_%#.root
170  if [[ "${STAGE_NAME}" == "slicer" && "$(basename ${0})" == *"lariatsoft"* ]]; then # This is LArIAT specific.
171  OUTPUT_STREAM=${OUTPUT_STREAM//.root/_%#.root}
172  fi
173 
174  echo -e "\nNumber of events for ${STAGE_NAME} stage: $NEVENTS\n"
175  echo ${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} ${EXTRA_OPTIONS} ${OUTPUT_STREAM:+-o "$OUTPUT_STREAM"} --config ${FHiCL_FILE} ${INPUT_FILE}
176  echo
177 
178  (
179  local counter=0
180  local expcode_exitcode=20
181  until [[ ${expcode_exitcode} -ne 20 || ${counter} -gt 5 ]]; do
182  /usr/bin/time ${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} ${EXTRA_OPTIONS} ${OUTPUT_STREAM:+-o "$OUTPUT_STREAM"} --config ${FHiCL_FILE} ${INPUT_FILE}
183  expcode_exitcode=$?
184  (>&2 echo "TIME SIGNATURE" )
185  if [[ ${expcode_exitcode} -eq 20 ]]; then
186  let $((counter++))
187  echo -e "\n\n*** ${EXECUTABLE_NAME} can not access the input file, wait 30 s, then retry #${counter}\n\n"
188  sleep 30
189  fi
190  done
191  exit $expcode_exitcode
192  )
193 
194  else
195  echo -e "\nCI MSG BEGIN\n Stage: ${STAGE_NAME}\n Task: ${TASKSTRING}\n skipped\nCI MSG END\n"
196  fi
197  exitstatus $?
198 
199  # This is uBooNE specific.
200  # The mergeana stage doesn't produce an artRoot file,
201  # but the CI expect to have it.
202  if [[ "${STAGE_NAME}" == "mergeana" && "$(basename ${0})" == *"uboonecode"* ]]; then
203  for CUR_OUT in ${OUTPUT_STREAM//-o/}; do
204  touch ${CUR_OUT}
205  done
206  fi
207 
208  # This is LArIAT specific.
209  # The slicer stage has output filename in the form file_%#.root
210  if [[ "${OUTPUT_STREAM}" == *"_%#"* && "${STAGE_NAME}" == "slicer" && "$(basename ${0})" == *"lariatsoft"* ]]; then
211 
212  for CUR_OUT in ${OUTPUT_STREAM//-o/} # this is LArIAT specific
213  do
214  CUR_OUT=${CUR_OUT//*:/}
215  CUR_OUT2=$(echo $CUR_OUT | sed -e "s/_%#// ; s/_1.root/.root/")
216  ln -fv ${CUR_OUT//_%#.root/_1.root} ${CUR_OUT2} && rm ${CUR_OUT//_%#.root/_1.root}
217  done
218  fi
219 
220 }
221 
222 function generate_data_dump
223 {
224  TASKSTRING="generate_data_dump for ${file_stream} output stream"
225  ERRORSTRING="W~Error during dump Generation~Check the log"
226 
227  trap 'LASTERR=$?; FUNCTION_NAME=${FUNCNAME[0]:-main}; exitstatus ${LASTERR} trap ${LINENO}; exit ${LASTERR}' ERR
228 
229 # local NEVENTS=1
230 
231  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PRINT THE COMMAND TO LOG AND THEN GENERATE THE DUMP FOR THE REFERENCE FILE ~~~~~~~~~~~~~~~~~~~
232  echo -e "\nGenerating Dump for ${reference_file}"
233  REF_DUMP_FILE=$(basename ${reference_file} | sed -e 's/.root/.dump/')
234  echo "${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} --config eventdump.fcl ${reference_file} 2>&1 | tee ${REF_DUMP_FILE}"
235 
236  (
237  set -o pipefail
238 
239  local counter=0
240  local expcode_exitcode=20
241  until [[ ${expcode_exitcode} -ne 20 || ${counter} -gt 5 ]]; do
242  ${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} --config eventdump.fcl "${reference_file}" 2>&1 | tee ${REF_DUMP_FILE}
243  expcode_exitcode=$?
244  if [[ ${expcode_exitcode} -eq 20 ]]; then
245  let $((counter++))
246  echo -e "\n\n*** ${EXECUTABLE_NAME} can not access the input file, wait 30 s, then retry #${counter}\n\n"
247  sleep 30
248  fi
249  done
250  exit ${expcode_exitcode}
251  )
252 
253  #~~~~~~~~~~~~~~~~~~~~~~~~~SAVE IN A VARIABLE THE PARSED REFERENCE DUMP FILE ~~~~~~~~~~~~~~~~~~~~~~
254  OUTPUT_REFERENCE=$(cat "${REF_DUMP_FILE}" | sed -e '/PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' )
255 
256  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PRINT THE COMMAND TO LOG AND THEN GENERATE THE DUMP FOR THE CURRENT FILE ~~~~~~~~~~~~~~~~~~~
257  echo -e "\nGenerating Dump for ${current_file}"
258  echo "${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} --config eventdump.fcl ${current_file} 2>&1 | tee ${current_file//.root}.dump"
259 
260  (
261  set -o pipefail
262 
263  local counter=0
264  local expcode_exitcode=20
265  until [[ ${expcode_exitcode} -ne 20 || ${counter} -gt 5 ]]; do
266  ${EXECUTABLE_NAME} --rethrow-all -n ${NEVENTS} --config eventdump.fcl "${current_file}" 2>&1 | tee "${current_file//.root}".dump
267  expcode_exitcode=$?
268  if [[ ${expcode_exitcode} -eq 20 ]]; then
269  let $((counter++))
270  echo -e "\n\n*** ${EXECUTABLE_NAME} can not access the input file, wait 30 s, then retry #${counter}\n\n"
271  sleep 30
272  fi
273  done
274  exit ${expcode_exitcode}
275  )
276  #~~~~~~~~~~~~~~~~~~~~~~~~~SAVE IN A VARIABLE THE PARSED CURRENT DUMP FILE ~~~~~~~~~~~~~~~~~~~~~~
277  OUTPUT_CURRENT=$(cat "${current_file//.root}".dump | sed -e '/PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' )
278 
279  echo -e "\nReference files for ${file_stream} output stream:"
280  echo -e "\n${REF_DUMP_FILE}\n"
281  echo "$OUTPUT_REFERENCE"
282  echo -e "\nCurrent files for ${file_stream} output stream:"
283  echo -e "\n${current_file//.root}.dump\n"
284  echo "$OUTPUT_CURRENT"
285 
286  exitstatus $?
287 }
288 
289 function compare_products_names
290 {
291  TASKSTRING="compare_products_names for ${file_stream} output stream"
292  ERRORSTRING="W~Error comparing products names~check the log"
293 
294  if [[ "$1" -eq 1 ]]
295  then
296  REF_DUMP_FILE=$(basename ${reference_file} | sed -e 's/.root/.dump/')
297  echo -e "\nCompare products names for ${file_stream} output stream."
298  #~~~~~~~~~~~~~~~~CHECK IF THERE'S A DIFFERENCE BEETWEEN THE TWO DUMP FILES IN THE FIRST FOUR COLUMNS~~~~~~~~~~~~~~
299  DIFF=$(diff <(sed 's/\.//g ; /PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' ${REF_DUMP_FILE} | cut -d "|" -f -4 ) <(sed 's/\.//g ; /PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' ${current_file//.root/.dump} | cut -d "|" -f -4 ) )
300  STATUS=$?
301 
302  echo -e "\nCheck for added/removed data products"
303  echo -e "difference(s)\n"
304  #~~~~~~~~~~~~~~~IF THERE'S A DIFFERENCE EXIT WITH ERROR CODE 201~~~~~~~~~~~~~~~
305  if [[ "${STATUS}" -ne 0 ]]; then
306  echo "${DIFF}"
307  ERRORSTRING="W~Differences in products names~Request new reference files"
308  exitstatus 201 defer
309  else
310  echo -e "none\n\n"
311  fi
312  else
313  echo -e "\nCI MSG BEGIN\n Stage: ${STAGE_NAME}\n Task: ${TASKSTRING}\n skipped\nCI MSG END\n"
314  exitstatus $?
315  fi
316 }
317 
318 function compare_products_sizes
319 {
320  TASKSTRING="compare_products_sizes for ${file_stream} output stream"
321  ERRORSTRING="W~Error comparing product sizes~Check the log"
322 
323 
324  if [[ "${1}" -eq 1 ]]
325  then
326 
327  REF_DUMP_FILE=$(basename ${reference_file} | sed -e 's/.root/.dump/')
328  echo -e "\nCompare products sizes for ${file_stream} output stream.\n"
329  #~~~~~~~~~~~~~~~~CHECK IF THERE'S A DIFFERENCE BEETWEEN THE TWO DUMP FILES,IN ALL THE COLUMNS~~~~~~~~~~~~~~
330  DIFF=$(diff <(sed 's/\.//g ; /PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' ${REF_DUMP_FILE}) <(sed 's/\.//g ; /PRINCIPAL TYPE:/,/^\s*$/!d ; s/PRINCIPAL TYPE:.*$// ; /^\s*$/d' ${current_file//.root/.dump}) )
331  STATUS=$?
332  echo -e "\nCheck for differences in the size of data products"
333  echo -e "difference(s)\n"
334 
335  #~~~~~~~~~~~~~~~IF THERE'S A DIFFERENCE EXIT WITH ERROR CODE 202 ~~~~~~~~~~~~~~~~~~~~~~~
336  if [[ "${STATUS}" -ne 0 ]]; then
337  echo "${DIFF}"
338  ERRORSTRING="W~Differences in products sizes~Request new reference files"
339  exitstatus 202
340  else
341  echo -e "none\n\n"
342  fi
343  else
344  echo -e "\nCI MSG BEGIN\n Stage: ${STAGE_NAME}\n Task: ${TASKSTRING}\n skipped\nCI MSG END\n"
345  exitstatus $?
346  fi
347 }
348 
349 
350 #~~~~~~~~~~~~~~~~~~~~~~~PRINT AN ERROR MESSAGE IN THE PROGRAM EXIT WITH AN ERROR CODE~~~~~~~~~~~~~~~~
351 function exitstatus
352 {
353  EXITSTATUS="$1"
354  if [ "$2" == "trap" ];then
355  echo -e "\nCI MSG BEGIN\n Script: `basename $0`\n Function: ${FUNCTION_NAME} - error at line ${3}\n Stage: ${STAGE_NAME}\n Task: ${TASKSTRING}\n exit status: $EXITSTATUS\nCI MSG END\n"
356  else
357  echo -e "\nCI MSG BEGIN\n Stage: ${STAGE_NAME}\n Task: ${TASKSTRING}\n exit status: ${EXITSTATUS}\nCI MSG END\n"
358  fi
359  #don't exit if the fetch of the reference failed,because we need to produce one and then upload it
360  if [[ "${EXITSTATUS}" -ne 0 ]]; then
361  if [[ -n "$ERRORSTRING" ]];then
362  echo "`basename $PWD`~${EXITSTATUS}~$ERRORSTRING" >> $WORKSPACE/data_production_stats${ci_cur_exp_name}.log
363  fi
364  if [ "$2" == "defer" ];then
365  PREVSTATUS=${EXITSTATUS}
366  else
367  exit "${EXITSTATUS}"
368  fi
369  fi
370  if [[ -n "${PREVSTATUS}" && "$2" != "defer" ]]; then
371  exit "${PREVSTATUS}"
372  fi
373 }
374 
375 
376 #~~~~~~~~~~~~~~~~~~~~~~~EXTRA FUNCTIONS TO RUN SPECIAL TESTS~~~~~~~~~~~~~~~~
377 function compare_anatree
378 {
379 
380  source ${GENERIC_CI_DIR}/bin/reporter_functions.sh
381 
382  THISCIDIR=$(eval "echo \${${PROJ_PREFIX}_CI_DIR}")
383 
384  root -l -b -q ${THISCIDIR}/test/compare_anatree.C\(\"${1}\",\"${2}\"\)
385 
386 
387 
388  if [ -n "${BUILD_ID}" ] # not in a jenkins build, don't send plots to CI web app
389  then
390  BASE_JOB=`echo $JOB_NAME | sed -e 's;/.*;;' -e 's/_jenkins.*//'`
391  export report_fullname="${BASE_JOB}/${BUILD_NUMBER}"
392  export report_serverurl="${HUDSON_URL}"
393 
394  for f in *.gif
395  do
396  bf=`basename $f`
397  hist_desc="${bf//.gif/} plot"
398  hist_name="${bf//.gif/}"
399  report_img "ci_tests" "${ci_cur_exp_name}" "" "$(basename $PWD)" "$hist_name" "$f" "$hist_desc"
400  # report_img "ci_tests" "" "end" "$hist_name" "$f" "$hist_desc"
401  done
402 
403  fi
404 
405 }
406 
407 
408 #~~~~~~~~~~~~~~~~~~~~~~~~MAIN OF THE SCRIPT~~~~~~~~~~~~~~~~~~
409 trap 'LASTERR=$?; FUNCTION_NAME=${FUNCNAME[0]:-main}; exitstatus ${LASTERR} trap ${LINENO}; exit ${LASTERR}' ERR
410 
411 initialize $@
412 
413 data_production "${check_data_production}"
414 
415 #~~~~~~~~~~~~~~~~PROCESS ALL THE FILES DECLARED INTO THE OUTPUT LIST~~~~~~~~~~~~~~~~~
416 for filename in ${OUTPUT_LIST//,/ }
417 do
418  file_stream=$(echo "${filename}" | cut -d ':' -f 1)
419  current_file=$(echo "${filename}" | cut -d ':' -f 2)
420 
421  echo "filename: ${filename}"
422  echo "file_stream: ${file_stream}"
423  echo "current_file: ${current_file}"
424 
425  reference_file=""
426  if [[ "${REFERENCE_FILES}" = *"xroot"* ]]; then
427  for temp_file in ${REFERENCE_FILES//,/ }
428  do
429  if [[ "${temp_file}" = *"${current_file//Current/Reference}"* ]]; then
430  reference_file=${temp_file}
431  fi
432  done
433 
434  ### XROOTD_PATH=$(echo "${reference_file}" | sed -e 's#\(^.*\)/'${STAGE_NAME}'/.*#\1/'${STAGE_NAME}/'#')
435 
436  else
437  ### if [ -n "${build_platform}" ]; then
438  ### reference_file=$(echo "${current_file%`echo ${build_platform}`*}${build_platform}${current_file#*`echo ${build_platform}`}")
439  ### else
440  ### reference_file=$(echo "${current_file}")
441  ### fi
442  ### reference_file="${reference_file//Current/Reference}"
443  reference_file="${current_file//Current/Reference}"
444  [[ -n "$build_identifier" ]] && reference_file="$(sed -e 's#'${build_identifier}'##' <<< "$reference_file" )"
445  fi
446 
447  if [[ "${check_compare_names}" -eq 1 || "${check_compare_size}" -eq 1 ]]; then
448  generate_data_dump
449  else
450  break
451  fi
452 
453  compare_products_names "${check_compare_names}"
454 
455  compare_products_sizes "${check_compare_size}"
456 
457  if [[ -n ${PREVSTATE} ]]; then
458  exit ${PREVSTATE}
459  fi
460 
461 done
462 
463 #~~~~~~~~~~~~~~~~RUN EXTRA FUNCTION~~~~~~~~~~~~~~~~~
464 if [ -n "${EXTRA_FUNCTION}" ]; then
465  ${EXTRA_FUNCTION//,/ }
466 fi