Skip to content

Commit

Permalink
Improve Travis CI usage
Browse files Browse the repository at this point in the history
Introduced MARBL_tools/run_test_suite.sh, a bash script that runs a series of
tests; Travis CI now tries to build the sphinx documentation and then runs this
test script. A few improvements to some python scripts along the way:

1. added a --no_pause option to bld_lib.py and bld_exe.py; if run with that
   flag, the user will not be prompted to press [return] between compilers
2. If a build fails, bld_lib.py and bld_exe.py exit immediately (rather than
   attempting to build with the next compiler and eventually returning a status
   of 0)
3. marbl_with_restore.input reflects tracers that are restored in POP
  • Loading branch information
mnlevy1981 committed Jun 14, 2018
2 parents 410196c + 3e35491 commit 2f8db4a
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 56 deletions.
16 changes: 3 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,13 @@ before_install:
- sudo apt-get install gfortran
install:
- pip install pyyaml
- pip install -r docs/py_requirements.txt
python:
- '2.7'
- '3.6'
script:
- cd MARBL_tools; ./yaml_to_json.py
- ./MARBL_generate_settings_file.py
- ./MARBL_generate_diagnostics_file.py
- cd ../tests/bld_tests; ./bld_exe.py
- cd ../unit_tests/get_put; ./get_put.py
- cd ../utils_routines; ./marbl_utils.py
- cd ../../regression_tests/init; ./init.py
- cd ../init-twice; ./init-twice.py
- cd ../gen_input_file; ./gen_input_file.py
- cd ../requested_diags; ./requested_diags.py
- cd ../requested_forcings; ./requested_forcings.py
- cd ../requested_restoring; ./requested_restoring.py
- cd ../requested_tracers; ./requested_tracers.py
- cd docs/src; make html
- cd ../../MARBL_tools; ./run_test_suite.sh

branches:
only:
Expand Down
157 changes: 157 additions & 0 deletions MARBL_tools/run_test_suite.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/bin/bash

# Convert shell return code to "PASS" or "FAIL"
# (0 = PASS, all other return codes = FAIL)
function check_return() {
if [ $1 -eq 0 ]; then
echo "PASS"
else
echo "FAIL"
fi

}

#################################################

# Output test results
function print_status() {
TEST_CNT=$((TEST_CNT+1))
if [ "${STATUS}" == "FAIL" ]; then
FAIL_CNT=$((FAIL_CNT+1))
fi
echo "${TEST_CNT}. $1: ${STATUS}"
}

#################################################

###############
# Global Vars #
###############

MARBL_ROOT=`(cd ..; pwd -P)`
OUTFILE=${MARBL_ROOT}/.test.out
TEST_CNT=0
FAIL_CNT=0
echo "Test Results:" > $OUTFILE

#########
# TESTS #
#########

# Convert YAML to JSON
cd ${MARBL_ROOT}/MARBL_tools
echo "$ ./yaml_to_json.py"
./yaml_to_json.py
STATUS=$(check_return $?)
print_status "yaml_to_json.py" >> $OUTFILE

# Generate a settings file (python)
cd ${MARBL_ROOT}/MARBL_tools
echo "$ ./MARBL_generate_settings_file.py"
./MARBL_generate_settings_file.py
STATUS=$(check_return $?)
print_status "MARBL_generate_settings_file.py" >> $OUTFILE

# Test MARBL_generate_diagnostics_file.py
cd ${MARBL_ROOT}/MARBL_tools
echo "$ ./MARBL_generate_diagnostics_file.py"
./MARBL_generate_diagnostics_file.py
STATUS=$(check_return $?)
print_status "MARBL_generate_diagnostics_file.py" >> $OUTFILE

# Clean Fortran Code
cd ${MARBL_ROOT}/tests/driver_src
echo "$ make clean"
make clean
STATUS=$(check_return $?)
print_status "make clean" >> $OUTFILE

# Build libmarbl.a
cd ${MARBL_ROOT}/tests/bld_tests
echo "$ ./bld_lib.py --no_pause"
./bld_lib.py --no_pause
STATUS=$(check_return $?)
print_status "bld_lib.py --no_pause" >> $OUTFILE

# Build stand-alone executable (only if library built successfully)
if [ "${STATUS}" == "PASS" ]; then
cd ${MARBL_ROOT}/tests/bld_tests
echo "$ ./bld_exe.py --no_pause"
./bld_exe.py --no_pause
STATUS=$(check_return $?)
print_status "bld_exe.py --no_pause" >> $OUTFILE
fi

# Only test Fortran executable if build was successful
if [ "${STATUS}" == "PASS" ]; then
# get_put unit test
cd ${MARBL_ROOT}/tests/unit_tests/get_put
echo "$ ./get_put.py"
./get_put.py
STATUS=$(check_return $?)
print_status "get_put.py" >> $OUTFILE

# marbl_utils unit test
cd ${MARBL_ROOT}/tests/unit_tests/utils_routines
echo "$ ./marbl_utils.py"
./marbl_utils.py
STATUS=$(check_return $?)
print_status "marbl_utils.py" >> $OUTFILE

# Initialize MARBL
cd ${MARBL_ROOT}/tests/regression_tests/init
echo "$ ./init.py"
./init.py
STATUS=$(check_return $?)
print_status "init.py" >> $OUTFILE

# Initialize MARBL, clean up memory, initialize again
cd ${MARBL_ROOT}/tests/regression_tests/init-twice
echo "$ ./init-twice.py"
./init-twice.py
STATUS=$(check_return $?)
print_status "init-twice.py" >> $OUTFILE

# Generate a settings file (Fortran)
cd ${MARBL_ROOT}/tests/regression_tests/gen_input_file
echo "$ ./gen_input_file.py"
./gen_input_file.py
STATUS=$(check_return $?)
print_status "gen_input_file.py" >> $OUTFILE

# Print all diagnostics MARBL can provide
cd ${MARBL_ROOT}/tests/regression_tests/requested_diags
echo "$ ./requested_diags.py"
./requested_diags.py
STATUS=$(check_return $?)
print_status "requested_diags.py" >> $OUTFILE

# Print all forcings MARBL requires
cd ${MARBL_ROOT}/tests/regression_tests/requested_forcings
echo "$ ./requested_forcings.py"
./requested_forcings.py
STATUS=$(check_return $?)
print_status "requested_forcings.py" >> $OUTFILE

# Print all restoring fields being requested
cd ${MARBL_ROOT}/tests/regression_tests/requested_restoring
echo "$ ./requested_restoring.py"
./requested_restoring.py -i ${MARBL_ROOT}/tests/input_files/marbl_with_restore.input
STATUS=$(check_return $?)
print_status "requested_restoring.py" >> $OUTFILE

# Print all tracers MARBL computes tendencies for
cd ${MARBL_ROOT}/tests/regression_tests/requested_tracers
echo "$ ./requested_tracers.py"
./requested_tracers.py
STATUS=$(check_return $?)
print_status "requested_tracers.py" >> $OUTFILE
fi

echo "----"
cat $OUTFILE
rm -f $OUTFILE
echo ""
echo "${TEST_CNT} tests were run, and $FAIL_CNT failed."
exit ${FAIL_CNT}

3 changes: 3 additions & 0 deletions docs/py_requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Sphinx==1.7.5
sphinx-rtd-theme==0.2.5b1
sphinxcontrib-bibtex==0.4.0
35 changes: 0 additions & 35 deletions docs/sphinx-requirements.txt

This file was deleted.

5 changes: 3 additions & 2 deletions tests/bld_tests/bld_exe.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
from general import pause

mt = MARBL_testcase()
mt.parse_args(desc='Build marbl.exe with every supported compiler on specified machine', HaveCompiler=False, HaveInputFile=False)
mt.parse_args(desc='Build marbl.exe with every supported compiler on specified machine', HaveCompiler=False,
HaveInputFile=False, HasPause=True)

for i,compiler in enumerate(mt.supported_compilers):
mt.build_exe(loc_compiler=compiler)
logging.info("Done with %s build" % compiler)
if i != len(mt.supported_compilers)-1:
if (i != len(mt.supported_compilers)-1) and (mt.pause):
pause()

5 changes: 3 additions & 2 deletions tests/bld_tests/bld_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
from general import pause

mt = MARBL_testcase()
mt.parse_args(desc='Build lib-marbl.a with every supported compiler on specified machine', HaveCompiler=False, HaveInputFile=False, CleanLibOnly=True)
mt.parse_args(desc='Build lib-marbl.a with every supported compiler on specified machine', HaveCompiler=False,
HaveInputFile=False, HasPause=True, CleanLibOnly=True)

for i,compiler in enumerate(mt.supported_compilers):
mt.build_lib(loc_compiler=compiler)
logger.info("Done with %s build" % compiler)
if i != len(mt.supported_compilers)-1:
if i != len(mt.supported_compilers)-1 and (mt.pause):
pause()

2 changes: 2 additions & 0 deletions tests/input_files/marbl_with_restore.input
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
tracer_restore_vars(1) = 'SiO3'
tracer_restore_vars(2) = 'NO3'
tracer_restore_vars(3) = 'PO4'
tracer_restore_vars(4) = 'ALK'
tracer_restore_vars(5) = 'ALK_ALT_CO2'
21 changes: 17 additions & 4 deletions tests/python_for_tests/marbl_testing_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(self):
# Some tests will let you specify a compiler and / or input file
# Some tests will require you to specify a machine
def parse_args(self, desc, HaveCompiler=True, HaveInputFile=True,
CleanLibOnly=False):
HasPause=False, CleanLibOnly=False):

import argparse

Expand All @@ -42,6 +42,10 @@ def parse_args(self, desc, HaveCompiler=True, HaveInputFile=True,
parser.add_argument('-i', '--input_file', action='store', dest='input_file',
default=None, help='input file to read')

if HasPause:
parser.add_argument('--no_pause', action='store_true', dest='no_pause',
help='do not pause between compilers')

if CleanLibOnly:
parser.add_argument('--clean', action='store_true',
help='remove object, module, and library files for MARBL lib')
Expand Down Expand Up @@ -112,6 +116,9 @@ def parse_args(self, desc, HaveCompiler=True, HaveInputFile=True,
self._mpitasks = int(args.mpitasks)
sys.stdout.flush()

if HasPause:
self.pause = not args.no_pause

# ERROR CHECKING
if HaveCompiler:
if not self._compiler in self.supported_compilers:
Expand All @@ -135,7 +142,10 @@ def build_lib(self, loc_compiler=None):
makecmd = 'make %s' % loc_compiler
if self._mpitasks > 0:
makecmd += ' USEMPI=TRUE'
sh_command('cd %s; %s' % (src_dir, makecmd))
status_code = sh_command('cd %s; %s' % (src_dir, makecmd))
if status_code != 0:
logging.error("ERROR building MARBL library")
sys.exit(1)

# -----------------------------------------------

Expand All @@ -153,7 +163,10 @@ def build_exe(self, loc_compiler=None):
makecmd = 'make %s' % loc_compiler
if self._mpitasks > 0:
makecmd += ' USEMPI=TRUE'
sh_command('cd %s; %s' % (drv_dir, makecmd))
status_code = sh_command('cd %s; %s' % (drv_dir, makecmd))
if status_code != 0:
logging.error("ERROR building MARBL stand-alone driver")
sys.exit(1)

# -----------------------------------------------

Expand Down Expand Up @@ -198,7 +211,7 @@ def run_exe(self):
status_code = sh_command(execmd)
if status_code != 0:
logging.error("ERROR in executable")
sys.exit(status_code)
sys.exit(1)

# -----------------------------------------------
# PRIVATE ROUTINES
Expand Down

0 comments on commit 2f8db4a

Please sign in to comment.