From 2c2a82aefc950ed92400763ecdbe71c6c1b48d65 Mon Sep 17 00:00:00 2001 From: moto <855818+mthrok@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:39:27 -0500 Subject: [PATCH] Add C++ test --- .github/workflows/_build_linux.yml | 52 +++++++++++ src/CMakeLists.txt | 4 + src/libspdl/CMakeLists.txt | 12 +++ src/libspdl/tests/CMakeLists.txt | 124 +++++++++++++++++++++++++++ src/third_party/CMakeLists.txt | 3 + src/third_party/gtest/CMakeLists.txt | 11 +++ 6 files changed, 206 insertions(+) create mode 100644 src/libspdl/tests/CMakeLists.txt create mode 100644 src/third_party/gtest/CMakeLists.txt diff --git a/.github/workflows/_build_linux.yml b/.github/workflows/_build_linux.yml index 2cd77ae32..bca5e2bd3 100644 --- a/.github/workflows/_build_linux.yml +++ b/.github/workflows/_build_linux.yml @@ -116,6 +116,58 @@ jobs: pip install --no-dependencies $(find "${HOME}/package" -name '*.whl' -depth -maxdepth 1) python .github/scripts/check_deps.py + cpp-unit-test: + if: "${{ inputs.run-test == 'true' }}" + needs: ["build"] + name: "C++ test (ffmpeg ${{ matrix.ffmpeg-version }})" + env: + SPDL_BUILD_TESTING: "1" + strategy: + fail-fast: false + matrix: + ffmpeg-version: ["8.0"] + runs-on: ${{ inputs.machine }} + defaults: + run: + shell: bash -el {0} + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: "3.12" + channels: conda-forge + conda-remove-defaults: "true" + + - name: Setup + run: | + set -ex + + # Install build dependencies + conda install -q cmake ninja gtest fmt glog "ffmpeg==${{ matrix.ffmpeg-version }}" pkg-config + + # For some reason, the dynamic libraries are not found. + echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${CONDA_PREFIX}/lib" >> $GITHUB_ENV + + - name: Build and run C++ tests + run: | + set -ex + + # Configure with testing enabled + cmake -S src/libspdl -B build \ + -GNinja \ + -DCMAKE_BUILD_TYPE=Release \ + -DSPDL_BUILD_TESTING=ON \ + -DCMAKE_PREFIX_PATH="${CONDA_PREFIX}" + + # Build + cmake --build build + + # Run tests + ctest --test-dir build --output-on-failure + unit-test: if: "${{ inputs.run-test == 'true' }}" needs: ["build"] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfdc735ca..cf8e3773c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ option(SPDL_LINK_STATIC_NVJPEG "Link nvJPEG and NPPI statically." OFF) option(SPDL_DEBUG_REFCOUNT "Enable debug print for reference counting of AVFrame objects." OFF) option(SPDL_IS_GIL_ENABLED "Whether the target Python has the GIL enabled" ON) option(SPDL_BUILD_PYTHON_BINDING "Build Python binding" ON) +option(SPDL_BUILD_TESTING "Build C++ test" ON) if (SPDL_USE_NVCODEC OR SPDL_USE_NVJPEG) if (NOT SPDL_USE_CUDA) @@ -41,6 +42,9 @@ find_package(fmt REQUIRED NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY N find_package(glog REQUIRED NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PACKAGE_REGISTRY) find_package(libdeflate REQUIRED NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PACKAGE_REGISTRY) find_package(ZLIB REQUIRED NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PACKAGE_REGISTRY) +if(SPDL_BUILD_TESTING) + find_package(GTest REQUIRED NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PACKAGE_REGISTRY) +endif() add_subdirectory(third_party/ffmpeg/multi) if (SPDL_USE_TRACING) diff --git a/src/libspdl/CMakeLists.txt b/src/libspdl/CMakeLists.txt index aa4ddd0ac..f60ad2824 100644 --- a/src/libspdl/CMakeLists.txt +++ b/src/libspdl/CMakeLists.txt @@ -1,3 +1,9 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + set(SPDL_COMMON_DEFS) if (SPDL_USE_TRACING) list(APPEND SPDL_COMMON_DEFS SPDL_USE_TRACING) @@ -25,3 +31,9 @@ add_subdirectory(core) if (SPDL_USE_CUDA) add_subdirectory(cuda) endif() + +# Enable testing +if (SPDL_BUILD_TESTING) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/src/libspdl/tests/CMakeLists.txt b/src/libspdl/tests/CMakeLists.txt new file mode 100644 index 000000000..0d3baab5b --- /dev/null +++ b/src/libspdl/tests/CMakeLists.txt @@ -0,0 +1,124 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +message(STATUS "########################################") +message(STATUS "# Configuring libspdl tests") +message(STATUS "########################################") + +# Find GTest package + + +# Generate test data directory +set(TEST_DATA_DIR "${CMAKE_CURRENT_BINARY_DIR}/test_data") +file(MAKE_DIRECTORY "${TEST_DATA_DIR}") + +# Helper function to generate test data files using FFmpeg +function(generate_test_data) + find_program(FFMPEG_EXECUTABLE ffmpeg REQUIRED) + + # Generate test audio (AAC, 5 seconds, 44.1kHz, stereo) + execute_process( + COMMAND ${FFMPEG_EXECUTABLE} + -f lavfi + -i sine=frequency=440:duration=5:sample_rate=44100 + -ac 2 + -c:a aac + -b:a 128k + ${TEST_DATA_DIR}/test_audio.aac + -y + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE AUDIO_RESULT + ) + + # Generate test image (JPEG, 320x240) + execute_process( + COMMAND ${FFMPEG_EXECUTABLE} + -f lavfi + -i testsrc=duration=1:size=320x240:rate=1 + -frames:v 1 + ${TEST_DATA_DIR}/test_image.jpg + -y + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE IMAGE_RESULT + ) + + # Generate test video (H.264/MP4, 2 seconds, 320x240, 30fps) + execute_process( + COMMAND ${FFMPEG_EXECUTABLE} + -f lavfi + -i testsrc=duration=2:size=320x240:rate=30 + -c:v libx264 + -pix_fmt yuv420p + ${TEST_DATA_DIR}/test_video.mp4 + -y + OUTPUT_QUIET + ERROR_QUIET + RESULT_VARIABLE VIDEO_RESULT + ) + + if(AUDIO_RESULT EQUAL 0 AND IMAGE_RESULT EQUAL 0 AND VIDEO_RESULT EQUAL 0) + message(STATUS "Test data generated successfully in ${TEST_DATA_DIR}") + else() + message(WARNING "Failed to generate some test data files. Tests may fail.") + endif() +endfunction() + +# Generate test data at configure time +generate_test_data() + +# Create smoke test executable for each FFmpeg version +function(add_smoke_test ffmpeg_version) + set(test_name "smoke_test_ffmpeg${ffmpeg_version}") + set(lib_name "spdl_ffmpeg${ffmpeg_version}") + + message(STATUS "Building test: ${test_name}") + + add_executable(${test_name} smoke_test.cpp) + + target_compile_definitions(${test_name} PRIVATE + "TEST_DATA_DIR=\"${TEST_DATA_DIR}\"" + ) + + target_link_libraries(${test_name} + PRIVATE + ${lib_name} + fmt::fmt + glog::glog + GTest::gtest + GTest::gtest_main + ) + + target_include_directories(${test_name} + PRIVATE + "${PROJECT_SOURCE_DIR}" + ) + + # Register test with CTest + add_test( + NAME ${test_name} + COMMAND ${test_name} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + + # Set test environment + set_tests_properties(${test_name} PROPERTIES + ENVIRONMENT "TEST_DATA_DIR=${TEST_DATA_DIR}" + ) +endfunction() + +# Build tests for configured FFmpeg versions +set(ffmpeg_versions 8 7 6 5 4) +if (SPDL_USE_FFMPEG_VERSION IN_LIST ffmpeg_versions) + add_smoke_test("${SPDL_USE_FFMPEG_VERSION}") +else() + add_smoke_test(8) + add_smoke_test(7) + add_smoke_test(6) + add_smoke_test(5) + add_smoke_test(4) +endif() diff --git a/src/third_party/CMakeLists.txt b/src/third_party/CMakeLists.txt index 4ce8b0ac0..681a8be5b 100644 --- a/src/third_party/CMakeLists.txt +++ b/src/third_party/CMakeLists.txt @@ -24,3 +24,6 @@ add_subdirectory(fmt) add_subdirectory(glog) add_subdirectory(zlib) add_subdirectory(libdeflate) +if(SPDL_BUILD_TESTING) + add_subdirectory(gtest) +endif() diff --git a/src/third_party/gtest/CMakeLists.txt b/src/third_party/gtest/CMakeLists.txt new file mode 100644 index 000000000..58c9012c2 --- /dev/null +++ b/src/third_party/gtest/CMakeLists.txt @@ -0,0 +1,11 @@ +message(STATUS "########################################") +message(STATUS "# Configuring GoogleTest") +message(STATUS "########################################") + +FetchContent_Declare( + gtest + URL https://github.com/google/googletest/releases/download/v1.17.0/googletest-1.17.0.tar.gz + URL_HASH SHA256=65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c + DOWNLOAD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../cache" + ) +FetchContent_MakeAvailable(gtest)