diff --git a/.github/workflows/branch_push_workflow.yml b/.github/workflows/branch_push_workflow.yml index c89d662b2..baf91c516 100644 --- a/.github/workflows/branch_push_workflow.yml +++ b/.github/workflows/branch_push_workflow.yml @@ -17,10 +17,10 @@ jobs: #in the body of a pull request merged into a non-default branch. issue_closer: if: github.repository == 'ESCOMP/CAM-SIMA' # Only run on main repo - runs-on: ubuntu-latest + runs-on: ubuntu-slim steps: # Acquire github action routines - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 # Acquire specific version of python - name: Set up Python 3.11 uses: actions/setup-python@v6 diff --git a/.github/workflows/build_and_run_cirrus.yml b/.github/workflows/build_and_run_cirrus.yml index 2d59be7b4..e17f51b61 100644 --- a/.github/workflows/build_and_run_cirrus.yml +++ b/.github/workflows/build_and_run_cirrus.yml @@ -19,6 +19,7 @@ concurrency: jobs: build-and-run-on-CIRRUS: name: Run ${{ matrix.image }} on ${{ matrix.runner }} + if: ${{ github.repository == 'ESCOMP/CAM-SIMA' }} env: TMP_DIR: tmp TMP_OUTPUT: case_output.log @@ -84,7 +85,7 @@ jobs: fi - name: Upload logs to GitHub artifacts when the CI test fails - if: failure() + if: failure() uses: actions/upload-artifact@v7 with: name: logs.${{ matrix.test_type }}.${{ matrix.compset }}.${{ matrix.compiler }}.${{ matrix.runner }} diff --git a/.github/workflows/cam_sima_fortran_ci.yml b/.github/workflows/cam_sima_fortran_ci.yml new file mode 100644 index 000000000..36e1aa3b1 --- /dev/null +++ b/.github/workflows/cam_sima_fortran_ci.yml @@ -0,0 +1,300 @@ +name: CAM-SIMA Fortran CI + +permissions: + contents: read + +on: + pull_request: + types: + - opened + - reopened + - synchronize + push: + branches: + - staging/** + - development + workflow_dispatch: + +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }} - ${{ github.ref }} + +jobs: + # This check is the stepped leader to determine if the rest of jobs should run. We unfortunately cannot use path filtering + # due to the peculiar limitations of GitHub Actions, quoted below for reference: + # + # "If a workflow is skipped due to path filtering, then checks associated with that workflow will remain in a "Pending" state. + # A pull request that requires those checks to be successful will be blocked from merging." + conditional-check: + name: Check if jobs should run + runs-on: ubuntu-slim + outputs: + should-run: ${{ steps.conditional.outputs.result }} + timeout-minutes: 1 + steps: + - name: Checkout CAM-SIMA + uses: actions/checkout@v6 + + - name: Check if there are changes to Fortran source code + id: conditional + run: | + set -euo pipefail + + write_result_and_exit() { + case "$1" in + false) + echo "Result: Skip jobs." + echo "result=$1" >> "$GITHUB_OUTPUT" + exit 0 + ;; + true) + echo "Result: Run jobs." + echo "result=$1" >> "$GITHUB_OUTPUT" + exit 0 + ;; + error|*) + echo "Error occurred!" + exit 1 + ;; + esac + } + + case "${{ github.event_name }}" in + pull_request) + echo "Event is pull request." + + HEAD_COMMIT="${{ github.sha }}" + + if [ -z "$HEAD_COMMIT" ]; then + echo "HEAD_COMMIT is empty." + write_result_and_exit false + fi + + echo "Fetching $HEAD_COMMIT with parents..." + git fetch --depth=2 origin "$HEAD_COMMIT" || write_result_and_exit error + + BASE_COMMIT="$(git rev-parse $HEAD_COMMIT^1)" || write_result_and_exit error + ;; + push) + echo "Event is push." + + BASE_COMMIT="${{ github.event.before }}" + HEAD_COMMIT="${{ github.event.after }}" + + if [ -z "$BASE_COMMIT" ] || [ -z "$HEAD_COMMIT" ]; then + echo "BASE_COMMIT or HEAD_COMMIT is empty." + write_result_and_exit false + fi + + if [ -z "${BASE_COMMIT//0/}" ] || [ -z "${HEAD_COMMIT//0/}" ]; then + echo "BASE_COMMIT or HEAD_COMMIT is null." + write_result_and_exit false + fi + + echo "Fetching $BASE_COMMIT..." + git fetch --depth=1 origin "$BASE_COMMIT" || write_result_and_exit error + + echo "Fetching $HEAD_COMMIT..." + git fetch --depth=1 origin "$HEAD_COMMIT" || write_result_and_exit error + ;; + workflow_dispatch) + echo "Event is workflow dispatch." + + # Always run jobs when triggered manually. + write_result_and_exit true + ;; + *) + echo "Event is unknown." + + # Always skip jobs for any other events. + write_result_and_exit false + ;; + esac + + echo "Finding changed paths between $BASE_COMMIT..$HEAD_COMMIT..." + git diff --name-only "$BASE_COMMIT..$HEAD_COMMIT" | tee changed-paths.txt || write_result_and_exit error + + if grep -E -q '(^\.github\/workflows\/cam_sima_fortran_ci\.yml$|^share$|^src\/.+$|^test\/unit\/.+$)' changed-paths.txt; then + write_result_and_exit true + else + write_result_and_exit false + fi + # This job evaluates the overall status of CAM-SIMA Fortran CI for the purpose of inclusion as a required status check. + # It exists solely due to, again, the peculiar limitations of GitHub Actions, quoted below for reference: + # + # "The `jobs..if` conditional is evaluated before `jobs..strategy.matrix` is applied." This implies that + # when a matrix job is set as a required status check, skipping it due to the conditional will cause a pull request to be + # blocked from merging. + overall-status: + name: Overall status (CAM-SIMA Fortran CI) + needs: + - conditional-check + - unit-tests + if: ${{ always() }} + runs-on: ubuntu-slim + timeout-minutes: 1 + steps: + - name: Evaluate overall status + run: | + set -euo pipefail + + write_result_and_exit() { + case "$1" in + false) + echo "Result: Failure." + exit 1 + ;; + true) + echo "Result: Success." + exit 0 + ;; + error|*) + echo "Error occurred!" + exit 1 + ;; + esac + } + + case "${{ needs.conditional-check.result }}" in + success) + : + ;; + cancelled|failure|skipped) + write_result_and_exit false + ;; + *) + write_result_and_exit error + ;; + esac + + case "${{ needs.unit-tests.result }}" in + skipped|success) + : + ;; + cancelled|failure) + write_result_and_exit false + ;; + *) + write_result_and_exit error + ;; + esac + + write_result_and_exit true + unit-tests: + name: Build and run unit tests (${{ matrix.compiler }}) + needs: conditional-check + if: ${{ needs.conditional-check.outputs.should-run == 'true' }} + runs-on: ubuntu-24.04 + container: + image: ghcr.io/kuanchihwang/atm-sci-container:2026-06-12_${{ matrix.compiler }}_${{ matrix.mpi }} + env: + CONTAINER_PRESET: cesm + CONTAINER_ENVIRONMENT: pfunit + RRTMGP_DATA_REFERENCE: v1.9 + UNIT_TESTS_BUILD_TYPE: Debug + UNIT_TESTS_PATH: ${{ github.workspace }}/test/unit/fortran + strategy: + fail-fast: false + matrix: + compiler: + - gnu-11 + - gnu-12 + - gnu-13 + - gnu-14 + - gnu-15 + - intel-2024 + - intel-2025 + # Uncomment the following lines to test with more MPI implementations. Currently only `open-mpi-5` + # (Open MPI 5.0.x series) is enabled. We may expand this matrix as our test coverage grows in the future. + mpi: + # - mpich-4 + # - open-mpi-4 + - open-mpi-5 + # include: + # - compiler: intel-2024 + # mpi: intel-mpi + # - compiler: intel-2025 + # mpi: intel-mpi + timeout-minutes: 10 + steps: + - name: Checkout CAM-SIMA + uses: actions/checkout@v6 + + - name: Checkout dependencies + run: | + ./bin/git-fleximod update ncar-physics share + + - name: Checkout rrtmgp-data for PIO file reader tests + uses: actions/checkout@v6 + with: + repository: earth-system-radiation/rrtmgp-data + ref: ${{ env.RRTMGP_DATA_REFERENCE }} + path: ${{ env.UNIT_TESTS_PATH }}/rrtmgp-data + + - name: Build unit tests + run: | + source "$(command -v container-entrypoint-hook.sh)" + cmake \ + -D CMAKE_BUILD_TYPE="$UNIT_TESTS_BUILD_TYPE" \ + -D CAM_SIMA_ENABLE_CODE_COVERAGE=ON \ + -D CAM_SIMA_ENABLE_IO_TESTS=ON \ + -D CAM_SIMA_ENABLE_TESTS=ON \ + -B "$UNIT_TESTS_PATH/build" \ + -S "$UNIT_TESTS_PATH" + cmake \ + --build "$UNIT_TESTS_PATH/build" \ + --config "$UNIT_TESTS_BUILD_TYPE" + + - name: Run unit tests + run: | + source "$(command -v container-entrypoint-hook.sh)" + ctest \ + --build-config "$UNIT_TESTS_BUILD_TYPE" \ + --output-junit "$UNIT_TESTS_PATH/build/unit-tests.xml" \ + --output-on-failure \ + --test-dir "$UNIT_TESTS_PATH/build" \ + --test-output-size-failed 524288 \ + --test-output-size-passed 524288 \ + --verbose + + - name: Upload unit test results + if: ${{ always() }} + uses: actions/upload-artifact@v7 + with: + if-no-files-found: ignore + name: unit-tests-xml-${{ matrix.compiler }} + path: ${{ env.UNIT_TESTS_PATH }}/build/unit-tests.xml + retention-days: 7 + + # Code coverage analysis only works reliably with the GNU Compiler Collection. + # Do it only with the latest version to save CI time. + + - name: Install Gcovr + if: ${{ matrix.compiler == 'gnu-15' }} + run: | + python3 -m venv venv-gcovr + source venv-gcovr/bin/activate + python3 -m pip install --upgrade pip + python3 -m pip install gcovr + + - name: Run Gcovr + if: ${{ matrix.compiler == 'gnu-15' }} + run: | + source venv-gcovr/bin/activate + export SOURCE_PATH="$PWD" + cd "$UNIT_TESTS_PATH/build" + gcovr \ + --filter "$SOURCE_PATH/src" \ + --html code-coverage.html \ + --root "$SOURCE_PATH" \ + --verbose \ + . + + - name: Upload code coverage results + if: ${{ always() && matrix.compiler == 'gnu-15' }} + uses: actions/upload-artifact@v7 + with: + if-no-files-found: ignore + name: code-coverage-html + path: ${{ env.UNIT_TESTS_PATH }}/build/code-coverage.html + retention-days: 7 diff --git a/.github/workflows/fleximod_test.yaml b/.github/workflows/fleximod_test.yaml index fbb37ac7d..87135ed94 100644 --- a/.github/workflows/fleximod_test.yaml +++ b/.github/workflows/fleximod_test.yaml @@ -2,7 +2,7 @@ on: pull_request: jobs: fleximod-test: - runs-on: ubuntu-latest + runs-on: ubuntu-slim strategy: fail-fast: false matrix: @@ -10,7 +10,7 @@ jobs: python-version: ["3.8", "3.x"] steps: - id: checkout-CESM - uses: actions/checkout@v5 + uses: actions/checkout@v6 - id: run-fleximod run: | $GITHUB_WORKSPACE/bin/git-fleximod update -o diff --git a/.github/workflows/fortran_unit_tests.yml b/.github/workflows/fortran_unit_tests.yml deleted file mode 100644 index 94a6b1197..000000000 --- a/.github/workflows/fortran_unit_tests.yml +++ /dev/null @@ -1,153 +0,0 @@ -name: Fortran Unit Tests - -on: - push: - branches: - - 'staging/**' - - development - pull_request: - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - gcc-toolchain: - name: Build and run with GCC ${{ matrix.version }} - runs-on: ubuntu-24.04 - strategy: - matrix: - version: [12, 13, 14] - env: - CC: gcc-${{ matrix.version }} - CXX: g++-${{ matrix.version }} - FC: gfortran-${{ matrix.version }} - PFUNIT_BUILD_TYPE: Release - PFUNIT_PATH: ${{ github.workspace }}/pFUnit - PFUNIT_REFERENCE: 'v4.13.0' - PIO_BUILD_TYPE: Release - PIO_PATH: ${{ github.workspace }}/ParallelIO - PIO_REFERENCE: 'pio2_6_7' - RRTMGP_DATA_REFERENCE: 'v1.9' - steps: - - name: Install dependencies - run: | - sudo apt update - sudo apt install -y libnetcdf-mpi-dev libnetcdff-dev libopenmpi-dev - - - name: Checkout CAM-SIMA - uses: actions/checkout@v5 - - # pFUnit takes a while to build. Cache it if possible to save time on consecutive workflow runs. - - name: Cache pFUnit - id: cache-pfunit - uses: actions/cache@v4 - with: - key: cache-pfunit-${{ env.PFUNIT_REFERENCE }}-gcc-v${{ matrix.version }}-cam-sima - path: ${{ env.PFUNIT_PATH }}/install - - # If there is a cache hit, just use the cached pFUnit and skip this step. - - name: Checkout pFUnit - if: ${{ steps.cache-pfunit.outputs.cache-hit != 'true' }} - uses: actions/checkout@v5 - with: - repository: Goddard-Fortran-Ecosystem/pFUnit - ref: ${{ env.PFUNIT_REFERENCE }} - path: pFUnit - - # If there is a cache hit, just use the cached pFUnit and skip this step. - - name: Build pFUnit - if: ${{ steps.cache-pfunit.outputs.cache-hit != 'true' }} - run: | - cmake \ - -D CMAKE_BUILD_TYPE="$PFUNIT_BUILD_TYPE" \ - -D CMAKE_INSTALL_PREFIX="$PFUNIT_PATH/install" \ - -B "$PFUNIT_PATH/build" \ - -S "$PFUNIT_PATH" - cmake --build "$PFUNIT_PATH/build" --config "$PFUNIT_BUILD_TYPE" - cmake --install "$PFUNIT_PATH/build" --config "$PFUNIT_BUILD_TYPE" --prefix "$PFUNIT_PATH/install" - - - name: Checkout PIO - uses: actions/checkout@v5 - with: - repository: NCAR/ParallelIO - ref: ${{ env.PIO_REFERENCE }} - path: ParallelIO - - - name: Build PIO - env: - CC: mpicc - CXX: mpic++ - FC: mpifort - run: | - cmake \ - -D CMAKE_BUILD_TYPE="$PIO_BUILD_TYPE" \ - -D CMAKE_INSTALL_PREFIX="$PIO_PATH/install" \ - -D NetCDF_C_LIBRARY="/usr/lib/x86_64-linux-gnu/libnetcdf_mpi.so" \ - -D NetCDF_Fortran_LIBRARY="/usr/lib/x86_64-linux-gnu/libnetcdff.so" \ - -D PIO_ENABLE_DOC=OFF \ - -D PIO_ENABLE_TESTS=OFF \ - -D PIO_ENABLE_TIMING=OFF \ - -D WITH_PNETCDF=OFF \ - -B "$PIO_PATH/build" \ - -S "$PIO_PATH" - cmake --build "$PIO_PATH/build" --config "$PIO_BUILD_TYPE" - cmake --install "$PIO_PATH/build" --config "$PIO_BUILD_TYPE" --prefix "$PIO_PATH/install" - - - name: Checkout atmospheric_physics - run: | - bin/git-fleximod update ncar-physics ccpp-framework share - - - name: Checkout rrtmgp-data for PIO file reader tests - uses: actions/checkout@v5 - with: - repository: earth-system-radiation/rrtmgp-data - ref: ${{ env.RRTMGP_DATA_REFERENCE }} - path: rrtmgp-data - - - name: Build Fortran unit tests - run: | - cmake \ - -D CMAKE_PREFIX_PATH="$PFUNIT_PATH/install;$PIO_PATH/install" \ - -D CAM_SIMA_ENABLE_CODE_COVERAGE=ON \ - -D CAM_SIMA_ENABLE_IO_TESTS=ON \ - -D CAM_SIMA_ENABLE_TESTS=ON \ - -B ./build \ - -S ./test/unit/fortran - cd build - make - - - name: Run Fortran unit tests - run: | - ctest \ - --output-junit test_results.xml \ - --output-on-failure \ - --test-dir ./build \ - --test-output-size-failed 524288 \ - --test-output-size-passed 524288 \ - --verbose - - - name: Upload unit test results - uses: actions/upload-artifact@v4 - with: - name: unit-test-results-${{ env.FC }} - path: build/test_results.xml - - - name: Setup Gcov - run: | - python3 -m venv venv - source venv/bin/activate - pip3 install gcovr - - - name: Run Gcov - run: | - source venv/bin/activate - cd build - gcovr --gcov-executable gcov-${{ matrix.version }} -r .. --filter '\.\./src' --html cam_sima_code_coverage.html --txt - - - name: Upload code coverage results - uses: actions/upload-artifact@v4 - with: - name: code-coverage-results-${{ env.FC }} - path: build/cam_sima_code_coverage.html diff --git a/.github/workflows/mpas_dynamical_core_ci.yml b/.github/workflows/mpas_dynamical_core_ci.yml index 98e6b5df5..541138f74 100644 --- a/.github/workflows/mpas_dynamical_core_ci.yml +++ b/.github/workflows/mpas_dynamical_core_ci.yml @@ -27,10 +27,10 @@ jobs: # A pull request that requires those checks to be successful will be blocked from merging." conditional-check: name: Check if jobs should run - timeout-minutes: 1 runs-on: ubuntu-slim outputs: should-run: ${{ steps.conditional.outputs.result }} + timeout-minutes: 1 steps: - name: Checkout CAM-SIMA uses: actions/checkout@v6 @@ -126,14 +126,14 @@ jobs: # when a matrix job is set as a required status check, skipping it due to the conditional will cause a pull request to be # blocked from merging. overall-status: - name: Overall status - timeout-minutes: 1 - runs-on: ubuntu-slim + name: Overall status (MPAS Dynamical Core CI) needs: - conditional-check - source-code-linting - unit-tests if: ${{ always() }} + runs-on: ubuntu-slim + timeout-minutes: 1 steps: - name: Evaluate overall status run: | @@ -195,13 +195,13 @@ jobs: write_result_and_exit true source-code-linting: name: Lint Fortran source code - timeout-minutes: 10 - runs-on: ubuntu-slim needs: conditional-check if: ${{ needs.conditional-check.outputs.should-run == 'true' }} + runs-on: ubuntu-slim env: FORTITUDE_VERSION: 0.7.* SOURCE_CODE_PATH: ${{ github.workspace }}/src/dynamics/mpas + timeout-minutes: 10 steps: - name: Checkout CAM-SIMA uses: actions/checkout@v6 @@ -221,7 +221,13 @@ jobs: - name: Lint Fortran source code run: | source venv-fortitude/bin/activate - fortitude --config-file "$SOURCE_CODE_PATH/assets/fortitude_config.toml" check --exit-zero --output-file "$SOURCE_CODE_PATH/source-code-linting.log" --preview "$SOURCE_CODE_PATH" + fortitude \ + --config-file "$SOURCE_CODE_PATH/assets/fortitude_config.toml" \ + check \ + --exit-zero \ + --output-file "$SOURCE_CODE_PATH/source-code-linting.log" \ + --preview \ + "$SOURCE_CODE_PATH" cat "$SOURCE_CODE_PATH/source-code-linting.log" - name: Upload Fortran source code linting log @@ -234,7 +240,15 @@ jobs: retention-days: 7 unit-tests: name: Build and run unit tests (${{ matrix.compiler }}) - timeout-minutes: 10 + needs: conditional-check + if: ${{ needs.conditional-check.outputs.should-run == 'true' }} + runs-on: ubuntu-24.04 + container: + image: ghcr.io/kuanchihwang/atm-sci-container:2026-06-12_${{ matrix.compiler }}_${{ matrix.mpi }} + env: + CONTAINER_ENVIRONMENT: pfunit + UNIT_TESTS_BUILD_TYPE: Debug + UNIT_TESTS_PATH: ${{ github.workspace }}/src/dynamics/mpas strategy: fail-fast: false matrix: @@ -250,15 +264,7 @@ jobs: # Testing with a single MPI implementation is sufficient for now. mpi: - open-mpi-5 - runs-on: ubuntu-24.04 - container: - image: ghcr.io/kuanchihwang/atm-sci-container:2026-04-12_${{ matrix.compiler }}_${{ matrix.mpi }} - needs: conditional-check - if: ${{ needs.conditional-check.outputs.should-run == 'true' }} - env: - CONTAINER_ENVIRONMENT: pfunit - UNIT_TESTS_BUILD_TYPE: Debug - UNIT_TESTS_PATH: ${{ github.workspace }}/src/dynamics/mpas + timeout-minutes: 10 steps: - name: Checkout CAM-SIMA uses: actions/checkout@v6 @@ -266,13 +272,23 @@ jobs: - name: Build unit tests run: | source "$(command -v container-entrypoint-hook.sh)" - cmake -D CMAKE_BUILD_TYPE="$UNIT_TESTS_BUILD_TYPE" -B "$UNIT_TESTS_PATH/build" -S "$UNIT_TESTS_PATH" - cmake --build "$UNIT_TESTS_PATH/build" --config "$UNIT_TESTS_BUILD_TYPE" + cmake \ + -D CMAKE_BUILD_TYPE="$UNIT_TESTS_BUILD_TYPE" \ + -B "$UNIT_TESTS_PATH/build" \ + -S "$UNIT_TESTS_PATH" + cmake \ + --build "$UNIT_TESTS_PATH/build" \ + --config "$UNIT_TESTS_BUILD_TYPE" - name: Run unit tests run: | source "$(command -v container-entrypoint-hook.sh)" - ctest --build-config "$UNIT_TESTS_BUILD_TYPE" --output-log "$UNIT_TESTS_PATH/build/unit-tests.log" --output-on-failure --test-dir "$UNIT_TESTS_PATH/build" --verbose + ctest \ + --build-config "$UNIT_TESTS_BUILD_TYPE" \ + --output-log "$UNIT_TESTS_PATH/build/unit-tests.log" \ + --output-on-failure \ + --test-dir "$UNIT_TESTS_PATH/build" \ + --verbose - name: Upload unit tests log if: ${{ always() }} diff --git a/.github/workflows/python_unit_tests.yml b/.github/workflows/python_unit_tests.yml index d406a79e6..3152d8060 100644 --- a/.github/workflows/python_unit_tests.yml +++ b/.github/workflows/python_unit_tests.yml @@ -17,8 +17,8 @@ jobs: #a PR is either opened or synced (i.e. additional commits are pushed #to branch involved in PR). python_unit_tests: - if: github.event_name == 'pull_request' || github.repository == 'ESCOMP/CAM-SIMA' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest + if: github.repository == 'ESCOMP/CAM-SIMA' + runs-on: ubuntu-slim strategy: matrix: #All of these python versions will be used to run tests: @@ -26,7 +26,7 @@ jobs: fail-fast: false steps: # Acquire github action routines: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 # Acquire specific version of python: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 diff --git a/.github/workflows/source_code_lint.yml b/.github/workflows/source_code_lint.yml index cc824f6bb..06620e3c1 100644 --- a/.github/workflows/source_code_lint.yml +++ b/.github/workflows/source_code_lint.yml @@ -11,10 +11,10 @@ jobs: #collects all modified files, and then passes those files #off to additional scripts to run the actual tests. source_code_tests: - runs-on: ubuntu-latest + runs-on: ubuntu-slim steps: # acquire github action routines - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 # acquire specific version of python - name: Set up Python 3.10 uses: actions/setup-python@v6 diff --git a/src/core_utils/CMakeLists.txt b/src/core_utils/CMakeLists.txt index 9919672f0..3990d9d69 100644 --- a/src/core_utils/CMakeLists.txt +++ b/src/core_utils/CMakeLists.txt @@ -1,9 +1,13 @@ -set(CORE_UTILS_SRC string_core_utils.F90) - # core_utils is not integrated into the CMake build of any top level # project yet and this CMake is for testing purposes only. # Making a change to this project's CMake will not impact the build of # a parent project at this time. -add_library(core_utils ${CORE_UTILS_SRC}) -target_include_directories(core_utils PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) - +add_library(core_utils) +target_sources(core_utils + PRIVATE + string_core_utils.F90 +) +target_include_directories(core_utils + INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} +) diff --git a/src/physics/utils/CMakeLists.txt b/src/physics/utils/CMakeLists.txt index 166169871..3821edad4 100644 --- a/src/physics/utils/CMakeLists.txt +++ b/src/physics/utils/CMakeLists.txt @@ -1,21 +1,22 @@ -set(IO_READER_SOURCE pio_reader.F90 - pio_reader_sub.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/../ncar_ccpp/phys_utils/ccpp_io_reader.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/../../../share/src/shr_kind_mod.F90) - # io_reader is not integrated into the CMake build of any top level # project yet and this CMake is for testing purposes only. # Making a change to this project's CMake will not impact the build of # a parent project at this time. -add_library(io_reader ${IO_READER_SOURCE}) -target_link_libraries(io_reader PUBLIC - MPI::MPI_Fortran - MPI::MPI_C - NetCDF::NetCDF_C - NetCDF::NetCDF_Fortran - PIO::PIO_Fortran - PIO::PIO_C - cam_pio_utils - ccpp_framework) -target_include_directories(io_reader PRIVATE ${CMAKE_BINARY_DIR}/ccpp_framework_stub - ${CMAKE_BINARY_DIR}/mock_routines) +add_library(io_reader) +target_sources(io_reader + PRIVATE + pio_reader.F90 + pio_reader_sub.F90 + ${CMAKE_CURRENT_SOURCE_DIR}/../ncar_ccpp/phys_utils/ccpp_io_reader.F90 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../share/src/shr_kind_mod.F90 +) +target_include_directories(io_reader + INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} +) +target_link_libraries(io_reader + PRIVATE + PIO::PIO_Fortran + cam_pio_utils + ccpp_framework +) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 21b46f773..000000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.21) - -project( - cam-sima-tests - VERSION 0.0.0 - LANGUAGES Fortran -) - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/cmake) -set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -option(CCPP_ENABLE_MEMCHECK "Enable memory checks in tests" OFF) - -set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) -set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) - -set(CAM_SIMA_SRC_PATH ${CMAKE_SOURCE_DIR}/../src) -set(CAM_SIMA_TEST_PATH ${CMAKE_SOURCE_DIR}) - -include(TestUtils) -include(CTest) -enable_testing() - -add_subdirectory(unit) \ No newline at end of file diff --git a/test/cmake/SetDefaults.cmake b/test/cmake/SetDefaults.cmake deleted file mode 100644 index 39e5d1d5c..000000000 --- a/test/cmake/SetDefaults.cmake +++ /dev/null @@ -1,4 +0,0 @@ -# Overwrite the init values choosen by CMake -if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU") - set(CMAKE_Fortran_FLAGS_DEBUG_INIT "-g") -endif() diff --git a/test/cmake/TestUtils.cmake b/test/cmake/TestUtils.cmake deleted file mode 100644 index df31b9cd5..000000000 --- a/test/cmake/TestUtils.cmake +++ /dev/null @@ -1,23 +0,0 @@ -################################################################################ -# Utility functions for creating tests - -if(CCPP_ENABLE_MEMCHECK) - find_program(MEMORYCHECK_COMMAND "valgrind") - - # Set the Valgrind suppressions file for tests - set(MEMCHECK_SUPPRESS "--suppressions=${CMAKE_SOURCE_DIR}/valgrind.supp") -endif() - -################################################################################ -# Runs a test with memory checking if enabled - -function(add_memory_check_test test_name test_binary test_args working_dir) - if(CCPP_ENABLE_MEMCHECK) - add_test(NAME memcheck_${test_name} - COMMAND mpirun -v -np 1 ${MEMORYCHECK_COMMAND} --leak-check=full --error-exitcode=1 --trace-children=yes --gen-suppressions=all ${MEMCHECK_SUPPRESS} - ${test_binary} ${test_args} - WORKING_DIRECTORY ${working_dir}) - endif() -endfunction(add_memory_check_test) - -################################################################################ \ No newline at end of file diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile deleted file mode 100644 index 474be7e53..000000000 --- a/test/docker/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -# This Dockerfile is designed for running CAM-SIMA fortran unit tests and integration tests. -FROM ubuntu:22.04 - -ARG BUILD_TYPE=Debug - -RUN apt update \ - && apt install -y sudo \ - && useradd -m test_user \ - && echo "test_user ALL=(root) NOPASSWD: ALL" >> /etc/sudoers.d/test_user \ - && chmod 0440 /etc/sudoers.d/test_user - -USER test_user -WORKDIR /home/test_user - -RUN sudo apt update \ - && sudo apt -y install \ - cmake \ - cmake-curses-gui \ - gfortran \ - git \ - libopenmpi-dev \ - make \ - openmpi-bin \ - valgrind \ - vim \ - && sudo apt clean - -ENV FC=mpif90 -ENV FFLAGS="-I/usr/include/" - -COPY . cam_sima -RUN sudo chown -R test_user:test_user cam_sima - -RUN cd cam_sima/test \ - && cmake -S . -B build \ - -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ - -D CCPP_ENABLE_MEMCHECK=ON \ - && cmake --build ./build - -WORKDIR /home/test_user/cam_sima/test/build \ No newline at end of file diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt deleted file mode 100644 index e220ee79c..000000000 --- a/test/unit/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(physics) \ No newline at end of file diff --git a/test/unit/fortran/CMakeLists.txt b/test/unit/fortran/CMakeLists.txt index 91af5b8f7..898fc1b38 100644 --- a/test/unit/fortran/CMakeLists.txt +++ b/test/unit/fortran/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.21) project(CAM-SIMA-core-utils LANGUAGES Fortran C) @@ -6,33 +6,38 @@ option(CAM_SIMA_ENABLE_TESTS "Run pFUnit unit tests" OFF) option(CAM_SIMA_ENABLE_CODE_COVERAGE "Run code coverage tool" OFF) option(CAM_SIMA_ENABLE_IO_TESTS "Run IO test integration" OFF) -if(NOT CAM-SIMA-core-utils_IS_TOP_LEVEL) - message(WARNING "CAM-SIMA-core-utils is not integrated into the CMake build of any top level " - "project yet and this CMake is for testing purposes only. " - "Making a change to this project's CMake will not impact the build of " - "a parent project at this time.") +if(NOT PROJECT_IS_TOP_LEVEL) + message(WARNING + "CAM-SIMA-core-utils is not integrated into the CMake build of any top level + project yet and this CMake is for testing purposes only. + Making a change to this project's CMake will not impact the build of + a parent project at this time." + ) endif() # Overwrite the init flags chosen by CMake if(${CMAKE_Fortran_COMPILER_ID} MATCHES "GNU") add_compile_options(-ffree-line-length-none) -endif() -if(CAM_SIMA_ENABLE_CODE_COVERAGE) - add_compile_options(-O0 --coverage) - add_link_options(--coverage) + if(CAM_SIMA_ENABLE_CODE_COVERAGE) + add_compile_options(--coverage -fprofile-abs-path) + add_link_options(--coverage -fprofile-abs-path) + + set(CMAKE_BUILD_TYPE "Debug") + endif() endif() -add_subdirectory(${CMAKE_SOURCE_DIR}/../../../src/core_utils ${CMAKE_BINARY_DIR}/src) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../src/core_utils + ${CMAKE_CURRENT_BINARY_DIR}/lib/core_utils) if(CAM_SIMA_ENABLE_TESTS OR CAM_SIMA_ENABLE_CODE_COVERAGE OR CAM_SIMA_ENABLE_IO_TESTS) - set(CMAKE_BUILD_TYPE Debug) find_package(PFUNIT REQUIRED) enable_testing() if(CAM_SIMA_ENABLE_TESTS) add_subdirectory(src/core_utils) endif() + if(CAM_SIMA_ENABLE_IO_TESTS) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -44,7 +49,7 @@ if(CAM_SIMA_ENABLE_TESTS OR CAM_SIMA_ENABLE_CODE_COVERAGE OR CAM_SIMA_ENABLE_IO_ add_subdirectory(mock_routines) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../src/physics/utils - ${CMAKE_CURRENT_BINARY_DIR}/src/physics/utils) + ${CMAKE_CURRENT_BINARY_DIR}/lib/physics/utils) add_subdirectory(src/pio_reader) endif() diff --git a/test/unit/fortran/ccpp_framework_stub/CMakeLists.txt b/test/unit/fortran/ccpp_framework_stub/CMakeLists.txt index a31883898..6885e0bfc 100644 --- a/test/unit/fortran/ccpp_framework_stub/CMakeLists.txt +++ b/test/unit/fortran/ccpp_framework_stub/CMakeLists.txt @@ -1,2 +1,9 @@ - add_library(ccpp_framework ccpp_kinds.F90) - +add_library(ccpp_framework) +target_sources(ccpp_framework + PRIVATE + ccpp_kinds.F90 +) +target_include_directories(ccpp_framework + INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} +) diff --git a/test/unit/fortran/ccpp_framework_stub/ccpp_kinds.F90 b/test/unit/fortran/ccpp_framework_stub/ccpp_kinds.F90 index 953b359e8..bdefbffe2 100644 --- a/test/unit/fortran/ccpp_framework_stub/ccpp_kinds.F90 +++ b/test/unit/fortran/ccpp_framework_stub/ccpp_kinds.F90 @@ -3,9 +3,8 @@ module ccpp_kinds use ISO_FORTRAN_ENV, only: kind_phys => REAL64 implicit none - private - public kind_phys + private + public :: kind_phys end module ccpp_kinds - \ No newline at end of file diff --git a/test/unit/fortran/mock_routines/CMakeLists.txt b/test/unit/fortran/mock_routines/CMakeLists.txt index 939755a87..a02deed0c 100644 --- a/test/unit/fortran/mock_routines/CMakeLists.txt +++ b/test/unit/fortran/mock_routines/CMakeLists.txt @@ -1,6 +1,14 @@ -add_library(cam_pio_utils cam_pio_utils.F90) -target_link_libraries(cam_pio_utils PUBLIC MPI::MPI_Fortran - PIO::PIO_Fortran - PIO::PIO_C - NetCDF::NetCDF_C - NetCDF::NetCDF_Fortran) +add_library(cam_pio_utils) +target_sources(cam_pio_utils + PRIVATE + cam_pio_utils.F90 +) +target_include_directories(cam_pio_utils + INTERFACE + ${CMAKE_CURRENT_BINARY_DIR} +) +target_link_libraries(cam_pio_utils + PRIVATE + MPI::MPI_Fortran + PIO::PIO_Fortran +) diff --git a/test/unit/fortran/src/core_utils/test_string_core_utils.pf b/test/unit/fortran/src/core_utils/test_string_core_utils.pf index 1dc68e0d4..056f54776 100644 --- a/test/unit/fortran/src/core_utils/test_string_core_utils.pf +++ b/test/unit/fortran/src/core_utils/test_string_core_utils.pf @@ -1,6 +1,12 @@ +module test_string_core_utils + use funit + + implicit none + + public +contains @test subroutine test_integer_one_to_str() - use funit use string_core_utils, only : core_to_str integer :: to_convert @@ -12,7 +18,6 @@ end subroutine test_integer_one_to_str @test subroutine test_integer_with_leading_zeros_to_str() - use funit use string_core_utils, only : core_to_str integer :: to_convert @@ -26,7 +31,6 @@ end subroutine test_integer_with_leading_zeros_to_str @test subroutine test_integer_with_trailing_zeros_to_str() - use funit use string_core_utils, only : core_to_str integer :: to_convert @@ -40,7 +44,6 @@ end subroutine test_integer_with_trailing_zeros_to_str @test subroutine test_one_int_date_to_yyyymmdd() - use funit use string_core_utils, only : core_int_date_to_yyyymmdd integer :: to_convert @@ -54,7 +57,6 @@ end subroutine test_one_int_date_to_yyyymmdd @test subroutine test_zero_int_seconds_to_hhmmss() - use funit use string_core_utils, only : core_int_seconds_to_hhmmss integer :: to_convert @@ -69,7 +71,6 @@ end subroutine test_zero_int_seconds_to_hhmmss @test subroutine test_stringify_empty_arrays() use, intrinsic :: iso_fortran_env, only: int32, int64, real32, real64 - use funit use string_core_utils, only: stringify character(len=128), allocatable :: carr(:) @@ -92,7 +93,6 @@ end subroutine test_stringify_empty_arrays @test subroutine test_stringify_character_array() - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator = '<' @@ -123,7 +123,6 @@ end subroutine test_stringify_character_array @test subroutine test_stringify_integer_array() use, intrinsic :: iso_fortran_env, only: int32, int64 - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator = '<' @@ -157,7 +156,6 @@ end subroutine test_stringify_integer_array @test subroutine test_stringify_integer_extreme_values() use, intrinsic :: iso_fortran_env, only: int32, int64 - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator_with_spaces = ' < ' @@ -190,7 +188,6 @@ end subroutine test_stringify_integer_extreme_values @test subroutine test_stringify_floating_point_array() use, intrinsic :: iso_fortran_env, only: real32, real64 - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator = '<' @@ -228,7 +225,6 @@ end subroutine test_stringify_floating_point_array @test subroutine test_stringify_floating_point_scientific_notation() use, intrinsic :: iso_fortran_env, only: real32, real64 - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator_with_spaces = ' < ' @@ -257,7 +253,6 @@ end subroutine test_stringify_floating_point_scientific_notation @test subroutine test_stringify_floating_point_extreme_values() use, intrinsic :: iso_fortran_env, only: real32, real64 - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator_with_spaces = ' < ' @@ -293,7 +288,6 @@ end subroutine test_stringify_floating_point_extreme_values @test subroutine test_stringify_logical_array() - use funit use string_core_utils, only: stringify character(len=*), parameter :: custom_separator = '.or.' @@ -322,7 +316,6 @@ end subroutine test_stringify_logical_array @test subroutine test_split_by_empty_string_set() - use funit use string_core_utils, only: split character(*), parameter :: test_string_comma_separated = & @@ -358,7 +351,6 @@ end subroutine test_split_by_empty_string_set @test subroutine test_split_by_forward_searches() - use funit use string_core_utils, only: split character(*), parameter :: test_string_comma_separated = & @@ -393,7 +385,6 @@ end subroutine test_split_by_forward_searches @test subroutine test_split_by_backward_searches() - use funit use string_core_utils, only: split character(*), parameter :: test_string_comma_separated = & @@ -428,7 +419,6 @@ end subroutine test_split_by_backward_searches @test subroutine test_split_by_out_of_bounds_searches() - use funit use string_core_utils, only: split character(*), parameter :: test_string_comma_separated = & @@ -476,7 +466,6 @@ end subroutine test_split_by_out_of_bounds_searches @test subroutine test_tokenize_into_first_last_by_empty_string_set() - use funit use string_core_utils, only: tokenize character(*), parameter :: test_string_comma_separated = & @@ -508,7 +497,6 @@ end subroutine test_tokenize_into_first_last_by_empty_string_set @test subroutine test_tokenize_into_first_last_by_known_string_set() - use funit use string_core_utils, only: tokenize character(*), parameter :: test_string_comma_separated = & @@ -543,7 +531,6 @@ end subroutine test_tokenize_into_first_last_by_known_string_set @test subroutine test_tokenize_into_tokens_separator_by_empty_string_set() - use funit use string_core_utils, only: tokenize character(*), parameter :: test_string_comma_separated = & @@ -599,7 +586,6 @@ end subroutine test_tokenize_into_tokens_separator_by_empty_string_set @test subroutine test_tokenize_into_tokens_separator_by_known_string_set() - use funit use string_core_utils, only: tokenize character(*), parameter :: test_string_comma_separated = & @@ -654,7 +640,6 @@ end subroutine test_tokenize_into_tokens_separator_by_known_string_set @test subroutine test_get_last_significant_char_empty_string() - use funit use string_core_utils, only: get_last_significant_char character(len=10) :: test_string @@ -665,7 +650,6 @@ end subroutine test_get_last_significant_char_empty_string @test subroutine test_get_last_significant_char_all_blanks() - use funit use string_core_utils, only: get_last_significant_char character(len=10) :: test_string @@ -676,7 +660,6 @@ end subroutine test_get_last_significant_char_all_blanks @test subroutine test_get_last_significant_char_trailing_spaces() - use funit use string_core_utils, only: get_last_significant_char character(len=20) :: test_string @@ -687,7 +670,6 @@ end subroutine test_get_last_significant_char_trailing_spaces @test subroutine test_get_last_significant_char_no_trailing_spaces() - use funit use string_core_utils, only: get_last_significant_char character(len=7) :: test_string @@ -698,7 +680,6 @@ end subroutine test_get_last_significant_char_no_trailing_spaces @test subroutine test_last_non_digit_empty_string() - use funit use string_core_utils, only: last_non_digit character(len=10) :: test_string @@ -709,7 +690,6 @@ end subroutine test_last_non_digit_empty_string @test subroutine test_last_non_digit_all_digits() - use funit use string_core_utils, only: last_non_digit character(len=10) :: test_string @@ -720,7 +700,6 @@ end subroutine test_last_non_digit_all_digits @test subroutine test_last_non_digit_with_trailing_digits() - use funit use string_core_utils, only: last_non_digit character(len=20) :: test_string @@ -731,7 +710,6 @@ end subroutine test_last_non_digit_with_trailing_digits @test subroutine test_last_non_digit_no_trailing_digits() - use funit use string_core_utils, only: last_non_digit character(len=20) :: test_string @@ -742,7 +720,6 @@ end subroutine test_last_non_digit_no_trailing_digits @test subroutine test_last_non_digit_single_digit() - use funit use string_core_utils, only: last_non_digit character(len=10) :: test_string @@ -753,7 +730,6 @@ end subroutine test_last_non_digit_single_digit @test subroutine test_last_non_digit_with_leading_zeros() - use funit use string_core_utils, only: last_non_digit character(len=15) :: test_string @@ -764,7 +740,6 @@ end subroutine test_last_non_digit_with_leading_zeros @test subroutine test_increment_string_no_trailing_digits() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -779,7 +754,6 @@ end subroutine test_increment_string_no_trailing_digits @test subroutine test_increment_string_single_digit_increment() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -794,7 +768,6 @@ end subroutine test_increment_string_single_digit_increment @test subroutine test_increment_string_multiple_digits() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -809,7 +782,6 @@ end subroutine test_increment_string_multiple_digits @test subroutine test_increment_string_with_rollover() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -824,7 +796,6 @@ end subroutine test_increment_string_with_rollover @test subroutine test_increment_string_with_large_increment() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -839,7 +810,6 @@ end subroutine test_increment_string_with_large_increment @test subroutine test_increment_string_positive_overflow() - use funit use string_core_utils, only: increment_string character(len=20) :: test_string @@ -850,4 +820,4 @@ subroutine test_increment_string_positive_overflow() @assertEqual(-2, result) end subroutine test_increment_string_positive_overflow - +end module test_string_core_utils diff --git a/test/unit/fortran/src/pio_reader/CMakeLists.txt b/test/unit/fortran/src/pio_reader/CMakeLists.txt index 82a23ee2c..5df26307a 100644 --- a/test/unit/fortran/src/pio_reader/CMakeLists.txt +++ b/test/unit/fortran/src/pio_reader/CMakeLists.txt @@ -8,6 +8,3 @@ add_pfunit_ctest(pio_tests PIO::PIO_C NetCDF::NetCDF_C NetCDF::NetCDF_Fortran) -target_include_directories(pio_tests PRIVATE ${CMAKE_BINARY_DIR}/utils - ${CMAKE_BINARY_DIR}/ccpp_framework_stub - ${CMAKE_BINARY_DIR}/src/physics/utils) diff --git a/test/unit/fortran/src/pio_reader/test_pio_reader.pf b/test/unit/fortran/src/pio_reader/test_pio_reader.pf index accb7f0cb..940407400 100644 --- a/test/unit/fortran/src/pio_reader/test_pio_reader.pf +++ b/test/unit/fortran/src/pio_reader/test_pio_reader.pf @@ -1,11 +1,17 @@ !This file contains tests for the PIO version of the CCPP NetCDF reader !object (pio_reader.F90) as implemented in CAM-SIMA. +module test_pio_reader + use funit + + implicit none + + public +contains !+++++++++++++++++++++++++++++++++++++++++++++++++++++ @test subroutine starting_test() - use funit use mpi, only: mpi_init, MPI_SUCCESS @@ -27,7 +33,6 @@ end subroutine starting_test subroutine test_pio_reader_open_close_file() !Check that the PIO reader can open and !close a file successfully. - use funit use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -83,8 +88,6 @@ subroutine test_pio_reader_already_opened_file_err() ! Check that the PIO reader raises the correct error ! when attempting to open a file that is already opened. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -130,8 +133,6 @@ subroutine test_pio_reader_no_file_err() ! Check that the PIO reader raises the correct error ! when attempting to open a file that does not exist. - use funit - use pio, only: PIO_NOERR use ccpp_io_reader, only: abstract_netcdf_reader_t @@ -177,8 +178,6 @@ subroutine test_pio_reader_1d_int_read() ! Check that the PIO reader can read a 1D integer variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -233,8 +232,6 @@ subroutine test_pio_reader_2d_int_read() ! Check that the PIO reader can read a 2D integer variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -288,8 +285,6 @@ subroutine test_pio_reader_3d_int_read() ! Check that the PIO reader can read a 3D integer variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -346,8 +341,6 @@ subroutine test_pio_reader_1d_char_read() ! Check that the PIO reader can read a 1D character variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -419,8 +412,6 @@ subroutine test_pio_reader_0d_real_read() ! Check that the PIO reader can read a scalar real variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -477,8 +468,6 @@ subroutine test_pio_reader_1d_real_read() ! Check that the PIO reader can read a 1D real variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -536,8 +525,6 @@ subroutine test_pio_reader_2d_real_read() ! Check that the PIO reader can read a 2D real variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -598,8 +585,6 @@ subroutine test_pio_reader_3d_real_read() ! Check that the PIO reader can read a 3D real variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -668,8 +653,6 @@ subroutine test_pio_reader_4d_real_read_with_dims() ! Check that the PIO reader can read a 4D real variable ! from a file successfully, and that the dimensions are correct. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -775,8 +758,6 @@ subroutine test_pio_reader_int_get_var_file_not_opened_err() ! when attempting to read an integer variable from a file ! that is not opened. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -817,8 +798,6 @@ subroutine test_pio_reader_char_get_var_file_not_opened_err() ! when attempting to read a character variable from ! a file that is not opened. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -859,8 +838,6 @@ subroutine test_pio_reader_real_get_var_file_not_opened_err() ! when attempting to read a character variable from ! a file that is not opened. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -907,8 +884,6 @@ subroutine test_pio_reader_get_var_open_close_err() ! NOTE: This behavior will be the same for all variable types, ! so we only need to test it once. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -957,8 +932,6 @@ subroutine test_pio_reader_int_get_var_missing_var() ! Check that the PIO reader raises the correct error ! when attempting to read an integer variable that does not exist. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1006,8 +979,6 @@ subroutine test_pio_reader_char_get_var_missing_var() ! when attempting to read an character variable that ! does not exist. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1055,8 +1026,6 @@ subroutine test_pio_reader_real_get_var_missing_var() ! when attempting to read a real variable that does ! not exist. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1106,8 +1075,6 @@ subroutine test_pio_reader_int_get_var_bad_rank() ! when attempting to read an integer variable with an ! incorrectly declared number of dimensions. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1155,8 +1122,6 @@ subroutine test_pio_reader_char_get_var_bad_rank() ! when attempting to read a character variable with ! an incorrectly declared number of dimensions. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1205,8 +1170,6 @@ subroutine test_pio_reader_real_get_var_bad_rank() ! when attempting to read a real variable with ! an incorrectly declared number of dimensions. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1259,8 +1222,6 @@ subroutine test_pio_reader_1d_int_full_subset_read() ! from a file successfully with subsetting that has ! a count array with the same rank as the output variable. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1317,8 +1278,6 @@ subroutine test_pio_reader_2d_int_full_subset_read() ! Check that the PIO reader can read a 2D integer variable ! from a file successfully. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1392,8 +1351,6 @@ subroutine test_pio_reader_1d_real_full_subset_read() ! Check that the PIO reader can read a 1D real variable ! from a file successfully with subsetting. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1453,8 +1410,6 @@ subroutine test_pio_reader_3d_real_full_subset_read ! Check that the PIO reader can read a 3D real variable ! from a file successfully with subsetting. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1514,8 +1469,6 @@ subroutine test_pio_reader_1d_char_full_subset_read() ! Check that the PIO reader can read a 3D real ! variable from a file successfully with subsetting. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1581,8 +1534,6 @@ subroutine test_pio_reader_missing_start_argument() ! a "count" argument provided, but with no "start" ! argument. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1631,8 +1582,6 @@ subroutine test_pio_reader_missing_count_argument() ! a "start" argument provided, but with no "count" ! argument. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1680,8 +1629,6 @@ subroutine test_pio_reader_0d_real_subset_err() ! correct error when a user attempts to subset ! a scalar (0-D) variable. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1733,8 +1680,6 @@ subroutine test_pio_reader_bad_num_start_elements() ! when attempting to read a variable with ! a "start" argument that has an incorrect number of elements. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1782,8 +1727,6 @@ subroutine test_pio_reader_bad_num_count_elements() ! when attempting to read a variable with ! a "count" argument that has an incorrect number of elements. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1831,8 +1774,6 @@ subroutine test_pio_reader_bad_start_element_range() ! when attempting to read a variable with ! a "start" argument that has an element out of range. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1890,8 +1831,6 @@ subroutine test_pio_reader_bad_count_element_range() ! when attempting to read a variable with ! a "count" argument that has an element out of range. - use funit - use ccpp_io_reader, only: abstract_netcdf_reader_t use ccpp_io_reader, only: create_netcdf_reader_t @@ -1956,7 +1895,6 @@ end subroutine test_pio_reader_bad_count_element_range @test subroutine final_test() - use funit use mpi, only: mpi_finalize, MPI_SUCCESS @@ -1969,3 +1907,4 @@ subroutine final_test() @assertEqual(MPI_SUCCESS, mpi_ierr) end subroutine final_test +end module test_pio_reader diff --git a/test/unit/physics/CMakeLists.txt b/test/unit/physics/CMakeLists.txt deleted file mode 100644 index 47202fc6c..000000000 --- a/test/unit/physics/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(utils) \ No newline at end of file diff --git a/test/unit/physics/utils/CMakeLists.txt b/test/unit/physics/utils/CMakeLists.txt deleted file mode 100644 index abf721000..000000000 --- a/test/unit/physics/utils/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Test orbital_data module -add_executable(test_physics_utils_orbital_data test_orbital_data.F90 test_orbital_data_stubs.F90) - -target_sources(test_physics_utils_orbital_data - PUBLIC - ${CAM_SIMA_SRC_PATH}/physics/utils/orbital_data.F90 -) - -target_compile_options(test_physics_utils_orbital_data PRIVATE -ffree-line-length-none) - -add_test( - NAME test_physics_utils_orbital_data - COMMAND $ - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} -) - -add_memory_check_test(test_physics_utils_orbital_data $ "" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) \ No newline at end of file diff --git a/test/unit/physics/utils/test_orbital_data.F90 b/test/unit/physics/utils/test_orbital_data.F90 deleted file mode 100644 index d04c5573a..000000000 --- a/test/unit/physics/utils/test_orbital_data.F90 +++ /dev/null @@ -1,57 +0,0 @@ -! Copyright (C) 2024 National Science Foundation-National Center for Atmospheric Research -! SPDX-License-Identifier: Apache-2.0 -!-------------------------------------------------------------------------- -! -! Tests of the orbital_data module. -! -!-------------------------------------------------------------------------- - -! Assert macros -#define ASSERT(x) if (.not.(x)) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: x"; stop 1; endif -#define ASSERT_NEAR( a, b, abs_error ) if( (abs(a - b) >= abs_error) .and. (abs(a - b) /= 0.0) ) then; write(*,*) "Assertion failed[", __FILE__, ":", __LINE__, "]: a, b"; stop 1; endif - -program test_orbital_data - - implicit none - - call test_orbital_data_functions() - -contains - - subroutine test_orbital_data_functions - - use orbital_data - use shr_kind_mod, only: R8 => SHR_KIND_R8 - implicit none - - integer, parameter :: NUMBER_OF_COLUMNS = 3 - real(kind=R8) :: calendar_day - real(kind=R8) :: latitudes(NUMBER_OF_COLUMNS) - real(kind=R8) :: longitudes(NUMBER_OF_COLUMNS) - integer :: i - - calendar_day = 10.5_R8 - latitudes = [1.0_R8, 2.0_R8, 3.0_R8] - longitudes = [4.0_R8, 5.0_R8, 6.0_R8] - - call orbital_data_init(NUMBER_OF_COLUMNS) - - ASSERT(allocated(solar_zenith_angle)) - ASSERT(size(solar_zenith_angle) == NUMBER_OF_COLUMNS) - ASSERT(all(solar_zenith_angle == -1.0_R8)) - ASSERT(solar_declination == -1.0_R8) - ASSERT(earth_sun_distance == -1.0_R8) - - call orbital_data_advance(calendar_day, latitudes, longitudes) - - ASSERT(allocated(solar_zenith_angle)) - ASSERT(size(solar_zenith_angle) == NUMBER_OF_COLUMNS) - ASSERT_NEAR(solar_zenith_angle(1), acos(latitudes(1) + longitudes(1) + calendar_day * 21.0_R8), 1.0E-6_R8) - ASSERT_NEAR(solar_zenith_angle(2), acos(latitudes(2) + longitudes(2) + calendar_day * 21.0_R8), 1.0E-6_R8) - ASSERT_NEAR(solar_zenith_angle(3), acos(latitudes(3) + longitudes(3) + calendar_day * 21.0_R8), 1.0E-6_R8) - ASSERT(solar_declination == calendar_day * 2.0_R8) - ASSERT(earth_sun_distance == calendar_day * 3.0_R8) - - end subroutine test_orbital_data_functions - -end program test_orbital_data \ No newline at end of file diff --git a/test/unit/physics/utils/test_orbital_data_stubs.F90 b/test/unit/physics/utils/test_orbital_data_stubs.F90 deleted file mode 100644 index 7822a140a..000000000 --- a/test/unit/physics/utils/test_orbital_data_stubs.F90 +++ /dev/null @@ -1,65 +0,0 @@ -! Copyright (C) 2024 National Science Foundation-National Center for Atmospheric Research -! SPDX-License-Identifier: Apache-2.0 -!-------------------------------------------------------------------------- -! -! Stub modules for the orbital_data module tests. -! -!-------------------------------------------------------------------------- - -module shr_kind_mod - implicit none - integer, parameter :: SHR_KIND_R8 = selected_real_kind(15) -end module shr_kind_mod -module ccpp_kinds - implicit none - integer, parameter :: kind_phys = selected_real_kind(15) -end module ccpp_kinds -module cam_abortutils - implicit none - public :: check_allocate -contains - subroutine check_allocate(error_code, subroutine_name, variable_name, file, line) - integer, intent(in) :: error_code - character(len=*), intent(in) :: subroutine_name - character(len=*), intent(in) :: variable_name - character(len=*), intent(in) :: file - integer, intent(in) :: line - if (error_code /= 0) then - write(*,*) "Allocation of '", variable_name, "' failed with code ", error_code, " in ", subroutine_name, " at ", file, ":", line - stop 3 - end if - end subroutine check_allocate -end module cam_abortutils -module shr_orb_mod - use shr_kind_mod, only: R8 => SHR_KIND_R8 - implicit none - real(kind=R8), parameter :: SHR_ORB_UNDEF_REAL = -1.0_R8 - public :: shr_orb_decl, shr_orb_cosz -contains - subroutine shr_orb_decl(calendar_day, eccen, mvelpp, lambm0, obliqr, solar_declination, earth_sun_distance) - real(kind=R8), intent(in) :: calendar_day - real(kind=R8), intent(in) :: eccen - real(kind=R8), intent(in) :: mvelpp - real(kind=R8), intent(in) :: lambm0 - real(kind=R8), intent(in) :: obliqr - real(kind=R8), intent(out) :: solar_declination - real(kind=R8), intent(out) :: earth_sun_distance - solar_declination = calendar_day * 2.0 - earth_sun_distance = calendar_day * 3.0 - end subroutine shr_orb_decl - real(R8) pure function shr_orb_cosz(calendar_day, latitude, longitude, solar_declination) - real(kind=R8), intent(in) :: calendar_day - real(kind=R8), intent(in) :: latitude - real(kind=R8), intent(in) :: longitude - real(kind=R8), intent(in) :: solar_declination - shr_orb_cosz = latitude + longitude + solar_declination - end function shr_orb_cosz -end module shr_orb_mod -module cam_control_mod - use shr_kind_mod, only: R8 => SHR_KIND_R8 - implicit none - real(kind=R8) :: eccen = 2.0_R8 - real(kind=R8) :: mvelpp = 3.0_R8 - real(kind=R8) :: lambm0 = 4.0_R8 - real(kind=R8) :: obliqr = 5.0_R8 -end module cam_control_mod \ No newline at end of file diff --git a/test/valgrind.supp b/test/valgrind.supp deleted file mode 100644 index ee1ba85e8..000000000 --- a/test/valgrind.supp +++ /dev/null @@ -1,81 +0,0 @@ -############################################################## -# -# MUSICA TUV-x suppressions -# -# TODO(jiwon) We are experiencing memory leak issues in certain -# functions of TUV-x. It appears that these leaks occur only -# occasionally during initialization. We believe it’s acceptable -# to add a Valgrind suppression for now, and we will investigate -# further if it becomes a significant concern. -# -############################################################## -{ - Suppress_MUSICA_TUV-x_Leak1 - Memcheck:Leak - fun:malloc - fun:__musica_config_MOD_get_string - fun:__tuvx_radiator_aerosol_MOD_constructor - fun:__tuvx_radiator_factory_MOD_radiator_builder - fun:__tuvx_radiator_warehouse_MOD_constructor - fun:__tuvx_radiative_transfer_MOD_constructor - fun:__tuvx_core_MOD_constructor - fun:InternalCreateTuvx - ... -} -{ - Suppress_MUSICA_TUV-x_Leak2 - Memcheck:Leak - fun:malloc - fun:__musica_config_MOD_get_string - fun:__tuvx_radiator_MOD_base_constructor - fun:__tuvx_radiator_MOD_constructor - fun:__tuvx_radiator_factory_MOD_radiator_builder - fun:__tuvx_radiator_warehouse_MOD_constructor - fun:__tuvx_radiative_transfer_MOD_constructor - fun:__tuvx_core_MOD_constructor - fun:InternalCreateTuvx - ... -} -{ - Suppress_MUSICA_TUV-x_CreateRadiator - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:__musica_string_MOD_string_assign_char - fun:__tuvx_radiator_from_host_MOD_constructor_char - fun:__tuvx_radiator_from_host_MOD_constructor_string - fun:InternalCreateRadiator - ... -} -{ - Suppress_MUSICA_TUV-x_AddRadiator - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t - fun:__tuvx_radiator_warehouse_MOD_add_radiator - fun:InternalAddRadiator - ... -} -{ - Suppress_MUSICA_TUV-x_GetRadiator - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t - fun:InternalGetRadiator - ... -} -{ - Suppress_MUSICA_TUV-x_CreateTuvx-RadiatorFromHost - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:__tuvx_radiator_from_host_MOD___copy_tuvx_radiator_from_host_Radiator_from_host_t - fun:__tuvx_radiator_warehouse_MOD_add_radiator - fun:__tuvx_radiator_warehouse_MOD_add_radiators - fun:__tuvx_radiative_transfer_MOD_constructor - fun:__tuvx_core_MOD_constructor - fun:InternalCreateTuvx - ... -} \ No newline at end of file