Newer
Older
set -o pipefail #abort if left command on a pipe fails
#This script:
# - compiles the PHYEX package using a specific commit
# - runs the different test progs and checks if results are identical to a given version
#ice_adjust: the ice adjust test case
#ref is commit 855b8f8 for ice_adjust, rain_ice
#ref is commit ??????? for turb
#ref is commit 7e44ab1 for shallow
#ref is commit e070d16 for rain_ice_old
#Commit e070d16 can be used for rain_ice_old (ref commit for this testprogs), and for
#turb, shallow, rain_ice and ice_adjust (as it gives the same results for these test cases).
#Some modifications have been introduced and new reference commit is 00148b1
#Data generation:
# - The last commit of the testprogs_data branch (based on 46t1) is able to produce the data
# for the turb, shallow, rain_ice and ice_adjust testprogs. The code is present but must be
# activated in the corresponding aro_* routine (as only one set of data can be produced during
# a single execution).
# - The last commit of the testprogs_data2 branch (based on 48t3) is able to produce the data
# for the rain_ice_old testprog.

RIETTE Sébastien
committed
#######################
#### CONFIGURATION ####
#######################
#Special pack names:
# - ref: symbolic name to the commit to use as a reference
# useless for the commits containing a json file

RIETTE Sébastien
committed
#About the tests:
# - ALLTests is a list of tests to be done when '-t ALL' is used. This list is filled here
# in case there is no ial_version.json file containig a 'testing' section. If this 'testing'
# section exists, this list is overridden.
# - allowedTests is the list of allowed tests which can depend on platform, if we ask to perform an action
# with a test not in the allowedTests list, the action is ignored
# - defaultTest is the list of tests to perform when no '-t' option is provided on the command line.
ALLTests="ice_adjust,rain_ice,rain_ice_old,turb,shallow"
defaultTest=${ALLTests}
allowedTests=${ALLTests}
separator='_' #- seprator must be in sync with prep_code.sh separator
PHYEXTOOLSDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

RIETTE Sébastien
committed
TESTDIR=${TESTPROGSDIR:=$HOME/TESTPROGS}
dirdata=$PHYEXTOOLSDIR/testprogs_data
if [ $(hostname | cut -c 1-7) == 'belenos' -o $(hostname | cut -c 1-7) == 'taranis' ]; then
HPC=1
defaultarchfile=MIMPIIFC1805.EPONA

RIETTE Sébastien
committed
################################
#### COMMAND LINE ARGUMENTS ####
################################

RIETTE Sébastien
committed
echo "Usage: $0 [-h] [-p] [-c] [-r] [-C] [-s] [--noexpand] [-t TEST] [--repo-user USER] [--repo-protocol PROTOCOL] [-a ARCH] [-A ARCH] [--remove] [--onlyIfNeeded] [--computeRefIfNeeded] commit [reference]"
echo "commit commit hash (or a directory, or among $specialName) to test"
echo "reference commit hash (or a directory, or among $specialName) REF to use as a reference"
echo "-s suppress compilation directory"

RIETTE Sébastien
committed
echo "-p creates pack"
echo "-c performs compilation"
echo "-r runs the tests"
echo "-C checks the result against the reference"

RIETTE Sébastien
committed
echo "-t TEST comma separated list of tests to execute"
echo " or ALL to execute all tests"
echo "--noexpand do not expand mnh_expand blocks (code will be in array-syntax)"

RIETTE Sébastien
committed
echo "--repo-user USER"
echo " user hosting the PHYEX repository on github,"

RIETTE Sébastien
committed
echo " defaults to the env variable PHYEXREOuser (=$PHYEXREOuser)"

RIETTE Sébastien
committed
echo "--repo-protocol PROTOCOL"
echo " protocol (https or ssh) to reach the PHYEX repository on github,"

RIETTE Sébastien
committed
echo " defaults to the env variable PHYEXREOprotocol (=$PHYEXREOprotocol)"
echo "--remove removes the pack"
echo "--onlyIfNeeded do not rerun already run steps"
echo "--computeRefIfNeeded"
echo " compute the reference if not already present"
echo "--no-perf deactivate DR_HOOK"

RIETTE Sébastien
committed
echo "-a arch ARCH architecture name to use to build and run the commit (=$defaultarchfile)"
echo "-A arch ARCH architecture name to use for the reference simulation (=$defaultarchfile)"

RIETTE Sébastien
committed
echo "If nothing is asked (pack creation compilation, running, check, removing) everything"
echo "except the removing is done"
echo
echo "If no test is aked for, the default one ($defaultTest) is executed"
echo
echo "With the special reference REF commit, a suitable reference is guessed"
echo
echo "The directory (for commit only, not ref) can take the form server:directory"
echo
echo "If using a directory (for commit or reference) it must contain at least one '/'"
echo "The commit can be a tag, written with syntagx tags/<TAG>"

RIETTE Sébastien
committed
packcreation=0
compilation=0
run=0
check=0
commit=""
reference=""
tests=""
suppress=0
useexpand=""
archfile=$defaultarchfile
refarchfile=$defaultarchfile

RIETTE Sébastien
committed
onlyIfNeeded=0
computeRefIfNeeded=0
while [ -n "$1" ]; do
case "$1" in
'-h') usage;;
'-s') suppress=1;;

RIETTE Sébastien
committed
'-p') packcreation=1;;
'-c') compilation=1;;
'-r') run=$(($run+1));;
'-C') check=1;;
'-t') tests="$2"; shift;;
'--noexpand') useexpand=$1;;

RIETTE Sébastien
committed
'--repo-user') export PHYEXREPOuser=$2; shift;;
'--repo-protocol') export PHYEXREPOprotocol=$2; shift;;
'--remove') remove=1;;
'-a') archfile="$2"; shift;;
'-A') refarchfile="$2"; shift;;

RIETTE Sébastien
committed
'--onlyIfNeeded') onlyIfNeeded=1;;
'--computeRefIfNeeded') computeRefIfNeeded=1;;
'--no-perf') perf=0;;

RIETTE Sébastien
committed
#--) shift; break ;;
*) if [ -z "${commit-}" ]; then
commit=$1
else
if [ -z "${reference-}" ]; then
reference=$1
else
echo "Only two commit hash allowed on command line"
exit 1
fi
fi;;
esac
shift
done

RIETTE Sébastien
committed
if [ $packcreation -eq 0 -a \
$compilation -eq 0 -a \
$check -eq 0 -a \
$remove -eq 0 ]; then

RIETTE Sébastien
committed
packcreation=1
compilation=1
run=1
check=1
fi
if [ -z "${commit-}" ]; then
echo "At least one commit hash must be provided on command line"
exit 2
fi
if [ $check -eq 1 -a -z "${reference-}" ]; then
echo "To perform a comparison two commit hashes are mandatory on the command line"
exit 3
fi

RIETTE Sébastien
committed
##############################
#### FUNCTION DEFINITIONS ####
##############################
function json_dictkey2value {
# $1 must contain the json string
# $2 must be the key name
# $3 is the default value
json_content="$1" python3 -c "import json; import os; result=json.loads(os.environ['json_content']).get('$2', '$3'); print(json.dumps(result) if isinstance(result, dict) else result)"
}
###########################
#### COMMIT ADAPTATION ####
###########################
#Name and directory for compiling and executing user pack
declare -A refByTest
if echo $commit | grep '/' | grep -v '^tags/' > /dev/null; then

RIETTE Sébastien
committed
#The git repository is a directory
name=$(echo $commit | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')

RIETTE Sébastien
committed
content_testprogs_version=$(scp $commit/src/testprogs/testprogs_version.json /dev/stdout 2>/dev/null || echo "")
[ $suppress -eq 1 -a -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
elif echo $specialName | grep -w $commit > /dev/null; then
name="$commit"
else

RIETTE Sébastien
committed
#The git repository is on github
if [[ $commit == testprogs${separator}* ]]; then
testprogs_version_file="testprogs_version.json"
else
testprogs_version_file="src/testprogs/testprogs_version.json"
fi
if echo $commit | grep '^tags/' > /dev/null; then
urlcommit=$(echo $commit | cut -d / -f 2-)
else
urlcommit=$commit
fi
content_testprogs_version=$(wget --no-check-certificate https://raw.githubusercontent.com/$PHYEXREPOuser/PHYEX/${urlcommit}/$testprogs_version_file -O - 2>/dev/null || echo "")
name="COMMIT$(echo $commit | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')"
[ $suppress -eq 1 -a -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
fi

RIETTE Sébastien
committed
if [ ! "${content_testprogs_version}" == "" ]; then
testing=$(json_dictkey2value "$content_testprogs_version" 'testing' '')
refALL=$(json_dictkey2value "$testing" "ALL" '')
if [ ! "$testing" == "" ]; then
ALLTests='' #We reset the list of tests
for t in $(echo $allowedTests | sed 's/,/ /g'); do
ref=$(json_dictkey2value "$testing" "$t" "$refALL")
if [ ! "$ref" == "" ]; then
ALLTests="${ALLTests},$t"
refByTest[$t]=$ref
fi
done
ALLTests="${ALLTests:1}" #Remove first character (',')

RIETTE Sébastien
committed
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#Name and directory for the reference version
if [ ! -z "${reference-}" ]; then
declare -A refnameByTest
#Reference to use for each test
for t in $(echo $ALLTests | sed 's/,/ /g'); do
#Name of the reference
if [ "$reference" == "REF" ]; then
if [[ ! -z "${refByTest[$t]+unset}" ]]; then #the -v test is valid only with bash > 4.3
#The json file contained the references to use on a per test case basis
caseref=${refByTest[$t]}
else
caseref=$defaultRef
fi
refByTest[$t]=$caseref
else
#The exact reference to use was given on the command line
caseref=$reference
fi
refByTest[$t]=$caseref
#Conversion into directory name
if echo $caseref | grep '/' > /dev/null; then
refname=$(echo $reference | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')
elif echo $specialName | grep -w $caseref > /dev/null; then
refname="$caseref"
else
refname="COMMIT${caseref}"
fi
refnameByTest[$t]=$refname
done
fi

RIETTE Sébastien
committed
if [ -z "${tests-}" ]; then
tests=$defaultTest
elif echo "$tests" | grep -w 'ALL' > /dev/null; then
tests=$(echo "$tests" | sed "s/\bALL\b/$ALLTests/g")
fi
#######################
#### PACK CREATION ####
#######################

RIETTE Sébastien
committed
if [ $packcreation -eq 1 ]; then

RIETTE Sébastien
committed
if [ $onlyIfNeeded -eq 0 ]; then
echo "Directory already exists ($TESTDIR/$name), suppress it to be able to compile it again (or use the -s option to automatically suppress it)"
exit 5
fi
else
echo "### Pack creation for commit $commit"
if echo $specialName | grep -w $commit > /dev/null; then
echo "Special commit '$commit' cannot be compiled with this script"
exit 4
fi
mkdir -p $TESTDIR/$name

RIETTE Sébastien
committed
cd $TESTDIR/$name/
cp -r $PHYEXTOOLSDIR/../build . #We use the compilation system from the same commit as the current script
cd $TESTDIR/$name/build/with_fcm/
rm -rf arch_*
./make_fcm.sh -p $useexpand --commit $commit --arch $archfile 2>&1 | tee Output_compilation_step1

RIETTE Sébastien
committed
fi

RIETTE Sébastien
committed
#####################
#### COMPILATION ####
#####################
if [ $compilation -eq 1 ]; then
if [ $onlyIfNeeded -eq 0 -o ! -f $TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/libphyex.so ]; then
echo "### Compilation of commit $commit"

RIETTE Sébastien
committed
cd $TESTDIR/$name/build/with_fcm/
./make_fcm.sh -c $useexpand --commit $commit --arch $archfile 2>&1 | tee Output_compilation_step2
fi

RIETTE Sébastien
committed
###################
#### EXECUTION ####
###################

RIETTE Sébastien
committed
if [ $run -ge 1 ]; then
cd $TESTDIR/$name
#Cleaning to suppress old results that may be confusing in case of a crash during the run

RIETTE Sébastien
committed
if [ $onlyIfNeeded -eq 0 ]; then
for t in $(echo $tests | sed 's/,/ /g'); do
if [ -d tests/with_fcm/arch_${archfile}/$t ]; then
rm -rf tests/with_fcm/arch_${archfile}/$t
fi
done
fi
#Run the tests one after the other

RIETTE Sébastien
committed
firstrun=1
for t in $(echo $tests | sed 's/,/ /g'); do

RIETTE Sébastien
committed
if echo $allowedTests | grep -w $t > /dev/null; then #test is allowed on this plateform
if [ ! -d tests/with_fcm/arch_${archfile}/$t ]; then #We do not enter systematically this part if onlyIfNeeded=1
if [ $firstrun -eq 1 ]; then
echo "### Running of commit $commit"
firstrun=0
fi
if [ ! -f $TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/main_${t}.exe ]; then
echo "Directory does not exist ($TESTDIR/$name) or compilation has failed, please check"
exit 6
fi
#execution
cd $TESTDIR/$name
mkdir -p tests/with_fcm/arch_${archfile}/$t
cd tests/with_fcm/arch_${archfile}/$t
ln -s $dirdata/$t data
if [ $perf -eq 1 ]; then
export DR_HOOK_OPT=prof
export DR_HOOK=1
export DR_HOOK_IGNORE_SIGNALS=-1
fi
$TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/main_${t}.exe --check > Output_run 2> Stderr_run
if [ $perf -eq 1 ]; then
firstLine=$(grep -m 1 -n "^ *1" drhook.prof.0 | cut -d: -f1)
python3 -c "import numpy, pandas
d = {'time': ('<f4', ('mean', )), 'self': ('<f4', ('mean', 'max', 'min', 'std', 'sum')),
'total': ('<f4', ('mean', 'max', 'min', 'std', 'sum')), 'calls': ('<i4', ('sum', )),
'self_per_call': ('<f4', ('mean', )), 'total_per_call': ('<f4', ('mean', )), 'routine': ('U256', '')}
arraynp = numpy.loadtxt('drhook.prof.0', dtype=[(k, v[0]) for (k, v) in d.items()],
converters={8: lambda s: s.split(b'@')[0].lstrip(b'*')},
skiprows=$firstLine - 1, usecols=[1, 3, 4, 5, 6, 7, 8])
df = pandas.DataFrame(arraynp).groupby('routine').agg(
**{k + '_' + agg:pandas.NamedAgg(column=k, aggfunc=agg)
for (k, agg) in [(k, agg) for k in d.keys() for agg in d[k][1]]
if k != 'routine'}).sort_values('self_sum', ascending=False)
df.index.name += ' ordered by self_sum'
with open('drhook.prof.agg', 'w') as f: f.write(df.to_string())
"
fi

RIETTE Sébastien
committed
fi
fi

RIETTE Sébastien
committed
####################
#### COMPARISON ####
####################
if [ $check -eq 1 ]; then
echo "### Check commit $commit against commit $reference"
alltests=0
message=""
for t in $(echo $tests | sed 's/,/ /g'); do

RIETTE Sébastien
committed
if echo $allowedTests | grep -w $t > /dev/null; then
#Run the reference if needed
if [ $computeRefIfNeeded -eq 1 ]; then
$0 -p -c -r -t $t -a ${archfile} --onlyIfNeeded ${refByTest[$t]}

RIETTE Sébastien
committed
#File comparison
file1=$TESTDIR/$name/tests/with_fcm/arch_${archfile}/$t/Output_run
file2=$TESTDIR/${refnameByTest[$t]}/tests/with_fcm/arch_${refarchfile}/$t/Output_run
mess=""
te=0
if [ ! -f "$file1" ]; then
mess="Result ($file1) for commit $commit does not exist, please run the simulation"
te=1
fi
if [ ! -f "$file2" ]; then
mess2="Result ($file2) for commit ${refByTest[$t]} does not exist, please run the simulation"
te=1
if [ "$mess" = "" ]; then
mess=$mess2
else
mess="$mess and $mess2"
fi
fi
if [ $te -eq 0 ]; then
set +e
mess=$($PHYEXTOOLSDIR/compare.py --testprogs $file1 $file2)

RIETTE Sébastien
committed
te=$?
set -e
fi
[ $te -ne 0 ] && message="$message $mess \n"
alltests=$(($alltests+$te))
fi
done
if [ $alltests -eq 0 ]; then
echo "SUCCESS, files are identical"
else
echo "*************** Files are different *******************"
echo -e "$message"

RIETTE Sébastien
committed
##################
#### CLEANING ####
##################
if [ $remove -eq 1 ]; then
echo "### Remove model directory for commit $commit"
[ -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
fi
exit $cmpstatus