334 lines
9.9 KiB
Python
334 lines
9.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""Unit tests for utils and config_utils
|
|
"""
|
|
|
|
import tempfile
|
|
import shutil
|
|
import unittest
|
|
import os
|
|
|
|
from ctsm import unit_testing
|
|
from ctsm.utils import fill_template_file
|
|
from ctsm.config_utils import lon_range_0_to_360, _handle_config_value
|
|
|
|
# Allow names that pylint doesn't like, because otherwise I find it hard
|
|
# to make readable unit test names
|
|
# pylint: disable=invalid-name
|
|
|
|
|
|
class TestUtilsFillTemplateFile(unittest.TestCase):
|
|
"""Tests of utils: fill_template_file"""
|
|
|
|
def setUp(self):
|
|
self._previous_dir = os.getcwd()
|
|
self._testdir = tempfile.mkdtemp()
|
|
|
|
def tearDown(self):
|
|
os.chdir(self._previous_dir)
|
|
shutil.rmtree(self._testdir, ignore_errors=True)
|
|
|
|
def test_fillTemplateFile_basic(self):
|
|
"""Basic test of fill_template_file"""
|
|
template_path = os.path.join(self._testdir, "template.txt")
|
|
final_path = os.path.join(self._testdir, "final.txt")
|
|
template_contents = """\
|
|
Hello
|
|
$foo
|
|
Goodbye
|
|
$bar
|
|
"""
|
|
with open(template_path, "w") as f:
|
|
f.write(template_contents)
|
|
|
|
fillins = {"foo": "aardvark", "bar": "zyzzyva"}
|
|
fill_template_file(template_path, final_path, fillins)
|
|
|
|
expected_final_text = """\
|
|
Hello
|
|
aardvark
|
|
Goodbye
|
|
zyzzyva
|
|
"""
|
|
with open(final_path) as f:
|
|
final_contents = f.read()
|
|
|
|
self.assertEqual(final_contents, expected_final_text)
|
|
|
|
|
|
class TestUtilsLonRange0to360(unittest.TestCase):
|
|
"""Test of utils: lon_range_0_to_360"""
|
|
|
|
def test_lonRange0To360_lonIsNeg180(self):
|
|
"""
|
|
Tests that negative inputs to lon_range_0_to_360 get 360 added to them
|
|
"""
|
|
inval = -180
|
|
result = lon_range_0_to_360(inval)
|
|
self.assertEqual(result, inval + 360)
|
|
|
|
def test_lonRange0To360_lonIsNegGreaterThan1(self):
|
|
"""
|
|
Tests that negative inputs to lon_range_0_to_360 get 360 added to them
|
|
"""
|
|
inval = -0.001
|
|
result = lon_range_0_to_360(inval)
|
|
self.assertEqual(result, inval + 360)
|
|
|
|
def test_lonRange0To360_lonIs0(self):
|
|
"""
|
|
Tests that input to lon_range_0_to_360 of 0 remains unchanged
|
|
"""
|
|
inval = 0
|
|
result = lon_range_0_to_360(inval)
|
|
self.assertEqual(result, inval)
|
|
|
|
def test_lonRange0To360_lonIs360(self):
|
|
"""
|
|
Tests that input to lon_range_0_to_360 of 360 remains unchanged
|
|
"""
|
|
inval = 360
|
|
result = lon_range_0_to_360(inval)
|
|
self.assertEqual(result, inval)
|
|
|
|
def test_lonRange0To360_outOfBounds(self):
|
|
"""
|
|
Tests that lon_range_0_to_360 aborts gracefully when lon = 361
|
|
"""
|
|
with self.assertRaisesRegex(SystemExit, "lon_in needs to be in the range 0 to 360"):
|
|
_ = lon_range_0_to_360(361)
|
|
|
|
|
|
class TestUtilsHandleConfigValue(unittest.TestCase):
|
|
"""Test of utils: _handle_config_value"""
|
|
|
|
def test_handleConfigValue_UnsetCantBeUnset(self):
|
|
"""
|
|
Tests the handling of UNSET variable read in from a .cfg file
|
|
for which can_be_unset = False
|
|
"""
|
|
val = "UNSET"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = False
|
|
convert_to_type = None
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
errmsg = "Must set a value for .cfg file variable: {}".format(item)
|
|
|
|
with self.assertRaisesRegex(SystemExit, errmsg):
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
def test_handleConfigValue_UnsetCanBeUnset(self):
|
|
"""
|
|
Tests the handling of UNSET variable read in from a .cfg file
|
|
for which can_be_unset = True
|
|
"""
|
|
val = "UNSET"
|
|
item = "varname_in_cfg_file"
|
|
default = [True, False, True]
|
|
is_list = True
|
|
convert_to_type = None
|
|
can_be_unset = True
|
|
allowed_values = None
|
|
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
self.assertEqual(val, default)
|
|
|
|
def test_handleConfigValue_convertToBoolFail(self):
|
|
"""
|
|
Tests the handling of misspelled boolean read in from a .cfg file
|
|
Also test whether the code can read a list of booleans
|
|
"""
|
|
val = "False Tree False" # intentionally misspelled True
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = True
|
|
convert_to_type = bool
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
errmsg = "Non-boolean value found for .cfg file variable: {}".format(item)
|
|
|
|
with self.assertRaisesRegex(SystemExit, errmsg):
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
def test_handleConfigValue_convertToBoolPass(self):
|
|
"""
|
|
Tests the handling of boolean read in from a .cfg file
|
|
Also test whether the code can read a list of booleans
|
|
"""
|
|
val = "yes no"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = True
|
|
convert_to_type = bool
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
self.assertTrue(val[0])
|
|
self.assertFalse(val[1])
|
|
|
|
def test_handleConfigValue_convertToTypePass(self):
|
|
"""
|
|
Tests the handling of non-boolean list from a .cfg file
|
|
"""
|
|
val = "-9 0.001"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = True
|
|
convert_to_type = float
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
self.assertEqual(val[0], -9)
|
|
self.assertEqual(val[1], 0.001)
|
|
|
|
def test_handleConfigValue_convertToTypeFail(self):
|
|
"""
|
|
Tests the handling of an incorrectly entered list from a .cfg file
|
|
"""
|
|
val = "1 2 3 x 5 6 7"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = True
|
|
convert_to_type = float
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
errmsg = "Wrong type for .cfg file variable: {}".format(item)
|
|
|
|
with self.assertRaisesRegex(SystemExit, errmsg):
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
def test_handleConfigValue_allowedValsFail(self):
|
|
"""
|
|
Tests that the code aborts if val does not include all allowed_values
|
|
"""
|
|
val = "1 2 3 4.5 6 7"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = True
|
|
convert_to_type = float
|
|
can_be_unset = False
|
|
allowed_values = [1, 2, 3, 4, 5, 6, 7]
|
|
v = 4.5 # v must equal the misstyped value in val
|
|
errmsg = "{} is not an allowed value for {} in .cfg file. Check allowed_values".format(
|
|
v, item
|
|
)
|
|
|
|
with self.assertRaisesRegex(SystemExit, errmsg):
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
def test_handleConfigValue_isListFail(self):
|
|
"""
|
|
Tests that the code aborts if we forget to set is_list = True
|
|
"""
|
|
val = "True False"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = False
|
|
convert_to_type = bool
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
errmsg = "More than 1 element found for .cfg file variable: {}".format(item)
|
|
|
|
with self.assertRaisesRegex(SystemExit, errmsg):
|
|
val = _handle_config_value(
|
|
var=val,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
def test_handleConfigValue_isListFalse(self):
|
|
"""
|
|
Tests that the code works for a basic case of is_list = False
|
|
"""
|
|
val_in = "0.5"
|
|
item = "varname_in_cfg_file"
|
|
default = None
|
|
is_list = False
|
|
convert_to_type = float
|
|
can_be_unset = False
|
|
allowed_values = None
|
|
|
|
val_out = _handle_config_value(
|
|
var=val_in,
|
|
default=default,
|
|
item=item,
|
|
is_list=is_list,
|
|
convert_to_type=convert_to_type,
|
|
can_be_unset=can_be_unset,
|
|
allowed_values=allowed_values,
|
|
)
|
|
|
|
self.assertEqual(val_out, float(val_in))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unit_testing.setup_for_tests()
|
|
unittest.main()
|