1#!/usr/bin/env bash
2#########################################################################
3#
4# Shell script for running DALTON tests
5#
6# First version by Christof Haettig and Kasper Hald, Sep. 2000
7#
8#########################################################################
9
10# Note: $DALTON points to the default "DALTON/build/dalton" script.
11#       If another name than "build" has been chosen for the build directory,
12#       then you should modify the BUILD_DIR defintion to point to that place.
13
14BUILD_DIR="../../build"
15
16# radovan: this is to figure out the location of this script
17# http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
18SOURCE="${BASH_SOURCE[0]}"
19while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
20    SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
21    SOURCE="$(readlink "$SOURCE")"
22    # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
23    [[ $SOURCE != /* ]] && SOURCE="$SCRIPT_DIR/$SOURCE"
24done
25SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
26cd $SCRIPT_DIR
27
28if [ -x '/usr/bin/time' ]; then
29 TIMING_OF="/usr/bin/time" #hjaaj sep07: gnu time gives more info than built-in time
30else
31 TIMING_OF=" "
32fi
33if [ -x "$BUILD_DIR/dalton" ]; then
34  DALTON="`pwd`/$BUILD_DIR/dalton"
35else
36  DALTON=NON_DEFAULT
37fi
38
39#########################################################################
40# function usage(): print usage information
41#########################################################################
42usage() {
43 cat <<%EOF%
44Usage: $0 [-h|-help|--help] [-keep] [-reftest] [-benchmark]
45            [-param "option list"] [-dalton script] [-log logfile] testcase
46
47       -h | -help | --help    : show this help description
48       -keep                  : keep *.mol, *.dal, *.check and *.log files
49       -reftest               : test reference file(s); do not run any calculations
50       -benchmark             : print CPU time for each testcase as part of the summary
51       -param "option list"   : pass "option list" to dalton-script
52       -dalton script         : use "script" instead of the default
53                                dalton-script "`pwd`/../../build/dalton" (absolute path)
54       -log logfile           : write output into logfile instead of to "DALTON_TESTLOG"
55       -result-directory path : change default result directory to path
56%EOF%
57exit 1
58}
59
60#########################################################################
61# function myprint(string): print to stdout and $listing
62#########################################################################
63myprint(){
64 echo "$1";
65 echo "$1" >> $listing;
66}
67
68errprint(){
69 echo "$1" >> /dev/stderr;
70}
71
72#########################################################################
73#########################################################################
74# start with real work:
75#########################################################################
76#########################################################################
77
78#########################################################################
79# set defaults and evaluate parameters
80#########################################################################
81TESTparams="$0 $*"
82help=""
83if [ -n "$KEEP_TEST_OUTPUTS" ]; then
84    keep="true"
85else
86    keep="false"
87fi
88paramlist=""
89par_paramlist="-N 4"
90reftest=""
91benchmark=""
92listing="DALTON_TESTLOG"
93emptystring="                                "
94keep_quiet=
95result_directory=''
96
97tmpfile=/tmp/dalton-$$.log
98touch "$tmpfile"   || { echo "cannot create temporary file. Aborting execution."; exit 1; }
99test -f "$tmpfile" || { echo "Possible security breach related to temporary file."; exit 1; }
100
101if [ `uname` = Linux ]; then
102   GREP="egrep -a"
103else
104   GREP="egrep"
105fi
106
107while echo $1 | egrep -q '^-'; do
108   case $1 in
109     "-h" | "-help" | "--help" ) help="true" ; break;;
110     "-dalton" )  shift; DALTON=$1; shift;;
111     "-log" ) shift; listing=$1; shift;;
112     "-result-directory" ) shift; result_directory=$1; shift;;
113     "-keep" ) keep="true"; shift;;
114     -param* ) shift; paramlist="$1"; shift;;
115     "-reftest" ) reftest="true"; shift;;
116     "-q") keep_quiet=true; shift;;
117     "-benchmark" ) benchmark="true"; shift;;
118     * ) echo "---> ERROR: $1 is an unknown option!"; usage;;
119   esac
120done
121if [ $help ]; then
122  usage
123fi
124
125if [ "${DALTON:0:1}" != "/" ]; then
126  DALTON="$PWD/$DALTON"   # we need absolute path, not relative path
127fi
128
129if [ ! -x $DALTON ]; then
130   echo ' '
131   echo '----> ERROR, the "dalton" job script '
132   echo    '"'$DALTON'"'
133   echo '  does not exist or is not executable.'
134   echo 'The person who installed dalton has probably selected'
135   echo '  another place for the "dalton" job script.'
136   echo 'Please modify the DALTON variable in this script (i.e. '$0')'
137   echo '  to point to that place.    Alternatively, you may'
138   echo '  specify where the dalton script is with the -dalton option'
139   echo ' '
140   exit 1
141fi
142
143#########################################################################
144# set list of test cases:
145#########################################################################
146testcase=$*
147if [ "$testcase" = "" ]; then
148  echo '    ***********************************'
149  echo '    * ERROR: No testcase(s) specified *'
150  echo '    ***********************************'
151  usage
152fi
153testcase=""
154while [ -n "$1" ]; do
155   case $1 in
156   * )
157   testcase="$testcase $1";
158   shift ;;
159   esac
160done
161
162if [ "$result_directory" = "" ]; then
163    # create a unique directory for test output
164    testdir="`date +'%Y-%m-%dT%H_%M'`-testjob-pid-$$"
165    while [ -e $testdir ]; do
166       testdir=${testdir}x
167    done
168    mkdir $testdir
169else
170    # user specifies explicit result directory
171    testdir=$result_directory
172    if [ ! -e $testdir ]; then mkdir $testdir; fi
173fi
174cp functions $testdir
175cd $testdir || exit 1
176
177myprint ""
178myprint "DALTON test           : $testcase"
179myprint "invoked with          : $TESTparams"
180myprint "date and time         : `date`"
181myprint "dalton script         : $TIMING_OF $DALTON"
182myprint "parameter list passed : $paramlist"
183myprint "test job directory    : $testdir"
184myprint "test listing          : $listing"
185
186#########################################################################
187# loop over test cases:
188#########################################################################
189passedall="ALL TESTS ENDED PROPERLY!"
190problems=""
191exitcode=0
192numresult=0
193num_reftests_not_found=0
194
195total_tests=0
196for item in ${testcase}
197do
198  total_tests=`expr $total_tests \+ 1`
199done
200
201total_failed=0
202total_tests_run=0
203
204for item in ${testcase}
205do
206  total_tests_run=`expr $total_tests_run \+ 1`
207  trouble=0
208  case $item in
209    par* | *parallel* )  # assume parallel test if name contains "parallel" or name starts with "par"
210      paramlist_this_test="$paramlist $par_paramlist"
211      shift ;;
212    * )
213      paramlist_this_test="$paramlist"
214      shift ;;
215  esac
216
217#  chmod +x $SCRIPT_DIR/$item || exit 1
218  bash $SCRIPT_DIR/$item
219# remove any directory path now the files are unpacked
220  item=`basename $item`
221  if [ -f $item.info -a "$keep_quiet" = "" ]; then
222    cat $item.info
223    cat $item.info >> $listing
224  fi
225# Check if this is a multistep job
226  numsteps=1
227  if [ -r ./$item'__'1.dal ]; then
228      multi=1
229      numsteps=`ls ./$item\_\_[0-9].dal | wc -l`
230      myprint "   This is a multi-step job consisting of $numsteps steps"
231      rm -f ./$item'__'[0-9]'_'$item.log
232      # chmod +x ./$item'__'[0-9].check
233  else
234      multi=0
235      rm -f ./$item.log
236      # chmod +x ./$item.check
237  fi
238# Multi-step tests loop over the different jobsteps, regular tests just
239# go through this once
240  step=1
241  while [ "$step" -le "$numsteps" ]
242  do
243      potfile=''
244      pcmfile=''
245      if [ "$multi" -eq 1 ]; then
246          myprint "---------------------------------------------------------------------"
247          myprint "  Start $item step $step of $numsteps :"
248          myprint "---------------------------------------------------------------------"
249          # use unique molfile for this step if available
250          if [ -r $item'__'$step.mol ]; then
251              cp -v $item'__'$step'.mol' $item'.mol'
252          fi
253          molfile=$item
254          # use unique potfile for this step if available
255          if [ -r $item'__'$step.pot ]; then
256              cp -v $item'__'$step'.pot' $item'.pot'
257          elif [ -r $item.pot ]; then
258              potfile=$item
259          fi
260          # use unique pcmfile for this step if available
261          if [ -r $item'__'$step.pcm ]; then
262              cp -v $item'__'$step'.pcm' $item'.pcm'
263          elif [ -r $item.pcm ]; then
264              pcmfile=$item
265          fi
266          cp $item'__'$step'.dal' $item'.dal'
267          dalfile=$item
268          logfile=./$item'__'$step'_'$item.log
269          checkfile=./$item'__'$step.check
270          reffile=../trueresult/$item'__'$step'_'$item.*ref
271          moldenfile=./$item'__'$step'_'$item.molden
272      else
273          molfile=$item
274          if [ -r $item.pot ]; then
275              potfile=$item
276          fi
277          if [ -r $item.pcm ]; then
278              pcmfile=$item
279          fi
280          dalfile=$item
281          logfile=./$item.log
282          checkfile=./$item.check
283          reffile=../trueresult/$item.*ref
284          moldenfile=./$item.molden
285      fi
286# If it's a reftest, no calculation is performed
287      if [ "$reftest" = "true" ]; then
288          myprint ""
289          myprint "evaluate reference output file $reffile:"
290          if [ ! -r $reffile ]; then
291              myprint "     PROBLEM: reference output $reffile is not available"
292              num_reftests_not_found=`expr $num_reftests_not_found \+ 1`
293              checkout="TEST ENDED PROPERLY"
294          else
295              checkout=`bash $checkfile $reffile`
296              if [ "$benchmark" = "true" ]; then
297                 if [ `$GREP "CPU  time used in DALTON" $reffile | wc -l` = 1 ]; then
298                     CPU_usage=`$GREP "CPU  time used in DALTON" $reffile | sed s/" Total CPU  time used in DALTON\:"/""/`
299                 else
300                     CPU_usage="N/A"
301                 fi
302              fi
303              if [ "$checkout" = "TEST ENDED AS EXPECTED" ]; then
304                 myprint "     $checkout"
305                 checkout="TEST ENDED PROPERLY"
306              fi
307          fi
308      else
309          failed=false
310          if [ "$step" -eq "1" ]; then
311#           make sure that directory is clear before start
312	        if [ -n "$potfile" ]; then
313                  $TIMING_OF $DALTON -d $paramlist_this_test -ow -ext log $dalfile $molfile $potfile > "$tmpfile"
314                  if [ $? -ne 0 ]; then failed=true; fi
315	        elif [ -n "$pcmfile" ]; then
316                  $TIMING_OF $DALTON -d $paramlist_this_test -ow -ext log $dalfile $molfile $pcmfile > "$tmpfile"
317                  if [ $? -ne 0 ]; then failed=true; fi
318	        else
319                  $TIMING_OF $DALTON -d $paramlist_this_test -ow -ext log $dalfile $molfile > "$tmpfile"
320                  if [ $? -ne 0 ]; then failed=true; fi
321	        fi
322          else
323	        if [ -n "$potfile" ]; then
324                  $TIMING_OF $DALTON -d $paramlist_this_test -f $item -ow -ext log $dalfile $molfile $potfile > "$tmpfile"
325                  if [ $? -ne 0 ]; then failed=true; fi
326	        elif [ -n "$pcmfile" ]; then
327                  $TIMING_OF $DALTON -d $paramlist_this_test -f $item -ow -ext log $dalfile $molfile $pcmfile > "$tmpfile"
328                  if [ $? -ne 0 ]; then failed=true; fi
329	        else
330                  $TIMING_OF $DALTON -d $paramlist_this_test -f $item -ow -ext log $dalfile $molfile > "$tmpfile"
331                  if [ $? -ne 0 ]; then failed=true; fi
332	        fi
333          fi
334          grep -v '\*\*\*' $tmpfile | grep -v -i 'WARNING' | grep -v -i 'INFO'| \
335          grep -v 'OUTPUT FROM' | grep -v 'Version' | grep -v 'PID' | \
336          grep -v '^$' | tee -a $listing
337
338          if [ "$multi" -eq 1 ]; then
339             cp $molfile'.log' $logfile
340          fi
341          myprint ""
342          myprint "evaluate output file $logfile:"
343
344          if [ -s "$logfile" ]; then
345              checkout=`bash $checkfile $logfile`
346          else
347              checkout="THERE IS A PROBLEM: no output was produced"
348              failed=true
349          fi
350
351          # Successful tests report "TEST ENDED PROPERLY" unless
352          # the test is meant to return non-zero exit code.  These
353          # return "TEST ENDED AS EXPECTED".  In the latter case, we
354          # change it to "TEST ENDED PROPERLY" if the exit code was
355          # nonzero, otherwise we return "DALTON SCRIPT ERROR"
356
357          if [ "$checkout" = "TEST ENDED PROPERLY" ]; then
358              [ "$failed" = "true" ] && checkout="TEST FAILED ABNORMALLY"
359          elif [ "$checkout" = "TEST ENDED AS EXPECTED" ]; then
360              myprint "     checkout=$checkout, failed=$failed"
361              if [ "$failed" = "true" ]; then
362                  checkout="TEST ENDED PROPERLY"
363              else
364                  checkout="DALTON SCRIPT ERROR"
365              fi
366          fi
367          if [ "$benchmark" = "true" ]; then
368              if [ `$GREP "CPU  time used in DALTON" $logfile | wc -l` = 1 ]; then
369                  CPU_usage=`$GREP "CPU  time used in DALTON" $logfile | sed s/" Total CPU  time used in DALTON\:"/""/`
370              else
371                  CPU_usage="N/A"
372              fi
373          fi
374      fi
375      if [ "$benchmark" = "true" ]; then
376          numresult=`expr $numresult \+ 1`
377          if [ $step -eq 1 ]; then
378              testlist[$numresult]="$item"
379          else
380              testlist[$numresult]="...step$step"
381          fi
382          timelist[$numresult]="$CPU_usage"
383      fi
384      passed=`echo $checkout | grep "TEST ENDED PROPERLY"`
385      if [ -z "$passed" ]; then
386        trouble=`expr $trouble \+ 1`
387        passedall="THERE IS A PROBLEM IN SOME TEST CASE(S)"
388        if [ "$trouble" -eq 1 ]; then
389            problems="$problems $item"
390            total_failed=`expr $total_failed \+ 1`
391        fi
392        exitcode=1
393      elif [ "$keep" = "false" ]; then
394        #rm -f $dalfile.dal $dalfile.BAS $checkfile $logfile $item.info
395        rm -f $dalfile.dal $dalfile.BAS $checkfile $item.info # keep $logfile, can be interesting to look closer at
396        if [ "$step" -eq "$numsteps" ]; then
397#       only delete restart files in last step of multistep test !!!
398           rm -f $dalfile.tar.gz
399        fi
400#     else everything OK and -keep defined
401      fi
402      myprint "     $checkout -- $total_failed tests failed out of the $total_tests_run tests run so far"
403      step=`expr $step \+ 1`
404  done
405  if [ "$trouble" -eq 0 ]; then
406      if [ "$keep" = "false" ]; then
407          rm -f $molfile.mol
408          rm -f $potfile.pot
409      fi
410  fi
411done
412
413
414#########################################################################
415# final result:
416#########################################################################
417
418myprint ""
419myprint "#####################################################################"
420myprint "                              Summary"
421myprint "#####################################################################"
422myprint ""
423
424if [ "$benchmark" = "true" ]; then
425    if [ "$numresult" -gt 0  ]; then
426      ind=1
427      while [ "$ind" -le "$numresult" ]; do
428        awk "END{printf \"%32s %s\\n\", \"${testlist[$ind]}\",\"${timelist[$ind]}\"}"</dev/null
429        awk "END{printf \"%32s %s\\n\", \"${testlist[$ind]}\",\"${timelist[$ind]}\"}"</dev/null >> $listing
430        ind=`expr $ind \+ 1`
431      done
432      myprint ""
433    fi
434fi
435
436if [ "$reftest" = "true" ]; then
437   myprint " THIS IS A TEST OF THE REFERENCE OUTPUTS "
438   myprint ""
439fi
440
441myprint "$passedall"
442if [ $total_failed -gt 0 ]; then
443   myprint "$total_failed tests failed"
444   myprint "$problems"
445fi
446if [ "$num_reftests_not_found" -gt 0  ]; then
447   myprint ""
448   myprint "WARNING: $num_reftests_not_found reference outputs were not found."
449   myprint ""
450fi
451rm "$tmpfile"
452myprint "date and time         : `date`"
453
454if [ "$result_directory" != "" ]; then
455  cd ..   # do not rm or mv your working directory
456  if [ "$exitcode" -eq 0 ]; then
457      # test passed, we remove the custom result directory
458      if [ "$keep" = "false" ]; then
459         rm -r $result_directory
460      else
461         mv $result_directory ${result_directory}_passed_"`date +'%Y-%m-%dT%H_%M'`-$$"
462      fi
463  else
464      mv $result_directory ${result_directory}_failed_"`date +'%Y-%m-%dT%H_%M'`-$$"
465  fi
466fi
467
468exit $exitcode
469