# ── Unit tests ──────────────────────────────────────────────────────────────── # Pure, GPU-free, model-free tests. The similarity tests compile the GEMM backend # directly with SAE_GEMM_CPU so the suite builds and runs on a machine without a # GPU regardless of the main build's SAE_GEMM_BACKEND selection. find_package(Catch2 3 QUIET) if(NOT Catch2_FOUND) include(FetchContent) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v3.5.3 ) FetchContent_MakeAvailable(Catch2) endif() add_executable(sae_tests test_similarity.cpp test_calibration.cpp test_gallery_store.cpp test_face_utils.cpp test_track_gallery.cpp test_face_tracker.cpp test_track_registry.cpp test_face_detector_node.cpp test_scene_detector_node.cpp test_replay_fixtures.cpp test_embedding_dump.cpp test_audio_signature.cpp test_benchmark.cpp ${CMAKE_SOURCE_DIR}/src/backends/gemm_backend.cpp ${CMAKE_SOURCE_DIR}/src/gallery/gallery_store.cpp ${CMAKE_SOURCE_DIR}/src/audio_signature.cpp ${CMAKE_SOURCE_DIR}/src/gallery/embedder_stamp.cpp ) target_include_directories(sae_tests PRIVATE ${CMAKE_SOURCE_DIR}/src) # SAE_GEMM_CPU: build the CPU reference GEMM regardless of the main backend. # SAE_MODELS_DIR: config.hpp (pulled in by track_gallery.hpp) bakes model paths. # SAE_TEST_FIXTURES_DIR: the audio golden vector is read from the source tree, # not copied, so the file the plugin repo shares is the file under test. # AR-026/AR-027: exercise the same kernel CI actually runs. Without this the # suite compiles the scalar fallback while the CPU builder image links OpenBLAS, # so the tested path and the shipped path would differ. find_package(PkgConfig QUIET) if(PkgConfig_FOUND) pkg_check_modules(OPENBLAS_T QUIET openblas) endif() if(OPENBLAS_T_FOUND) target_include_directories(sae_tests PRIVATE ${OPENBLAS_T_INCLUDE_DIRS}) target_link_libraries(sae_tests PRIVATE ${OPENBLAS_T_LINK_LIBRARIES}) elseif(NOT SAE_ALLOW_SCALAR_GEMM) # Same rule as the CPU backend itself: testing the scalar loop while the # shipped CPU path is OpenBLAS means the suite is not evidence about the # kernel that runs. message(FATAL_ERROR "OpenBLAS not found, and the unit tests compile the CPU GEMM kernel " "(AR-026). Install openblas-devel, or pass -DSAE_ALLOW_SCALAR_GEMM=ON " "to test the scalar fallback deliberately.") endif() target_compile_definitions(sae_tests PRIVATE $<$:SAE_GEMM_CBLAS> SAE_GEMM_CPU SAE_MODELS_DIR="${SAE_MODELS_DIR}" SAE_TEST_FIXTURES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/fixtures") # gallery_store.cpp + gallery_calibration.hpp use nlohmann/json and HDF5 # (galleries are HDF5-native, see src/gallery/gallery_store.cpp); face_utils.hpp # and the calibration GEMM pull in OpenCV (calib3d/imgproc/core) via types.hpp. # ffmpeg_libs: audio_signature.cpp decodes the golden fixture (avformat/avcodec/ # avutil/swresample). Still GPU-free — the audio path is pure CPU. target_link_libraries(sae_tests PRIVATE Catch2::Catch2WithMain nlohmann_json::nlohmann_json # VR-015: test_benchmark.cpp includes src/benchmark.hpp, which reads KPN's # diagnostics structs. Header-only — no KPN network is constructed here, so # the cost attribution stays testable on CI's GPU-free N100. kpn ffmpeg_libs ${OpenCV_LIBS} ${HDF5_CXX_LIBRARIES}) target_include_directories(sae_tests PRIVATE ${HDF5_INCLUDE_DIRS}) include(CTest) include(Catch) catch_discover_tests(sae_tests)