clm5/python/ctsm/test/test_unit_lilac_build_ctsm.py
2024-05-09 15:14:01 +08:00

304 lines
12 KiB
Python

#!/usr/bin/env python3
"""Unit tests for lilac_build_ctsm
"""
import unittest
from unittest.mock import patch
from io import StringIO
from ctsm import unit_testing
from ctsm.lilac_build_ctsm import _commandline_args, _check_and_transform_os
# Allow names that pylint doesn't like, because otherwise I find it hard
# to make readable unit test names
# pylint: disable=invalid-name
# pylint: disable=line-too-long
class TestBuildCtsm(unittest.TestCase):
"""Tests of lilac_build_ctsm"""
# ------------------------------------------------------------------------
# Tests of _commandline_args
# ------------------------------------------------------------------------
def test_commandlineArgs_rebuild_valid(self):
"""Test _commandline_args with --rebuild, with a valid argument list (no disallowed args)"""
# pylint: disable=no-self-use
_ = _commandline_args(args_to_parse=["build/directory", "--rebuild"])
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_rebuild_invalid1(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is invalid with this option
This tests an argument that is required for non-rebuilds, without a dash
"""
expected_re = r"--compiler cannot be provided if --rebuild is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=["build/directory", "--rebuild", "--compiler", "intel"]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_rebuild_invalid2(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is invalid with this option
This tests an argument that is required for new machines, without a dash
"""
expected_re = r"--os cannot be provided if --rebuild is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(args_to_parse=["build/directory", "--rebuild", "--os", "linux"])
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_rebuild_invalid3(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is invalid with this option
This tests an argument that is required for new machines, with a dash
"""
expected_re = r"--netcdf-path cannot be provided if --rebuild is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--rebuild",
"--netcdf-path",
"/path/to/netcdf",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_rebuild_invalid4(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is invalid with this option
This tests an argument that is optional for new non-rebuild
that isn't None
"""
expected_re = r"--no-build cannot be provided if --rebuild is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(args_to_parse=["build/directory", "--rebuild", "--no-build"])
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_rebuild_invalid5(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is invalid with this option
This tests an argument that is optional for new machines, which also has a default
that isn't None
"""
expected_re = r"--gmake cannot be provided if --rebuild is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=["build/directory", "--rebuild", "--gmake", "mymake"]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
def test_commandlineArgs_noRebuild_valid(self):
"""Test _commandline_args without --rebuild or --machine, with a valid argument list
(all required things present)
"""
# pylint: disable=no-self-use
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--os",
"linux",
"--compiler",
"intel",
"--netcdf-path",
"/path/to/netcdf",
"--esmf-mkfile-path",
"/path/to/esmf/lib/esmf.mk",
"--max-mpitasks-per-node",
"16",
"--no-pnetcdf",
]
)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_noRebuild_invalid1(self, mock_stderr):
"""Test _commandline_args without --rebuild or --machine, with a missing required argument
This tests an argument in the non-rebuild-required list
"""
expected_re = r"--compiler must be provided if --rebuild is not set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--os",
"linux",
"--netcdf-path",
"/path/to/netcdf",
"--esmf-mkfile-path",
"/path/to/esmf/lib/esmf.mk",
"--max-mpitasks-per-node",
"16",
"--no-pnetcdf",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_noRebuild_invalid2(self, mock_stderr):
"""Test _commandline_args without --rebuild or --machine, with a missing required argument
This tests an argument in the new-machine-required list
"""
expected_re = r"--os must be provided if neither --machine nor --rebuild are set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--compiler",
"intel",
"--netcdf-path",
"/path/to/netcdf",
"--esmf-mkfile-path",
"/path/to/esmf/lib/esmf.mk",
"--max-mpitasks-per-node",
"16",
"--no-pnetcdf",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_noRebuild_invalidNeedToDictatePnetcdf(self, mock_stderr):
"""Test _commandline_args without --rebuild or --machine: invalid b/c nothing specified for pnetcdf"""
expected_re = (
r"For a user-defined machine, need to specify either --no-pnetcdf or --pnetcdf-path"
)
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--os",
"linux",
"--compiler",
"intel",
"--netcdf-path",
"/path/to/netcdf",
"--esmf-mkfile-path",
"/path/to/esmf/lib/esmf.mk",
"--max-mpitasks-per-node",
"16",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_noRebuild_invalidConflictingPnetcdf(self, mock_stderr):
"""Test _commandline_args without --rebuild or --machine: invalid b/c of conflicting specifications for pnetcdf"""
expected_re = r"--no-pnetcdf cannot be given if you set --pnetcdf-path"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--os",
"linux",
"--compiler",
"intel",
"--netcdf-path",
"/path/to/netcdf",
"--esmf-mkfile-path",
"/path/to/esmf/lib/esmf.mk",
"--max-mpitasks-per-node",
"16",
"--no-pnetcdf",
"--pnetcdf-path",
"/path/to/pnetcdf",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
def test_commandlineArgs_machine_valid(self):
"""Test _commandline_args with --machine, with a valid argument list
(all required things present)
"""
# pylint: disable=no-self-use
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--machine",
"mymachine",
"--compiler",
"intel",
]
)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_machine_missingRequired(self, mock_stderr):
"""Test _commandline_args with --machine, with a missing required argument"""
expected_re = r"--compiler must be provided if --rebuild is not set"
with self.assertRaises(SystemExit):
_ = _commandline_args(args_to_parse=["build/directory", "--machine", "mymachine"])
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_machine_illegalArg1(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is illegal with this option
This tests an argument that is required for new machines
"""
expected_re = r"--os cannot be provided if --machine is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--machine",
"mymachine",
"--compiler",
"intel",
"--os",
"linux",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
@patch("sys.stderr", new_callable=StringIO)
def test_commandlineArgs_machine_illegalArg2(self, mock_stderr):
"""Test _commandline_args with --rebuild, with an argument that is illegal with this option
This tests an argument that is optional for new machines
"""
expected_re = r"--gmake cannot be provided if --machine is set"
with self.assertRaises(SystemExit):
_ = _commandline_args(
args_to_parse=[
"build/directory",
"--machine",
"mymachine",
"--compiler",
"intel",
"--gmake",
"mymake",
]
)
self.assertRegex(mock_stderr.getvalue(), expected_re)
# ------------------------------------------------------------------------
# Tests of _check_and_transform_os
# ------------------------------------------------------------------------
def test_checkAndTransformOs_valid(self):
"""Test _check_and_transform_os with valid input"""
os = _check_and_transform_os("linux")
self.assertEqual(os, "LINUX")
def test_checkAndTransformOs_invalid(self):
"""Test _check_and_transform_os with invalid input"""
with self.assertRaises(ValueError):
_ = _check_and_transform_os("bad_os")
if __name__ == "__main__":
unit_testing.setup_for_tests()
unittest.main()