Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial testing framework simplified #1284

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .ci/env/derecho.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh

echo "Setting up derecho environment"
workingDirectory=$PWD
. /etc/profile.d/z00_modules.sh
echo "Loading modules : $*"
cmd="module purge"
echo $cmd && eval "${cmd}"

# We should be handed in the modules to load
while [ $# -gt 0 ]; do
cmd="module load $1"
echo $cmd && eval "${cmd}"
shift
done

# Go back to working directory if for unknown reason HPC config changing your directory on you
if [ "$workingDirectory" != "$PWD" ]; then
echo "derecho module loading changed working directory"
echo " Moving back to $workingDirectory"
cd $workingDirectory
fi
46 changes: 46 additions & 0 deletions .ci/env/helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/sh

# Useful string manipulation functions, leaving in for posterity
# https://stackoverflow.com/a/8811800
# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains()
{
string="$1"
substring="$2"

if [ "${string#*"$substring"}" != "$string" ]; then
echo 0 # $substring is in $string
else
echo 1 # $substring is not in $string
fi
}

setenvStr()
{
# Changing IFS produces the most consistent results
tmpIFS=$IFS
IFS=","
string="$1"
for s in $string; do
if [ ! -z $s ]; then
eval "echo export \"$s\""
eval "export \"$s\""
fi
done
IFS=$tmpIFS
}

banner()
{
lengthBanner=$1
shift
# https://www.shellscript.sh/examples/banner/
printf "#%${lengthBanner}s#\n" | tr " " "="
printf "# %-$(( ${lengthBanner} - 2 ))s #\n" "`date`"
printf "# %-$(( ${lengthBanner} - 2 ))s #\n" " "
printf "# %-$(( ${lengthBanner} - 2 ))s #\n" "$*"
printf "#%${lengthBanner}s#\n" | tr " " "="
}
16 changes: 16 additions & 0 deletions .ci/env/hostenv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh

# Allow selection of hostname, and if none is provided use the current machine
# While this may seem unintuitive at first, it provides the flexibility of using
# "named" configurations without being explicitly tied to fqdn
hostname=$AS_HOST
if [ -z "$hostname" ]; then
hostname=$( python3 -c "import socket; print( socket.getfqdn() )" )
fi

if [ $( contains ${hostname} hsn.de.hpc ) -eq 0 ]; then
# Derecho HPC SuSE PBS
. .ci/env/derecho.sh
else
echo "No known environment for '${hostname}', using current"
fi
1 change: 1 addition & 0 deletions .ci/hpc-workflows
Submodule hpc-workflows added at 97ca80
48 changes: 48 additions & 0 deletions .ci/mpas_compilation.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// MPAS Compilation tests
{
"submit_options" :
{
// Default values
"timelimit" : "00:15:00",
"working_directory" : "..",
"arguments" :
{
"base_env_numprocs" : [ "-e", "NUM_PROCS=4" ],

".*make.*::args_build_core" : [ "-c", "atmosphere" ],
".*debug.*::args_build_debug" : [ "-d" ],
".*make.*::args_build_options" : [ "-b", "-j $NUM_PROCS" ],
".*make.*gnu.*::args_target" : [ "-t", "gnu" ]
},
// Derecho-specifics
"hsn.de.hpc" :
{
"submission" : "PBS",
"queue" : "main",
"hpc_arguments" :
{
"node_select" : { "-l " : { "select" : 1, "ncpus" : 16 } },
"priority" : { "-l " : { "job_priority" : "economy" } }
},
"arguments" :
{
// We want NUM_PROCS to match ncpus
"base_env_numprocs" : [ "-e", "NUM_PROCS=16" ],
"very_last_modules" : [ "cray-mpich", "parallel-netcdf" ],
".*gnu.*::test_modules" : [ "gcc/12.2.0" ]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One part where I've had some troubles with is the ordering of the arguments that are passed to the script we are running (build.sh here). If I'm not careful enough, there are sometimes options I'm trying to pass to the script (say "-z option1") that get misconstrued as modules to be loaded, etc.

Probably related to the ordering of options which are defined in these regex statements (".make.::args_build_options"). I usually avoid this issue by specifying the arguments locally after every command ("command" : ".ci/tests/build.sh"). Not sure if I what I wrote is very clear, but I'll try to clarify my comment with a better example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand. This is probably due to the way I have it setup where on the first unknown arg it encounters getopts exits and forwards the rest to the environment script.

The order passed in will be determined by the alphabetical order of the non-regex portions, deconflicted by order of appearance in the config file. I'm not sure if you've already found this documentation (https://github.com/islas/hpc-workflows/blob/main/tutorials/AdvancedTestConfig_regex_argpacks.md#simple-regex-argpack-config) at the end of that section there is a note about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, admittedly, a very fragile setup relying on argument order between what the test script needs and what the environment script needs..

Perhaps a better approach would be something like the -e env option where things are accumulated and then handled afterwards. In that way multiple things can be passed to then env script without relying on order

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @islas! I don't think I've looked at this specific section of your documentation. I will go through that.

I think it's a relatively minor issue, and as long as there's some documentation, I'd be fine with things as they are.

}
}
},
// Specific GNU compilation test
"make-gnu" :
{
"steps" :
{
// Eventually include debug and other compile modes
"optimized" :
{
"command" : ".ci/tests/build.sh"
}
}
}
}
90 changes: 90 additions & 0 deletions .ci/tests/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/sh
help()
{
echo "./build.sh as_host workingdir [options] [-- <hostenv.sh options>]"
echo " as_host First argument must be the host configuration to use for environment loading"
echo " workingdir Second argument must be the working dir to immediate cd to"
echo " -b Additional make arguments passed in"
echo " -c Core to build"
echo " -t Target configuration (gnu, intel, etc)"
echo " -d Debug build"
echo " -e environment variables in comma-delimited list, e.g. var=1,foo,bar=0"
echo " -- <hostenv.sh options> Directly pass options to hostenv.sh, equivalent to hostenv.sh <options>"
echo " -h Print this message"
echo ""
echo "If you wish to use an env var in your arg such as '-b core=\$CORE -e CORE=atmosphere', you must"
echo "you will need to do '-b \\\$CORE -e CORE=atmosphere' to delay shell expansion"
}

echo "Input arguments:"
echo "$*"

AS_HOST=$1
shift
if [ $AS_HOST = "-h" ]; then
help
exit 0
fi

workingDirectory=$1
shift

cd $workingDirectory

# Get some helper functions, AS_HOST must be set by this point to work
. .ci/env/helpers.sh

while getopts b:c:t:de:h opt; do
case $opt in
b)
buildCommand="$OPTARG"
;;
c)
core="$OPTARG"
;;
t)
target="$OPTARG"
;;
d)
debug="DEBUG=true"
;;
e)
envVars="$envVars,$OPTARG"
;;
h) help; exit 0 ;;
*) help; exit 1 ;;
:) help; exit 1 ;;
\?) help; exit 1 ;;
esac
done

shift "$((OPTIND - 1))"

# Everything else goes to our env setup, POSIX does not specify how to pass in
# arguments to sourced script, but all args are already shifted. This is left for
# posterity to "show" what is happening and the assumption of the remaining args
. .ci/env/hostenv.sh $*

# Now evaluate env vars in case it pulls from hostenv.sh
if [ ! -z "$envVars" ]; then
setenvStr "$envVars"
fi

# Re-evaluate input values for delayed expansion
eval "core=\"$core\""
eval "target=\"$target\""
eval "buildCommand=\"$buildCommand\""

make clean CORE=$core

echo "Compiling with options $target core=$core $debug $buildCommand"
echo "make $target CORE=$core $debug $buildCommand"
make $target CORE=$core $debug $buildCommand
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was wondering if there's value to including the other MPAS build options in this PR, or if it's better in a succeeding PR.

result=$?

if [ $result -ne 0 ]; then
echo "Failed to compile"
exit 1
fi

echo "TEST $(basename $0) PASS"
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule ".ci/hpc-workflows"]
path = .ci/hpc-workflows
url = https://github.com/islas/hpc-workflows/