Skip to content

Commit

Permalink
Merge pull request #1381 from billsacks/cheyenne_unit_tests
Browse files Browse the repository at this point in the history
Get Fortran unit tests working on cheyenne
  • Loading branch information
jedwards4b authored Apr 19, 2017
2 parents 9629886 + 085fbfd commit 06c5645
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 28 deletions.
1 change: 1 addition & 0 deletions config/cesm/machines/config_compilers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,7 @@ using a fortran linker.
<CMAKE_OPTS>
<append DEBUG="TRUE"> -DPIO_ENABLE_LOGGING=ON </append>
</CMAKE_OPTS>
<PFUNIT_PATH>$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit3.2.8_cheyenne_Intel17.0.1_MPI_openMP</PFUNIT_PATH>
<!-- Bug in the intel/17.0.1 compiler requires this, remove this line when compiler is updated -->
<HAS_F2008_CONTIGUOUS>FALSE</HAS_F2008_CONTIGUOUS>
</compiler>
Expand Down
12 changes: 12 additions & 0 deletions config/cesm/machines/config_machines.xml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@
<arg name="zthreadplacement"> omplace </arg>
</arguments>
</mpirun>
<mpirun mpilib="default" unit_testing="true">
<!-- The only place we can build and run the unit tests is on cheyenne's
shared nodes. However, running mpi jobs on the shared nodes currently
requires some workarounds; these workarounds are implemented here -->
<executable>/opt/sgi/mpt/mpt-2.15/bin/mpirun $ENV{UNIT_TEST_HOST} -np 1 </executable>
</mpirun>
<mpirun mpilib="mpi-serial">
<executable></executable>
</mpirun>
Expand Down Expand Up @@ -264,6 +270,12 @@
<env name="OMP_STACKSIZE">256M</env>
<env name="MPI_TYPE_DEPTH">16</env>
</environment_variables>
<environment_variables unit_testing="true">
<!-- It's possible that we also need to set:
LD_LIBRARY_PATH=/opt/sgi/mpt/mpt-2.15/lib:$LD_LIBRARY_PATH
-->
<env name="MPI_USE_ARRAY">false</env>
</environment_variables>
</machine>

<machine MACH="constance">
Expand Down
1 change: 1 addition & 0 deletions config/xml_schemas/config_machines.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
<xs:attribute ref="debug"/>
<xs:attribute ref="mpilib"/>
<xs:attribute ref="compiler"/>
<xs:attribute ref="unit_testing"/>
</xs:complexType>
</xs:element>
<xs:element name="env">
Expand Down
12 changes: 8 additions & 4 deletions scripts/lib/CIME/BuildTools/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

logger = logging.getLogger(__name__)

def configure(machobj, output_dir, macros_format, compiler, mpilib, debug, sysos):
def configure(machobj, output_dir, macros_format, compiler, mpilib, debug,
sysos, unit_testing=False):
"""Add Macros, Depends, and env_mach_specific files to a directory.
Arguments:
Expand All @@ -34,6 +35,8 @@ def configure(machobj, output_dir, macros_format, compiler, mpilib, debug, sysos
compiler - String containing the compiler vendor to configure for.
mpilib - String containing the MPI implementation to configure for.
debug - Boolean specifying whether debugging options are enabled.
unit_testing - Boolean specifying whether we're running unit tests (as
opposed to a system run)
"""
# Macros generation.
suffixes = {'Makefile': 'make', 'CMake': 'cmake'}
Expand All @@ -44,7 +47,7 @@ def configure(machobj, output_dir, macros_format, compiler, mpilib, debug, sysos

_copy_depends_files(machobj.get_machine_name(), machobj.machines_dir, output_dir, compiler)
_generate_env_mach_specific(output_dir, machobj, compiler, mpilib,
debug, sysos)
debug, sysos, unit_testing)

def _copy_depends_files(machine_name, machines_dir, output_dir, compiler):
"""
Expand All @@ -64,15 +67,16 @@ def _copy_depends_files(machine_name, machines_dir, output_dir, compiler):
shutil.copyfile(dfile, outputdfile)


def _generate_env_mach_specific(output_dir, machobj, compiler, mpilib, debug, sysos):
def _generate_env_mach_specific(output_dir, machobj, compiler, mpilib, debug,
sysos, unit_testing):
"""
env_mach_specific generation.
"""
ems_path = os.path.join(output_dir, "env_mach_specific.xml")
if os.path.exists(ems_path):
logger.warn("%s already exists, delete to replace"%ems_path)
return
ems_file = EnvMachSpecific(output_dir)
ems_file = EnvMachSpecific(output_dir, unit_testing=unit_testing)
ems_file.populate(machobj)
ems_file.write()
for shell in ('sh', 'csh'):
Expand Down
8 changes: 7 additions & 1 deletion scripts/lib/CIME/XML/env_mach_specific.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
# get_type) otherwise need to implement own functions and make GenericXML parent class
class EnvMachSpecific(EnvBase):
# pylint: disable=unused-argument
def __init__(self, caseroot, infile="env_mach_specific.xml",components=None):
def __init__(self, caseroot, infile="env_mach_specific.xml",
components=None, unit_testing=False):
"""
initialize an object interface to file env_mach_specific.xml in the case directory
"""
fullpath = infile if os.path.isabs(infile) else os.path.join(caseroot, infile)
EnvBase.__init__(self, caseroot, fullpath)
self._unit_testing = unit_testing

def populate(self, machobj):
"""Add entries to the file using information from a Machines object."""
Expand Down Expand Up @@ -191,6 +193,10 @@ def _match_attribs(self, attribs, compiler, debug, mpilib):
elif ("debug" in attribs and
not self._match("TRUE" if debug else "FALSE", attribs["debug"].upper())):
return False
elif ("unit_testing" in attribs and
not self._match("TRUE" if self._unit_testing else "FALSE",
attribs["unit_testing"].upper())):
return False

return True

Expand Down
23 changes: 13 additions & 10 deletions scripts/tests/scripts_regression_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,19 @@ def setUpClass(cls):
cls._testroot = os.path.join(TEST_ROOT, 'TestUnitTests')
cls._testdirs = []

def _has_unit_test_support(self):
default_compiler = MACHINE.get_default_compiler()
compiler = Compilers(MACHINE, compiler=default_compiler)
pfunit_path = compiler.get_optional_compiler_node("PFUNIT_PATH")
if pfunit_path is None:
return False
else:
return True

def test_a_unit_test(self):
cls = self.__class__
machine = MACHINE.get_machine_name()
compiler = MACHINE.get_default_compiler()
if (machine != "yellowstone" or compiler != "intel"):
#TODO: get rid of this restriction
self.skipTest("Skipping TestUnitTest - only supported on yellowstone with intel")
if not self._has_unit_test_support():
self.skipTest("Skipping TestUnitTest - PFUNIT_PATH not found for the default compiler on this machine")
test_dir = os.path.join(cls._testroot,"unit_tester_test")
cls._testdirs.append(test_dir)
os.makedirs(test_dir)
Expand All @@ -199,11 +205,8 @@ def test_b_cime_f90_unit_tests(self):
if (FAST_ONLY):
self.skipTest("Skipping slow test")

machine = MACHINE.get_machine_name()
compiler = MACHINE.get_default_compiler()
if (machine != "yellowstone" or compiler != "intel"):
#TODO: get rid of this restriction
self.skipTest("Skipping TestUnitTest - only supported on yellowstone with intel")
if not self._has_unit_test_support():
self.skipTest("Skipping TestUnitTest - PFUNIT_PATH not found for the default compiler on this machine")

test_dir = os.path.join(cls._testroot,"driver_f90_tests")
cls._testdirs.append(test_dir)
Expand Down
3 changes: 2 additions & 1 deletion src/externals/CMake/pFUnit_utils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ function(create_pFUnit_test test_name executable_name pf_file_list fortran_sourc
endif()

# Prefix command with an mpirun command
set (MY_COMMAND ${PFUNIT_MPIRUN} ${MY_COMMAND})
separate_arguments(PFUNIT_MPIRUN_LIST UNIX_COMMAND ${PFUNIT_MPIRUN})
set (MY_COMMAND ${PFUNIT_MPIRUN_LIST} ${MY_COMMAND})

# Do the work
add_pFUnit_executable(${executable_name} "${pf_file_list}"
Expand Down
28 changes: 16 additions & 12 deletions tools/unit_testing/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from CIME.XML.env_mach_specific import EnvMachSpecific
from xml_test_list import TestSuiteSpec, suites_from_xml
import subprocess
import socket
#=================================================
# Standard library modules.
#=================================================
Expand Down Expand Up @@ -277,8 +278,20 @@ def _main():
# Create the environment, and the Macros.cmake file
#
#
configure(machobj, build_dir, ["CMake"], compiler, mpilib, debug, os_)
machspecific = EnvMachSpecific(build_dir)
configure(machobj, build_dir, ["CMake"], compiler, mpilib, debug, os_,
unit_testing=True)
machspecific = EnvMachSpecific(build_dir, unit_testing=True)

machspecific.load_env(compiler, debug, mpilib)
os.environ["OS"] = os_
os.environ["COMPILER"] = compiler
os.environ["DEBUG"] = stringify_bool(debug)
os.environ["MPILIB"] = mpilib
if use_openmp:
os.environ["compile_threaded"] = "true"
os.environ["CC"] = find_executable("mpicc")
os.environ["FC"] = find_executable("mpif90")
os.environ["UNIT_TEST_HOST"] = socket.gethostname()

if no_mpirun:
mpirun_command = ""
Expand All @@ -292,18 +305,9 @@ def _main():

# We can get away with specifying case=None since we're using exe_only=True
mpirun_command, _ = machspecific.get_mpirun(case=None, attribs=mpi_attribs, exe_only=True)
mpirun_command = machspecific.get_resolved_value(mpirun_command)
logger.warn("mpirun command is '%s'"%mpirun_command)

machspecific.load_env(compiler, debug, mpilib)
os.environ["OS"] = os_
os.environ["COMPILER"] = compiler
os.environ["DEBUG"] = stringify_bool(debug)
os.environ["MPILIB"] = mpilib
if use_openmp:
os.environ["compile_threaded"] = "true"
os.environ["CC"] = find_executable("mpicc")
os.environ["FC"] = find_executable("mpif90")

#=================================================
# Run tests.
#=================================================
Expand Down

0 comments on commit 06c5645

Please sign in to comment.