Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6fb9f68
added three new CTest cases and re-fixed label bug in the main CMakeL…
TerrenceMcGuinness-NOAA Sep 26, 2025
67cd1bf
needed gfs.t12z ahead of some file history
TerrenceMcGuinness-NOAA Sep 26, 2025
ae029e1
adding back the new cases in the CMakeLists.txt file
TerrenceMcGuinness-NOAA Sep 26, 2025
2bc6aff
needed the gfs.t12z on the front end to of the file cp
TerrenceMcGuinness-NOAA Sep 26, 2025
bb2acc5
needed to creat history dir in dest
TerrenceMcGuinness-NOAA Sep 26, 2025
9283fe0
updated name of job to include the forcast hours
TerrenceMcGuinness-NOAA Sep 26, 2025
7f484f6
the requirements where sort of pspeo code and I did not check the rea…
TerrenceMcGuinness-NOAA Sep 26, 2025
a5a5662
Merge branch 'NOAA-EMC:develop' into ctest_case_updates
TerrenceMcGuinness-NOAA Sep 29, 2025
9b01f3b
Merge branch 'NOAA-EMC:develop' into ctest_case_updates
TerrenceMcGuinness-NOAA Sep 29, 2025
81d25e8
renamed ctest case files with - as CASE-jobname delementer
TerrenceMcGuinness-NOAA Sep 30, 2025
8968ea9
Merge branch 'ctest_case_updates' of github.com:TerrenceMcGuinness-NO…
TerrenceMcGuinness-NOAA Sep 30, 2025
422bf8d
updated LABELS for patter matching for -L ctest on case names with - …
TerrenceMcGuinness-NOAA Sep 30, 2025
90972c3
Merge branch 'NOAA-EMC:develop' into ctest_case_updates
TerrenceMcGuinness-NOAA Sep 30, 2025
a5626f7
added a report from Cluad Code with upated Claud Sonnit 4.5
TerrenceMcGuinness-NOAA Sep 30, 2025
45bf58e
added master files to atmos prod
TerrenceMcGuinness-NOAA Sep 30, 2025
95ba844
added a mkdir for master files in gfs_atmos_prod in C48_ATM
TerrenceMcGuinness-NOAA Sep 30, 2025
a275d18
added a few more imput files and execute passes
TerrenceMcGuinness-NOAA Oct 1, 2025
2e8de9f
updated ctest case files for atmos and ocean for C48_ATM and C48_S2W
TerrenceMcGuinness-NOAA Oct 1, 2025
cbdd138
Fix: Correct forecast hours and products path in C48_ATM atmos_prod test
TerrenceMcGuinness-NOAA Oct 1, 2025
abb19b4
removed some extra md files
TerrenceMcGuinness-NOAA Oct 1, 2025
8dda765
Split ocean/ice products test into separate component tests
TerrenceMcGuinness-NOAA Oct 1, 2025
3c2f209
updated some output files with the correct resolutions for ocean and …
TerrenceMcGuinness-NOAA Oct 1, 2025
e6c747f
udpated case documentation by removing historical facts and put them …
TerrenceMcGuinness-NOAA Oct 1, 2025
1cd4dbc
renamed ctest yaml case file to match with the job name for cases C48…
TerrenceMcGuinness-NOAA Oct 1, 2025
86e2bcc
updated gef dirs in enseble case
TerrenceMcGuinness-NOAA Oct 1, 2025
be0f9c5
re-did case C48_S2SWA_gefs for job gefs_fcst_mem001_seg0
TerrenceMcGuinness-NOAA Oct 1, 2025
a452972
C48_S2SWA_gefs (ensemble coupled): Only needs ice/ocean/wave restarts…
TerrenceMcGuinness-NOAA Oct 1, 2025
4b559d9
needed prep file for gefs_fcst_mem001_seg0
TerrenceMcGuinness-NOAA Oct 1, 2025
7e872ae
added ICs for atmos in C48_S2SWA_gefs-gefs
TerrenceMcGuinness-NOAA Oct 1, 2025
4f0fa15
neede restart files for 06Z as well as 12Z for the C48_S2SWA_gefs-ge…
TerrenceMcGuinness-NOAA Oct 1, 2025
f4fefd0
updated README.md documentation and detailed documentation for 48_S2S…
TerrenceMcGuinness-NOAA Oct 1, 2025
91ccd44
removed in place AI changelog for this effort
TerrenceMcGuinness-NOAA Oct 1, 2025
c8e0080
removed exta md files for the AI record and some test scripts
TerrenceMcGuinness-NOAA Oct 1, 2025
70b3482
fixed the ctest case list in the GitLab pipeline
TerrenceMcGuinness-NOAA Oct 1, 2025
cf36b04
Update dev/ctests/cases/C48_ATM-gfs_atmos_prod_f000-f002.yaml
TerrenceMcGuinness-NOAA Oct 2, 2025
17b7c90
Update dev/ctests/README.md
TerrenceMcGuinness-NOAA Oct 2, 2025
00af3ad
Merge branch 'NOAA-EMC:develop' into ctest_case_updates
TerrenceMcGuinness-NOAA Oct 2, 2025
9d54cc0
changed EXPDIR to COMROOT because that is where the ctests staged fil…
TerrenceMcGuinness-NOAA Oct 2, 2025
67151f2
removed he case md files for ctest and remove extra f003 forcast for …
TerrenceMcGuinness-NOAA Oct 3, 2025
370214d
expanded matix of ctest names into seperate lines for better maintiai…
TerrenceMcGuinness-NOAA Oct 3, 2025
757e2e5
moved detailed doc fo CTest CI Frameworkd to doxygen and tried to sim…
TerrenceMcGuinness-NOAA Oct 3, 2025
b1b4585
couple of little updates to README.md
TerrenceMcGuinness-NOAA Oct 3, 2025
531b8ce
cmake line needs three .. (todo use -B)
TerrenceMcGuinness-NOAA Oct 4, 2025
6ebbe74
Fix cmake command in README for running tests
TerrenceMcGuinness-NOAA Oct 4, 2025
add2b25
removed un-necceary ICs in the ctest for C48_ATM-gfs_atmos_prod_f000-…
TerrenceMcGuinness-NOAA Oct 6, 2025
114047d
ocean and ice prod f006 for C48_S2SW did not need IC only history
TerrenceMcGuinness-NOAA Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion dev/ci/gitlab-ci-hosts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,13 @@ finalize_success-ursa:
stage: run_tests
parallel:
matrix:
- CTEST_NAME: ['C48_ATM_gfs_fcst_seg0', 'C48_S2SW_gfs_fcst_seg0']
- CTEST_NAME:
- C48_ATM-gfs_fcst_seg0
- C48_ATM-gfs_atmos_prod_f000-f002
- C48_S2SW-gfs_fcst_seg0
- C48_S2SW-gfs_ocean_prod_f006
- C48_S2SW-gfs_ice_prod_f006
- C48_S2SWA_gefs-gefs_fcst_mem001_seg0

# Host-specific CTest setup jobs
setup_ctests-hera:
Expand Down
34 changes: 29 additions & 5 deletions dev/ctests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,30 +72,30 @@ function(AddJJOBTest)
"${novals}" "${singlevals}" "${multivals}"
${ARGN})

set(TEST_NAME ${ARG_CASE}_${ARG_JOB})
set(TEST_NAME ${ARG_CASE}-${ARG_JOB})
set(CASE_PATH ${HOMEgfs}/dev/ci/cases/pr)
set(CASE_YAML ${CASE_PATH}/${ARG_CASE}.yaml)

add_test(NAME test_${TEST_NAME}_setup
COMMAND ./setup.sh ${TEST_NAME} ${CASE_YAML} ${ARG_TEST_DATE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripts)
set_tests_properties(test_${TEST_NAME}_setup PROPERTIES LABELS "${ARG_CASE}_${ARG_JOB}")
set_tests_properties(test_${TEST_NAME}_setup PROPERTIES LABELS "${ARG_CASE}-${ARG_JOB}")

add_test(NAME test_${TEST_NAME}_stage
COMMAND ./stage.sh ${ARG_CASE} ${TEST_NAME} ${ARG_TEST_DATE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripts)
set_tests_properties(test_${TEST_NAME}_stage PROPERTIES DEPENDS test_${TEST_NAME}_setup LABELS "${ARG_CASE}_${ARG_JOB}")
set_tests_properties(test_${TEST_NAME}_stage PROPERTIES DEPENDS test_${TEST_NAME}_setup LABELS "${ARG_CASE}-${ARG_JOB}")

add_test(NAME test_${TEST_NAME}_execute
COMMAND ./execute.sh ${TEST_NAME} ${ARG_JOB} ${ARG_TEST_DATE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripts)
set_tests_properties(test_${TEST_NAME}_execute PROPERTIES DEPENDS test_${TEST_NAME}_stage LABELS "${ARG_CASE}_${ARG_JOB}")
set_tests_properties(test_${TEST_NAME}_execute PROPERTIES DEPENDS test_${TEST_NAME}_stage LABELS "${ARG_CASE}-${ARG_JOB}")

# TODO - This is a stub for the validation step
add_test(NAME test_${TEST_NAME}_validate
COMMAND ./validate.sh ${ARG_CASE} ${TEST_NAME} ${ARG_TEST_DATE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripts)
set_tests_properties(test_${TEST_NAME}_validate PROPERTIES DEPENDS test_${TEST_NAME}_execute LABELS "${ARG_CASE}_${ARG_JOB}")
set_tests_properties(test_${TEST_NAME}_validate PROPERTIES DEPENDS test_${TEST_NAME}_execute LABELS "${ARG_CASE}-${ARG_JOB}")
endfunction()

AddJJOBTest(
Expand All @@ -104,8 +104,32 @@ AddJJOBTest(
TEST_DATE "2021032312"
)

AddJJOBTest(
CASE "C48_ATM"
JOB "gfs_atmos_prod_f000-f002"
TEST_DATE "2021032312"
)

AddJJOBTest(
CASE "C48_S2SW"
JOB "gfs_fcst_seg0"
TEST_DATE "2021032312"
)

AddJJOBTest(
CASE "C48_S2SW"
JOB "gfs_ice_prod_f006"
TEST_DATE "2021032312"
)

AddJJOBTest(
CASE "C48_S2SW"
JOB "gfs_ocean_prod_f006"
TEST_DATE "2021032312"
)

AddJJOBTest(
CASE "C48_S2SWA_gefs"
JOB "gefs_fcst_mem001_seg0"
TEST_DATE "2021032312"
)
270 changes: 235 additions & 35 deletions dev/ctests/README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,263 @@
# CTest Framework for NOAA Global Workflow
# CTest Framework Quick Start

This directory contains the CTest framework for testing Rocoto JJOBS. The framework allows you to stage, execute, and validate individual JJOBS independently from other jobs in the workflow. Each test requires its own YAML definition of inputs and configurations.
This directory contains the CTest framework for testing Rocoto workflow jobs (JJOBS) independently. Each test runs in an isolated environment with staged input files from nightly baseline runs.

## Overview
> **📖 Complete Documentation**: See the [comprehensive testing documentation](../../docs/source/testing.rst) for detailed information on framework architecture, YAML configuration, test patterns, CI/CD integration, and troubleshooting.

The CTest framework consists of the following scripts:
- **setup.sh.in**: Prepares the environment and creates the experiment.
- **stage.sh.in**: Stages the input files needed to run a JJOB.
- **execute.sh.in**: Executes the JJOB and monitors its status.
- **validate.sh.in**: Validates the results of the JJOB.
## Quick Start Guide

**NOTE:** So far only test C48_ATM *gfs_fcst_set0* has `output_files` for the validation step using a basic chksum for testing. Further development using grib and NETCDF comparison tools is pending.
### Prerequisites

## Usage
The following environment variables must be set (either in your environment or via platform configuration):

### CMake Configuration
```bash
HPC_ACCOUNT # Your HPC allocation account
STAGED_CTESTS # Path to nightly baseline COMROOT
ICSDIR_ROOT # Path to initial condition files
```

To configure the **CTest** framework using **CMake**, you need to provide several environment variables. Here is an example of how to configure and build the project:
These are typically defined in `$HOMEgfs/dev/ci/platforms/config.$MACHINE_ID`.

**NOTE**: The the specific values for these three enviroment variables can be found in `$HOMEgfs/dev/ci/platforms/config.$MACHINE_ID` and may also be added to the `cmake` command line with the `-D` option
### Configure and Build

# Run CMake to configure the ctest framework
```shell
```bash
cd $HOMEgfs/dev/ctests
mkdir build
mkdir -p build
cd build
cmake ../..
```

### Running Tests with CTest
# Configure using environment variables from config.$MACHINE_ID
cmake ../../..

Once the project is configured, you can run the tests using CTest. Here are some examples:
# Or configure with explicit command-line options
cmake -DHPC_ACCOUNT=myaccount \
-DSTAGED_CTESTS=/path/to/baselines/RUNTESTS \
-DICSDIR_ROOT=/path/to/ics \
../../..
```

#### Run All Tests
### Run Tests

```bash
cd /path/to/build
# Run all tests
ctest

# Run tests for a specific configuration case
ctest -L C48_ATM

# Run test for a specific JJOB
cest -L C48_ATM-gfs_atmos_prod_f000-f002

# Run a specific test with verbose output
ctest -R test_C48_ATM-gfs_fcst_seg0_execute -V

# Run tests in parallel (4 concurrent tests)
ctest -j 4

# Show test list without running
ctest -N
```

#### Run Tests for a Specific Case
### Common CTest Options

You can use the `-L` option with CTest to run tests for a specific case. For example, to run tests for the `C48_ATM` case:
| Option | Description |
|--------|-------------|
| `-V` | Verbose output |
| `-VV` | Extra verbose output |
| `-N` | Dry run (list tests without executing) |
| `-L <label>` | Run tests matching label (e.g., `-L C48_ATM`) |
| `-R <regex>` | Run tests matching regex pattern |
| `-j <N>` | Run N tests in parallel |
| `--output-on-failure` | Show output only for failed tests |
| `--rerun-failed` | Rerun only previously failed tests |

## Test Structure

Each test consists of four phases executed sequentially:

1. **Setup**: Creates experiment directory and configuration
2. **Stage**: Stages input files from baseline into test COMROOT
3. **Execute**: Runs the job script and monitors execution
4. **Validate**: Compares outputs against baseline results

Test phases are automatically chained via CMake dependencies.

## Validation Modes

Control validation behavior with the `CTEST_VALIDATION_MODE` environment variable:

```bash
cd /path/to/build
ctest -L C48_ATM
```
Or simply use the '-R' switch to run any individual test:
```
ctest -R test_C48_S2SW_gfs_fcst_seg0_execute -V
# PRESENCE_ONLY (default): Verify files exist, no checksum validation
export CTEST_VALIDATION_MODE=PRESENCE_ONLY
ctest -R validate

# STRICT: All files must exist AND checksums must match
export CTEST_VALIDATION_MODE=STRICT
ctest -R validate

# CHECKSUM_ONLY: Validate checksums for existing files, ignore missing files
export CTEST_VALIDATION_MODE=CHECKSUM_ONLY
ctest -R validate
```

To add a new test use the **AddJJOBTest()** function at the end of the `$HOMEgfs/dev/ctest/CMakeLists.txt` file as follows:
## Available Tests

Current test cases include:

| Test Name | Configuration | Component | Description |
|-----------|--------------|-----------|-------------|
| `C48_ATM-gfs_fcst_seg0` | C48_ATM | Atmosphere | Atmosphere-only forecast |
| `C48_ATM-gfs_atmos_prod_f000-f002` | C48_ATM | Products | Atmosphere product generation |
| `C48_S2SW-gfs_fcst_seg0` | C48_S2SW | Coupled | Coupled forecast (atmos-ocean-ice-wave) |
| `C48_S2SW-gfs_ocean_prod_f006` | C48_S2SW | Products | Ocean product generation |
| `C48_S2SW-gfs_ice_prod_f006` | C48_S2SW | Products | Ice product generation |
| `C48_S2SWA_gefs-gefs_fcst_mem001_seg0` | C48_S2SWA_gefs | Ensemble | GEFS ensemble member forecast |

## Adding New Tests

### 1. Add test definition to `CMakeLists.txt`:

```cmake
AddJJOBTest(
CASE "C48_ATM"
JOB "gfs_fcst_seg0"
TEST_DATE "2021032312"
CASE "C48_ATM" # Configuration case
JOB "gfs_analysis" # Job identifier
TEST_DATE "2021032312" # Test cycle (YYYYMMDDHH)
)
```
Then create a new YAML file with the required staged input files as is done with this example found in `$HOMEgfs/dev/ctests/cases/C48_ATM_gfs_fcts_seg0.yaml`

### 2. Create YAML file `cases/C48_ATM-gfs_analysis.yaml`:

```yaml
{% set cyc = TEST_DATE | strftime('%H') %}
{% set PDY = TEST_DATE | to_YMD %}
{% set SRC_DIR = STAGED_CTESTS + '/COMROOT/' + PSLOT %}
{% set DST_DIR = RUNTESTS + '/COMROOT/' + TEST_NAME %}

input_files:
mkdir:
- {{ DST_DIR }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input

copy:
- [{{ SRC_DIR }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc,
{{ DST_DIR }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/input/gfs_ctrl.nc]
# Add additional required files...

output_files:
cmpfiles:
- [{{ SRC_DIR }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/analysis/atminc.nc,
{{ DST_DIR }}/gfs.{{ PDY }}/{{ cyc }}/model/atmos/analysis/atminc.nc]
# Add additional output files...
```

### 3. Build and test:

```bash
cd build
cmake ../../..
ctest -L C48_S2SW -j 3
```

## Naming Convention

Test names follow the pattern: `CASE-JOB.yaml`

**Examples:**
- `C48_ATM-gfs_fcst_seg0.yaml` - Atmosphere forecast
- `C48_S2SW-gfs_ocean_prod_f006.yaml` - Ocean products
- `C48_S2SWA_gefs-gefs_fcst_mem001_seg0.yaml` - Ensemble member forecast

## Troubleshooting

### Missing Input Files

```bash
# Compare baseline with test environment
ls ${STAGED_CTESTS}/COMROOT/${PSLOT}/gfs.${PDY}/${cyc}/
ls ${RUNTESTS}/COMROOT/${TEST_NAME}/gfs.${PDY}/${cyc}/
```

Add missing files to the YAML `input_files.copy` section.

### Checksum Validation Failures

For development, use presence-only validation:
```bash
export CTEST_VALIDATION_MODE=PRESENCE_ONLY
ctest -R validate
```

### Verbose Debugging

```bash
# Enable debug logging
export LOGGING_LEVEL=DEBUG

# Run with maximum verbosity
ctest -R test_name -VV

# Check test logs
tail -f ${RUNTESTS}/COMROOT/${TEST_NAME}_*/EXPDIR/logs/*.log
```

### Manual Execution

Run test phases manually for debugging:

```bash
cd build/scripts
./setup.sh TEST_NAME CASE_YAML TEST_DATE
./stage.sh CASE_NAME TEST_NAME TEST_DATE
./execute.sh TEST_NAME JOB_NAME TEST_DATE
./validate.sh CASE_NAME TEST_NAME TEST_DATE
```

## Key Directories

```
$HOMEgfs/dev/ctests/ # Framework root
├── build/ # CMake build directory (create this)
├── cases/ # YAML test definitions
├── scripts/ # Test phase scripts
└── CMakeLists.txt # Test configuration

$HOMEgfs/dev/ci/platforms/ # Platform-specific configuration
└── config.$MACHINE_ID # Machine settings (STAGED_CTESTS, HPC_ACCOUNT, etc.)

${STAGED_CTESTS}/COMROOT/ # Nightly baseline outputs (input source)
${RUNTESTS}/COMROOT/ # Test execution environments (created by tests)
```

## Platform Configuration

Platform-specific settings are in `$HOMEgfs/dev/ci/platforms/config.$MACHINE_ID`:

```bash
# Example from config.hera
export GFS_CI_ROOT=/scratch1/NCEPDEV/global/Terry.McGuinness/GFS_CI_ROOT
export GITLAB_BUILDS_DIR=${GFS_CI_ROOT}/BUILDS/GITLAB
export STAGED_CTESTS=${GITLAB_BUILDS_DIR}/stable/RUNTESTS
export ICSDIR_ROOT=/scratch1/NCEPDEV/global/glopara/data/ICSDIR
export HPC_ACCOUNT=nems
```

Source the appropriate configuration before running CMake:

```bash
source $HOMEgfs/ush/detect_machine.sh
source $HOMEgfs/dev/ci/platforms/config.$MACHINE_ID
```

## Additional Resources

- **Complete Documentation**: `docs/source/testing.rst`
- **Test Case Examples**: `cases/*.yaml`
- **CI/CD Pipeline**: `../ci/gitlab-ci-hosts.yml`
- **Job Scripts**: `../../jobs/JGLOBAL_*`
- **Platform Configuration**: `../ci/platforms/config.*`

---

**Framework Version**: 1.0
**Last Updated**: October 2025
**Status**: Active Development

For detailed architecture, YAML templating, CI/CD integration, and comprehensive troubleshooting, see the [full testing documentation](../../docs/source/testing.rst).
Loading