From e52286109559d39c28090467ac07e3206a713b2d Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 09:40:13 -0500 Subject: [PATCH 01/12] small grammar correction for if we're ungraciously provided >3 files in a minute --- gridded_glm/libexec/{ => gridded_glm}/_minute_gridder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename gridded_glm/libexec/{ => gridded_glm}/_minute_gridder.py (99%) diff --git a/gridded_glm/libexec/_minute_gridder.py b/gridded_glm/libexec/gridded_glm/_minute_gridder.py similarity index 99% rename from gridded_glm/libexec/_minute_gridder.py rename to gridded_glm/libexec/gridded_glm/_minute_gridder.py index d43be6a..70afac7 100644 --- a/gridded_glm/libexec/_minute_gridder.py +++ b/gridded_glm/libexec/gridded_glm/_minute_gridder.py @@ -339,7 +339,7 @@ def grid_minute(minute, args): # do we have three input files for this minute? if len(minute_files) != 3: - log.error("Minute {} only has {} input file(s). A gridded file will not be generated.".format(minute, len(minute_files))) + log.error("Minute {} has {} input file(s). We expected 3. A gridded file will not be generated.".format(minute, len(minute_files))) return # do the gridding -- GitLab From 0bf7e950147d7fea827a9fe4b1278eda6981a135 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 09:49:33 -0500 Subject: [PATCH 02/12] add our first set of pytest-based regression tests --- gridded_glm/bin/cspp-geo-gglm.sh | 2 +- gridded_glm/libexec/gridded_glm/__init__.py | 0 .../libexec/gridded_glm/_minute_gridder.py | 7 +- tests/.gitattributes | 1 + ...0000000_e20220740000200_c20220740000227.nc | 3 + ...0000200_e20220740000400_c20220740000428.nc | 3 + ...0000400_e20220740001000_c20220740001027.nc | 3 + ...0001000_e20220740001200_c20220740001225.nc | 3 + ...0001200_e20220740001400_c20220740001419.nc | 3 + ...0001400_e20220740002000_c20220740002019.nc | 3 + ...0002000_e20220740002200_c20220740002228.nc | 3 + ...0002200_e20220740002400_c20220740002427.nc | 3 + ...0002400_e20220740003000_c20220740003018.nc | 3 + tests/test_regressions.py | 139 ++++++++++++++++++ 14 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 gridded_glm/libexec/gridded_glm/__init__.py create mode 100644 tests/.gitattributes create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001000_e20220740001200_c20220740001225.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001400_e20220740002000_c20220740002019.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc create mode 100644 tests/test_regressions.py diff --git a/gridded_glm/bin/cspp-geo-gglm.sh b/gridded_glm/bin/cspp-geo-gglm.sh index fb2bfff..7320b71 100755 --- a/gridded_glm/bin/cspp-geo-gglm.sh +++ b/gridded_glm/bin/cspp-geo-gglm.sh @@ -30,4 +30,4 @@ source $CSPP_GEO_GGLM_HOME/libexec/env.sh # Call the python module to do the processing, passing all arguments export PROG_NAME="${BASH_SOURCE[0]}" -python3 $CSPP_GEO_GGLM_HOME/libexec/_minute_gridder.py "$@" +python3 $CSPP_GEO_GGLM_HOME/libexec/gridded_glm/_minute_gridder.py "$@" diff --git a/gridded_glm/libexec/gridded_glm/__init__.py b/gridded_glm/libexec/gridded_glm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gridded_glm/libexec/gridded_glm/_minute_gridder.py b/gridded_glm/libexec/gridded_glm/_minute_gridder.py index 70afac7..321aff8 100644 --- a/gridded_glm/libexec/gridded_glm/_minute_gridder.py +++ b/gridded_glm/libexec/gridded_glm/_minute_gridder.py @@ -403,7 +403,7 @@ def grid_minute(minute, args): # tempdir cleans itself up via atexit, above -if __name__ == '__main__': +def main(): # freeze_support() # nb. I don't think this is needed as we're not making windows execs at this time parser = create_parser() args = parser.parse_args() @@ -461,4 +461,7 @@ if __name__ == '__main__': log.error(e) log.debug(traceback.format_exc()) log.error(f"Gridding minute {m} failed.") - continue \ No newline at end of file + continue + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/tests/.gitattributes b/tests/.gitattributes new file mode 100644 index 0000000..9abd205 --- /dev/null +++ b/tests/.gitattributes @@ -0,0 +1 @@ +*.nc filter=lfs diff=lfs merge=lfs -text diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc new file mode 100644 index 0000000..54394a4 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa8371db66811b43030f0e7bfbd36d8979650022b3f241087723a98c63ecea35 +size 407925 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc new file mode 100644 index 0000000..25d0659 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d58219b5995807cee8d12ad668a56b85a6d28691e98aae424fc7b70f9a86c995 +size 379253 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc new file mode 100644 index 0000000..4a76c41 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf7d7fb938664e5349b793376e7438b7e8b006314a0481421ae6fc1cc25853e1 +size 358773 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001000_e20220740001200_c20220740001225.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001000_e20220740001200_c20220740001225.nc new file mode 100644 index 0000000..fad137c --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001000_e20220740001200_c20220740001225.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5428944ea5f2a566f8c99ee6400ed96a71db07d8ee9f67a987baa8081e418f88 +size 440693 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc new file mode 100644 index 0000000..d6e8350 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62d2e0857dbf4667230e0dec0686e2301bcbd33cd8214b9a8f035026f8242e03 +size 401781 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001400_e20220740002000_c20220740002019.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001400_e20220740002000_c20220740002019.nc new file mode 100644 index 0000000..211ec83 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740001400_e20220740002000_c20220740002019.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc1214302c8df0217ae504ebbc5eeba39dc87910046e90e99b621b6516410b4c +size 375157 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc new file mode 100644 index 0000000..ef686db --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d03d3f6dc115fd17325ad4af9b47a9b4d152b028d3a17d96cdc2281a3d7e97d6 +size 385397 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc new file mode 100644 index 0000000..b2a5032 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3c40ad0642eb7e5795c1b3e17c9f6ebdacaeb54e56ee4416ac270b6e60627d7 +size 389493 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc new file mode 100644 index 0000000..6768e3a --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3abf234f7d2b2e3853779bdb20efc29a4a9f5c6981612cff609fb3b0ed941db2 +size 403829 diff --git a/tests/test_regressions.py b/tests/test_regressions.py new file mode 100644 index 0000000..42771f0 --- /dev/null +++ b/tests/test_regressions.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +""" +Gridded GLM test suite +""" + +# setting PYTHONPATH so we can work +import sys +import os +TESTDIR = os.path.dirname(__file__) +TOPDIR = os.path.dirname(TESTDIR) +PYDIR = os.path.join(TOPDIR, 'gridded_glm/libexec') +sys.path.append(PYDIR) +MINUTE_GRIDDER = os.path.join(PYDIR, "gridded_glm/_minute_gridder.py") +#from gridded_glm import _minute_gridder as mg + +#import argparse +#from unittest import mock +import subprocess + +from glob import glob +def check_fileglob(fileglob_pattern, nfiles=1): + files = glob(fileglob_pattern) + if len(files) == nfiles: + return True + else: + return False + +import pytest +import tempfile +import os +import shutil +@pytest.fixture(autouse=True) +def run_before_and_after_tests(tmp_path): + """Fixture to execute asserts before and after a test is run""" + # Setup: fill with any logic you want + os.chdir(tmp_path) + print(os.getcwd()) + + yield # this is where the testing happens + + print(glob("*")) + # Teardown : fill with any logic you want + shutil.rmtree(tmp_path) + + +def test_simple(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "full", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G16_s20220740000000_e20220740001000_c*.nc")) + +def test_issue5_3minutes(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001000_e20220740001200_c20220740001225.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001400_e20220740002000_c20220740002019.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740000000_e20220740001000_c*.nc")) + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740001000_e20220740002000_c*.nc")) + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740002000_e20220740003000_c*.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000100.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000200.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000100.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000200.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000100.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000200.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000100.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000200.nc")) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc")) + +def test_issue5_crossminutes(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + +def test_issue5_realtime_fail1(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + "--realtime", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + +def test_issue5_realtime_fail2(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + "--realtime", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + +def test_issue5_realtime_succeed1(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + "--realtime", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740002000_e20220740003000_c*", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) -- GitLab From 385f5da97ccdbc9c76c1ba59d56ecb63627bc1a0 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 09:55:10 -0500 Subject: [PATCH 03/12] fix the filenames produced when given multiple minutes of input (ref: test_issue5_3minutes) --- .../libexec/gridded_glm/_minute_gridder.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/gridded_glm/libexec/gridded_glm/_minute_gridder.py b/gridded_glm/libexec/gridded_glm/_minute_gridder.py index 321aff8..56c6e3d 100644 --- a/gridded_glm/libexec/gridded_glm/_minute_gridder.py +++ b/gridded_glm/libexec/gridded_glm/_minute_gridder.py @@ -158,19 +158,19 @@ def get_start_end(filenames, start_time=None, end_time=None): return start_time, end_time -def get_sector_shortstring(args): - if args.goes_sector == 'full': +def get_sector_shortstring(goes_sector): + if goes_sector == 'full': return 'F' - elif args.goes_sector == 'conus': + elif goes_sector == 'conus': return 'C' - elif args.goes_sector == 'meso' or args.goes_sector == 'meso1': + elif goes_sector == 'meso' or goes_sector == 'meso1': return 'M1' - elif args.goes_sector == 'meso2': + elif goes_sector == 'meso2': return 'M2' else: raise RuntimeError("sector not recognized") -def get_outpath_base(args): +def get_outpath_base(filenames, goes_sector, system_environment_prefix): """create a base outpath string to feed glmtools from glmtools: @@ -181,16 +181,16 @@ def get_outpath_base(args): start_time, end_time: datetimes that can be used with strftime syntax, e.g. './{start_time:%y/%b/%d}/GLM_{start_time:%Y%m%d_%H%M%S}.nc' """ - ordered_filenames = sorted(args.filenames) + ordered_filenames = sorted(filenames) _, _, platform, start_time, _, _ = parse_glm_filename(os.path.basename(ordered_filenames[0])) _, _, _, _, end_time, _ = parse_glm_filename(os.path.basename(ordered_filenames[-1])) - sector_short = get_sector_shortstring(args) + sector_short = get_sector_shortstring(goes_sector) mode = "M3" # FIXME: is GLM always in M3? # example string: OR_GLM-L2-GLMC-M3_G17_s20182750032000_e20182750033000_c20210431923130.nc dsname = "{environment_prefix}_GLM-L2-GLM{sector_short}-{mode}_{platform}_s{start_time}_e{end_time}_c{created_time}.nc".format( - environment_prefix=args.system_environment_prefix, + environment_prefix=system_environment_prefix, sector_short=sector_short, mode=mode, platform=platform, @@ -225,7 +225,7 @@ def grid_setup(glm_files, args, work_dir=os.getcwd()): base_date = datetime(start_time.year, start_time.month, start_time.day) proj_name = 'geos' - outputpath = os.path.join(work_dir, get_outpath_base(args)) # GLMTools expects a template in addition to the path + outputpath = os.path.join(work_dir, get_outpath_base(glm_files, args.goes_sector, args.system_environment_prefix)) # GLMTools expects a template in addition to the path goes_position = get_goes_position(glm_files) -- GitLab From e024b24a570c1a516f03e822d3f19ae3d7a5ff1e Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 10:06:24 -0500 Subject: [PATCH 04/12] adds the rest of our issue5 tests --- tests/test_regressions.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 42771f0..1c7f5d3 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -43,7 +43,7 @@ def run_before_and_after_tests(tmp_path): shutil.rmtree(tmp_path) -def test_simple(): +def test_simple_success(): completed_process = subprocess.run(['python', MINUTE_GRIDDER, "--goes-sector", "full", @@ -54,6 +54,35 @@ def test_simple(): assert completed_process.returncode == 0 assert(check_fileglob("CG_GLM-L2-GLMF-M3_G16_s20220740000000_e20220740001000_c*.nc")) +def test_issue5_fail1_3(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + +def test_issue5_fail2_1and3(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + +def test_issue5_fail2_2and3(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-*.nc", 0)) + assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) + def test_issue5_3minutes(): completed_process = subprocess.run(['python', MINUTE_GRIDDER, -- GitLab From e0224e0e72cf875156e2e0801b4a5dfe4f1f7fd9 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 10:28:55 -0500 Subject: [PATCH 05/12] add non-zero exit codes for failure cases --- .../libexec/gridded_glm/_minute_gridder.py | 24 ++++++++++++------- tests/test_regressions.py | 16 +++++++------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/gridded_glm/libexec/gridded_glm/_minute_gridder.py b/gridded_glm/libexec/gridded_glm/_minute_gridder.py index 56c6e3d..f0969b1 100644 --- a/gridded_glm/libexec/gridded_glm/_minute_gridder.py +++ b/gridded_glm/libexec/gridded_glm/_minute_gridder.py @@ -339,8 +339,8 @@ def grid_minute(minute, args): # do we have three input files for this minute? if len(minute_files) != 3: - log.error("Minute {} has {} input file(s). We expected 3. A gridded file will not be generated.".format(minute, len(minute_files))) - return +# log.error("Minute {} has {} input file(s). We expected 3. A gridded file will not be generated.".format(minute, len(minute_files))) + raise RuntimeError("Minute {} has {} input file(s). We expected 3. A gridded file will not be generated.".format(minute, len(minute_files))) # do the gridding gridder, glm_filenames, start_time, end_time, grid_kwargs = grid_setup(minute_files, args, work_dir=tempdir_path) @@ -405,6 +405,7 @@ def grid_minute(minute, args): def main(): # freeze_support() # nb. I don't think this is needed as we're not making windows execs at this time + errors = False parser = create_parser() args = parser.parse_args() @@ -422,20 +423,21 @@ def main(): if args.realtime: if len(args.filenames) != 1: log.error("realtime mode only accepts one input file") - exit(1) + return 1 glminfo = parse_glm_filename(os.path.basename(args.filenames[0])) globstring = "{}_{}_{}_s{}*".format(glminfo[0], glminfo[1], glminfo[2], glminfo[3].strftime("%Y%j%H%M")) fileglob = glob(os.path.join(os.path.dirname(args.filenames[0]), globstring)) if len(fileglob) != 3: - log.error("There are not (yet) three GLM files from this minute. This may be expected. Exiting.") - exit(0) + log.error("There are not yet three GLM files from this minute. This may be expected. Exiting.") + # we expect people using realtime mode to run this on every file, so a return code of 0 is expected on a file before the end of the minute + return 0 # this allows a user to use realtime mode to process a large directory of GLM without # creating the same output file multiple times if sorted(fileglob)[-1] != args.filenames[0]: log.error("This is not the last file from this minute. Exiting.") - exit(0) + return 0 args.filenames = fileglob @@ -443,7 +445,7 @@ def main(): for f in args.filenames: if not os.path.exists(f): log.error("Tried to grid file that does not exist: {}".format(f)) - exit(1) + return 1 # set up output dir os.makedirs(args.output_dir, exist_ok=True) @@ -458,10 +460,16 @@ def main(): try: grid_minute(m, args) except Exception as e: + errors = True log.error(e) log.debug(traceback.format_exc()) log.error(f"Gridding minute {m} failed.") continue + if errors: + return 1 + else: + return 0 + if __name__ == '__main__': - main() \ No newline at end of file + sys.exit(main()) \ No newline at end of file diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 1c7f5d3..d230188 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -59,7 +59,7 @@ def test_issue5_fail1_3(): MINUTE_GRIDDER, os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), ]) - assert completed_process.returncode == 0 + assert completed_process.returncode == 1 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) @@ -69,7 +69,7 @@ def test_issue5_fail2_1and3(): os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), ]) - assert completed_process.returncode == 0 + assert completed_process.returncode == 1 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) @@ -79,7 +79,7 @@ def test_issue5_fail2_2and3(): os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), ]) - assert completed_process.returncode == 0 + assert completed_process.returncode == 1 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) @@ -115,7 +115,7 @@ def test_issue5_3minutes(): assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000200.nc")) assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc")) -def test_issue5_crossminutes(): +def test_issue5_crossminutes_fail(): completed_process = subprocess.run(['python', MINUTE_GRIDDER, "--goes-sector", "conus", @@ -124,11 +124,11 @@ def test_issue5_crossminutes(): os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc"), os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), ]) - assert completed_process.returncode == 0 + assert completed_process.returncode == 1 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) -def test_issue5_realtime_fail1(): +def test_issue5_realtime_early1(): completed_process = subprocess.run(['python', MINUTE_GRIDDER, "--goes-sector", "conus", @@ -136,11 +136,12 @@ def test_issue5_realtime_fail1(): "--realtime", os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), ]) + # we expect people using realtime mode to run this on every file, so a return code of 0 is expected on a file before the end of the minute assert completed_process.returncode == 0 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) -def test_issue5_realtime_fail2(): +def test_issue5_realtime_early2(): completed_process = subprocess.run(['python', MINUTE_GRIDDER, "--goes-sector", "conus", @@ -148,6 +149,7 @@ def test_issue5_realtime_fail2(): "--realtime", os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740001200_e20220740001400_c20220740001419.nc"), ]) + # we expect people using realtime mode to run this on every file, so a return code of 0 is expected on a file before the end of the minute assert completed_process.returncode == 0 assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) -- GitLab From 2156fcb739963c3270d041bb794344c4034d743b Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 10:30:45 -0500 Subject: [PATCH 06/12] add the issue7 regression test --- tests/test_regressions.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index d230188..e713ebc 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -168,3 +168,27 @@ def test_issue5_realtime_succeed1(): assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc", 1)) assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) + +# test for providing two minutes with a minute in between that has no input +# the middle minute should produce no output +def test_issue7(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002000_e20220740002200_c20220740002228.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002200_e20220740002400_c20220740002427.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), + ]) + assert completed_process.returncode == 0 + # check for 2 output gridded files + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16*.nc", 2)) + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740002000_e20220740003000_c*", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) + -- GitLab From 5fcfb76fa670e1dbad85bf1c714d5b7216740c89 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 10:37:28 -0500 Subject: [PATCH 07/12] add the issue22 regression test --- tests/test_regressions.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index e713ebc..63ab574 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -192,3 +192,17 @@ def test_issue7(): assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) +# test for proper handling of negative center lat/lons +def test_issue22(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "-96.85", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMM1-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) + -- GitLab From 531ddfd99d2e643ee2fb070673fd34ce98248e6b Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 10:51:53 -0500 Subject: [PATCH 08/12] add issue23 & issue24 tests --- tests/test_regressions.py | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 63ab574..c6ca181 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -206,3 +206,95 @@ def test_issue22(): assert completed_process.returncode == 0 assert(check_fileglob("CG_GLM-L2-GLMM1-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) +def test_issue23_oor_lon_high(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "200", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode != 0 + assert(check_fileglob("CG_GLM-L2-*.nc", 0)) + +def test_issue23_oor_lon_low(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "-181", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode != 0 + assert(check_fileglob("CG_GLM-L2-*.nc", 0)) + +def test_issue23_oor_lat_high(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "91", + "--ctr-lon", "-96.85", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode != 0 + assert(check_fileglob("CG_GLM-L2-*.nc", 0)) + +def test_issue23_oor_lat_low(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "-90.30", + "--ctr-lon", "-96.85", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode != 0 + assert(check_fileglob("CG_GLM-L2-*.nc", 0)) + +def test_issue24_meso1(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "-96.85", + "--goes-sector", "meso1", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMM1-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) + +def test_issue24_meso2(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "-96.85", + "--goes-sector", "meso2", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMM2-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) + +def test_issue24_meso2_tiles(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "32.05", + "--ctr-lon", "-96.85", + "--goes-sector", "meso2", + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMM2-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMM2-M3_G16_T01_20220315000100.nc", 1)) -- GitLab From 5f265f6d08843e80172e9fb198cd32b86881ab53 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 11:17:14 -0500 Subject: [PATCH 09/12] add the issue38 regression test --- tests/test_regressions.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test_regressions.py b/tests/test_regressions.py index c6ca181..2ab1b3e 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -42,6 +42,8 @@ def run_before_and_after_tests(tmp_path): # Teardown : fill with any logic you want shutil.rmtree(tmp_path) +import netCDF4 +import numpy as np def test_simple_success(): completed_process = subprocess.run(['python', @@ -298,3 +300,25 @@ def test_issue24_meso2_tiles(): assert completed_process.returncode == 0 assert(check_fileglob("CG_GLM-L2-GLMM2-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) assert(check_fileglob("CSPP_OR_GLM-L2-GLMM2-M3_G16_T01_20220315000100.nc", 1)) + +# test that we still produce a file when there's no valid data inside the gridded region +def test_issue38_no_valid_data(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--ctr-lat", "43.0722", + "--ctr-lon", "-89.4008", + "--goes-sector", "meso", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMM1-M3_G16_s20220740000000_e20220740001000_c*.nc", 1)) + + # check that the file contents are blank too + mesofilename = glob("CG_GLM-L2-GLMM1-M3_G16_s20220740000000_e20220740001000_c*.nc")[0] + ds = netCDF4.Dataset(mesofilename, 'r') + assert(ds.variables['minimum_flash_area'][:].all() is np.ma.masked) + assert(ds.variables['total_energy'][:].all() is np.ma.masked) + assert(ds.variables['total_energy'][:].all() is np.ma.masked) + assert((ds.variables['DQF'][:] == 0).all()) \ No newline at end of file -- GitLab From 0af082ebf8969c22c3cb158f1a5918e98968aa0b Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 14:35:29 -0500 Subject: [PATCH 10/12] separate tests out into basic functionality & regression testing, add some functionality tests --- setup.cfg | 2 + tests/conftest.py | 30 ++++ tests/test-inputs/.gitignore | 2 + ...1921000_e20222631921200_c20222631921214.nc | 3 + ...1921200_e20222631921400_c20222631921418.nc | 3 + ...1921400_e20222631922000_c20222631922019.nc | 3 + tests/test_functionality.py | 136 ++++++++++++++++++ tests/test_regressions.py | 68 +-------- tests/testlib/common.py | 18 +++ 9 files changed, 203 insertions(+), 62 deletions(-) create mode 100644 setup.cfg create mode 100644 tests/conftest.py create mode 100644 tests/test-inputs/.gitignore create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921000_e20222631921200_c20222631921214.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921200_e20222631921400_c20222631921418.nc create mode 100644 tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921400_e20222631922000_c20222631922019.nc create mode 100644 tests/test_functionality.py create mode 100644 tests/testlib/common.py diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..d09983e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[tool:pytest] +norecursedirs=tests/lib diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..66c3aba --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,30 @@ +""" +Shared config for all tests +""" +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), 'lib')) + + + +import pytest +import shutil +import pprint +from glob import glob + +@pytest.fixture(autouse=True) +def run_before_and_after_tests(tmp_path): + """Fixture to execute asserts before and after a test is run""" + # Setup: fill with any logic you want + os.chdir(tmp_path) + print(os.getcwd()) + + yield # this is where the testing happens + + # print the current directory's list of files + pp = pprint.PrettyPrinter() + pp.pprint(glob("*")) + + # Teardown : fill with any logic you want + shutil.rmtree(tmp_path) + diff --git a/tests/test-inputs/.gitignore b/tests/test-inputs/.gitignore new file mode 100644 index 0000000..0bee393 --- /dev/null +++ b/tests/test-inputs/.gitignore @@ -0,0 +1,2 @@ +# ignore all G18 test files until G18 data can be made public +OR_GLM-L2-LCFA_G18* diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921000_e20222631921200_c20222631921214.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921000_e20222631921200_c20222631921214.nc new file mode 100644 index 0000000..a96b2f8 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921000_e20222631921200_c20222631921214.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6bdb97180067489205cea8b7fcd8640907e0e59c4de74157f2d6e5207bd062f +size 155423 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921200_e20222631921400_c20222631921418.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921200_e20222631921400_c20222631921418.nc new file mode 100644 index 0000000..743991d --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921200_e20222631921400_c20222631921418.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd7509d24f141096d66a579e8a6ea9514022f0f48780c32950a2729829a97b1b +size 157110 diff --git a/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921400_e20222631922000_c20222631922019.nc b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921400_e20222631922000_c20222631922019.nc new file mode 100644 index 0000000..4954ae7 --- /dev/null +++ b/tests/test-inputs/OR_GLM-L2-LCFA_G17_s20222631921400_e20222631922000_c20222631922019.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b530b9bd17f9096a2093ca9c7d5c685e3b8ed8b1ae79198a872fae0c3a05bcd +size 154428 diff --git a/tests/test_functionality.py b/tests/test_functionality.py new file mode 100644 index 0000000..4241ec2 --- /dev/null +++ b/tests/test_functionality.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +""" +Gridded GLM basic functionality tests +""" + +import subprocess +import os +import warnings + +from testlib.common import TESTDIR, MINUTE_GRIDDER +from testlib.common import check_fileglob + +def test_simple_success(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "full", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G16_s20220740000000_e20220740001000_c*.nc")) + +# formerly the issue5 realtime success test +def test_realtime(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--goes-sector", "conus", + "--create-tiles", + "--realtime", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740002000_e20220740003000_c*", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) + +def test_g16(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G16_*.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMF-M3_G16_T*.nc", 17)) + + assert(check_fileglob('CG_GLM-L2-GLMF-M3_G16_s20220740000000_e20220740001000_c*.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T27_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T41_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T40_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T20_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T46_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T08_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T14_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T42_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T38_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T21_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T47_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T15_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T28_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T34_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T35_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T36_20220315000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G16_T33_20220315000100.nc', 1)) + +def test_g17(): + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--create-tiles", + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G17_s20222631921000_e20222631921200_c20222631921214.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G17_s20222631921200_e20222631921400_c20222631921418.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G17_s20222631921400_e20222631922000_c20222631922019.nc"), + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G17_*.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMF-M3_G17_T*.nc", 15)) + + assert(check_fileglob('CG_GLM-L2-GLMF-M3_G17_s20222631921000_e20222631922000_c*.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T49_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T19_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T05_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T18_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T30_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T11_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T43_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T25_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T14_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T08_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T24_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T13_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T41_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T17_20220920192200.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G17_T23_20220920192200.nc', 1)) + +def test_g18(): + inputs = [os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G18_s20222210000000_e20222210000200_c20222210000225.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G18_s20222210000200_e20222210000400_c20222210000424.nc"), + os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G18_s20222210000400_e20222210001000_c20222210001027.nc")] + for i in inputs: + if not os.path.exists(i): + warnings.warn(UserWarning("GOES-18 test files are not available in this environment. GOES-18 functionality has not been tested.")) + return + + completed_process = subprocess.run(['python', + MINUTE_GRIDDER, + "--create-tiles", + inputs[0], + inputs[1], + inputs[2], + ]) + assert completed_process.returncode == 0 + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G18_*.nc", 1)) + assert(check_fileglob("CSPP_OR_GLM-L2-GLMF-M3_G18_T*.nc", 15)) + + assert(check_fileglob("CG_GLM-L2-GLMF-M3_G18_s20222210000000_e20222210001000_c*.nc", 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T04_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T30_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T18_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T29_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T49_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T16_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T27_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T23_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T17_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T20_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T08_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T11_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T21_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T24_20220809000100.nc', 1)) + assert(check_fileglob('CSPP_OR_GLM-L2-GLMF-M3_G18_T10_20220809000100.nc', 1)) + diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 2ab1b3e..47c77cc 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -1,60 +1,18 @@ #!/usr/bin/env python3 """ -Gridded GLM test suite +Gridded GLM regression tests """ -# setting PYTHONPATH so we can work -import sys -import os -TESTDIR = os.path.dirname(__file__) -TOPDIR = os.path.dirname(TESTDIR) -PYDIR = os.path.join(TOPDIR, 'gridded_glm/libexec') -sys.path.append(PYDIR) -MINUTE_GRIDDER = os.path.join(PYDIR, "gridded_glm/_minute_gridder.py") -#from gridded_glm import _minute_gridder as mg - -#import argparse -#from unittest import mock import subprocess - -from glob import glob -def check_fileglob(fileglob_pattern, nfiles=1): - files = glob(fileglob_pattern) - if len(files) == nfiles: - return True - else: - return False - -import pytest -import tempfile import os -import shutil -@pytest.fixture(autouse=True) -def run_before_and_after_tests(tmp_path): - """Fixture to execute asserts before and after a test is run""" - # Setup: fill with any logic you want - os.chdir(tmp_path) - print(os.getcwd()) - - yield # this is where the testing happens - - print(glob("*")) - # Teardown : fill with any logic you want - shutil.rmtree(tmp_path) +from glob import glob import netCDF4 import numpy as np -def test_simple_success(): - completed_process = subprocess.run(['python', - MINUTE_GRIDDER, - "--goes-sector", "full", - os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000000_e20220740000200_c20220740000227.nc"), - os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000200_e20220740000400_c20220740000428.nc"), - os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740000400_e20220740001000_c20220740001027.nc"), - ]) - assert completed_process.returncode == 0 - assert(check_fileglob("CG_GLM-L2-GLMF-M3_G16_s20220740000000_e20220740001000_c*.nc")) +from testlib.common import TESTDIR, MINUTE_GRIDDER +from testlib.common import check_fileglob + def test_issue5_fail1_3(): completed_process = subprocess.run(['python', @@ -156,20 +114,6 @@ def test_issue5_realtime_early2(): assert(check_fileglob("CG_GLM-*.nc", 0)) assert(check_fileglob("CSPP_OR_GLM-*.nc", 0)) -def test_issue5_realtime_succeed1(): - completed_process = subprocess.run(['python', - MINUTE_GRIDDER, - "--goes-sector", "conus", - "--create-tiles", - "--realtime", - os.path.join(TESTDIR, "test-inputs/OR_GLM-L2-LCFA_G16_s20220740002400_e20220740003000_c20220740003018.nc"), - ]) - assert completed_process.returncode == 0 - assert(check_fileglob("CG_GLM-L2-GLMC-M3_G16_s20220740002000_e20220740003000_c*", 1)) - assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T08_20220315000300.nc", 1)) - assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T05_20220315000300.nc", 1)) - assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T04_20220315000300.nc", 1)) - assert(check_fileglob("CSPP_OR_GLM-L2-GLMC-M3_G16_T07_20220315000300.nc", 1)) # test for providing two minutes with a minute in between that has no input # the middle minute should produce no output @@ -321,4 +265,4 @@ def test_issue38_no_valid_data(): assert(ds.variables['minimum_flash_area'][:].all() is np.ma.masked) assert(ds.variables['total_energy'][:].all() is np.ma.masked) assert(ds.variables['total_energy'][:].all() is np.ma.masked) - assert((ds.variables['DQF'][:] == 0).all()) \ No newline at end of file + assert((ds.variables['DQF'][:] == 0).all()) diff --git a/tests/testlib/common.py b/tests/testlib/common.py new file mode 100644 index 0000000..261bbbc --- /dev/null +++ b/tests/testlib/common.py @@ -0,0 +1,18 @@ +import sys +import os + +# setting PYTHONPATH so we can work +LIBDIR = os.path.dirname(__file__) +TESTDIR = os.path.dirname(LIBDIR) +TOPDIR = os.path.dirname(TESTDIR) +PYDIR = os.path.join(TOPDIR, 'gridded_glm/libexec') +sys.path.append(PYDIR) +MINUTE_GRIDDER = os.path.join(PYDIR, "gridded_glm/_minute_gridder.py") + +from glob import glob +def check_fileglob(fileglob_pattern, nfiles=1): + files = glob(fileglob_pattern) + if len(files) == nfiles: + return True + else: + return False -- GitLab From a8cdbcbb26c6b9fea8ac2683e0db51ccc43b79c3 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 15:13:09 -0500 Subject: [PATCH 11/12] update our packaging to include libexec subfolders --- buildbucket/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildbucket/package.sh b/buildbucket/package.sh index 80e0bd9..d47c556 100755 --- a/buildbucket/package.sh +++ b/buildbucket/package.sh @@ -76,7 +76,7 @@ mkdir -p bin libexec/python_runtime cp $GGLM_DIR/PACKAGE_README.md ./README.md cp $GGLM_DIR/PACKAGE_LICENSE ./LICENSE cp $GGLM_DIR/bin/* ./bin/ -cp $GGLM_DIR/libexec/* ./libexec/ +cp -r $GGLM_DIR/libexec/ ./libexec/ # Untar the tarball so we can put things where we want tar -xz -C ./libexec/python_runtime -f ../${conda_tb} # write a conda environment.yml to the python_runtime/ folder so that we can more easily audit what's included in our runtime between builds -- GitLab From 956b2dbb5ce9fb894ba6f054cc02c89dedf0be33 Mon Sep 17 00:00:00 2001 From: Nick Bearson Date: Tue, 20 Sep 2022 15:51:20 -0500 Subject: [PATCH 12/12] well that was dumb of me --- buildbucket/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildbucket/package.sh b/buildbucket/package.sh index d47c556..829e5ff 100755 --- a/buildbucket/package.sh +++ b/buildbucket/package.sh @@ -76,7 +76,7 @@ mkdir -p bin libexec/python_runtime cp $GGLM_DIR/PACKAGE_README.md ./README.md cp $GGLM_DIR/PACKAGE_LICENSE ./LICENSE cp $GGLM_DIR/bin/* ./bin/ -cp -r $GGLM_DIR/libexec/ ./libexec/ +cp -r $GGLM_DIR/libexec/* ./libexec/ # Untar the tarball so we can put things where we want tar -xz -C ./libexec/python_runtime -f ../${conda_tb} # write a conda environment.yml to the python_runtime/ folder so that we can more easily audit what's included in our runtime between builds -- GitLab