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

266 lines
9.4 KiB
Python

#!/usr/bin/env python3
"""
Unit tests for subset_data
You can run this by:
python -m unittest test_unit_subset_data.py
"""
import unittest
import configparser
import argparse
import os
import sys
# -- add python/ctsm to path (needed if we want to run the test stand-alone)
_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir)
sys.path.insert(1, _CTSM_PYTHON)
# pylint: disable=wrong-import-position
from ctsm import unit_testing
from ctsm.subset_data import get_parser, setup_files, check_args
from ctsm.path_utils import path_to_ctsm_root
# pylint: disable=invalid-name
class TestSubsetData(unittest.TestCase):
"""
Basic class for testing SubsetData class in subset_data.py.
"""
def setUp(self):
sys.argv = ["subset_data", "point", "--create-surface"]
DEFAULTS_FILE = os.path.join(
os.getcwd(), "../tools/site_and_regional/default_data_2000.cfg"
)
self.parser = get_parser()
self.args = self.parser.parse_args()
self.cesmroot = path_to_ctsm_root()
self.defaults = configparser.ConfigParser()
self.defaults.read(os.path.join(self.cesmroot, "tools/site_and_regional", DEFAULTS_FILE))
def test_inputdata_setup_files_basic(self):
"""
Test
"""
check_args(self.args)
files = setup_files(self.args, self.defaults, self.cesmroot)
self.assertEqual(
files["fsurf_in"],
"surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc",
"fsurf_in filename not whats expected",
)
self.assertEqual(
files["fsurf_out"],
None,
"fsurf_out filename not whats expected",
)
self.assertEqual(
files["main_dir"],
"/glade/campaign/cesm/cesmdata/cseg/inputdata",
"main_dir directory not whats expected",
)
def test_inputdata_setup_files_inputdata_dne(self):
"""
Test that inputdata directory does not exist
"""
check_args(self.args)
self.defaults.set("main", "clmforcingindir", "/zztop")
with self.assertRaisesRegex(SystemExit, "inputdata directory does not exist"):
setup_files(self.args, self.defaults, self.cesmroot)
def test_check_args_nooutput(self):
"""
Test that check args aborts when no-output is asked for
"""
sys.argv = ["subset_data", "point"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(argparse.ArgumentError, "Must supply one of"):
check_args(self.args)
def test_check_args_notype(self):
"""
Test that check args aborts when no type is asked for
"""
sys.argv = ["subset_data"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(argparse.ArgumentError, "Must supply a positional argument:"):
check_args(self.args)
def test_check_args_badconfig(self):
"""
Test that check args aborts when a config file is entered that doesn't exist
"""
sys.argv = ["subset_data", "point", "--create-surface", "--cfg-file", "zztop"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError, "Entered default config file does not exist"
):
check_args(self.args)
def test_check_args_outsurfdat_provided(self):
"""
Test that check args allows an output surface dataset to be specified
when create-surface is on
"""
sys.argv = ["subset_data", "point", "--create-surface", "--out-surface", "outputsurface.nc"]
self.args = self.parser.parse_args()
check_args(self.args)
files = setup_files(self.args, self.defaults, self.cesmroot)
self.assertEqual(
files["fsurf_out"],
"outputsurface.nc",
"fsurf_out filename not whats expected",
)
def test_check_args_outsurfdat_fails_without_create_surface(self):
"""
Test that check args does not allow an output surface dataset to be specified
when create-surface is not on
"""
sys.argv = ["subset_data", "point", "--create-datm", "--out-surface", "outputsurface.nc"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError,
"out-surface option is given without the --create-surface option",
):
check_args(self.args)
def test_check_args_fails_for_timeseries_without_correct_surface_year(self):
"""
Test that check args does not allow landuse-timeseries to be used
without providing the correct start surface year
"""
sys.argv = ["subset_data", "point", "--create-landuse", "--create-surface"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError,
"--surf-year option is NOT set to 1850 and the --create-landuse option",
):
check_args(self.args)
def test_check_args_fails_for_surf_year_without_surface(self):
"""
Test that check args does not allow surf_year to be set
without the create-surface option
"""
sys.argv = ["subset_data", "point", "--create-datm", "--surf-year", "1850"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError,
"--surf-year option is set to something besides the default of 2000",
):
check_args(self.args)
def test_check_args_fails_for_landuse_without_surface(self):
"""
Test that check args does not allow landuse to be set
without the create-surface option
"""
sys.argv = ["subset_data", "point", "--create-landuse"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError,
"--create-landuse option requires the --create-surface option",
):
check_args(self.args)
def test_check_args_fails_bad_surface_year(self):
"""
Test that check args does not allow --surf-year to be bad
"""
sys.argv = ["subset_data", "point", "--create-surface", "--surf-year", "2305"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError, "--surf-year option can only be set to 1850 or 2000"
):
check_args(self.args)
def test_check_args_outsurfdat_fails_without_overwrite(self):
"""
Test that check args does not allow an output surface dataset to be specified
for an existing dataset without the overwrite option
"""
outfile = os.path.join(
os.getcwd(),
"ctsm/test/testinputs/",
"surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc",
)
self.assertTrue(os.path.exists(outfile), str(outfile) + " outfile should exist")
sys.argv = ["subset_data", "point", "--create-surface", "--out-surface", outfile]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError,
"out-surface filename exists and the overwrite option was not also selected",
):
check_args(self.args)
def test_inputdata_setup_files_bad_inputdata_arg(self):
"""
Test that inputdata directory provided on command line does not exist if it's bad
"""
check_args(self.args)
self.args.inputdatadir = "/zztop"
with self.assertRaisesRegex(SystemExit, "inputdata directory does not exist"):
setup_files(self.args, self.defaults, self.cesmroot)
def test_create_user_mods_without_create_mesh(self):
"""
Test that you can't run create user mods without also doing create_mesh
"""
sys.argv = ["subset_data", "region", "--create-user-mods", "--create-surface"]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError, "For regional cases, you can not create user_mods"
):
check_args(self.args)
def test_create_mesh_without_domain(self):
"""
Test that you can't run create mesh without domain
"""
sys.argv = [
"subset_data",
"region",
"--create-user-mods",
"--create-surface",
"--create-mesh",
]
self.args = self.parser.parse_args()
with self.assertRaisesRegex(
argparse.ArgumentError, "For regional cases, you can not create mesh files"
):
check_args(self.args)
def test_complex_option_works(self):
"""
Test that check_args won't flag a set of complex options that is valid
Do user-mods, surface and landuse-timeseries, as well as DATM, for verbose with crop
"""
sys.argv = [
"subset_data",
"region",
"--reg",
"testname",
"--create-user-mods",
"--create-surface",
"--create-landuse",
"--surf-year",
"1850",
"--create-mesh",
"--create-domain",
"--create-datm",
"--verbose",
"--crop",
]
self.args = self.parser.parse_args()
check_args(self.args)
if __name__ == "__main__":
unit_testing.setup_for_tests()
unittest.main()