# TONE3000 DSP test suite.
# A GTest console app exercising the chain's DSP invariants (oversampler,
# NamEngine phase interleaving, IR base-rate islands) against the real model
# and IR assets in test/files. Build and run locally:
#
#   ./script/test-dsp.sh                     # configure/build/run in one go
#   ./script/test-dsp.sh 'IrConvolutionTest.*'   # gtest filter
#
# or by hand: cmake --build build --target DspTests, then run the binary in
# build/test/DspTests_artefacts (also registered with ctest).

# The root project only enables CXX; the JUCE modules this app pulls in
# (juce_graphics via juce_audio_processors) include a C source.
enable_language(C)

juce_add_console_app(DspTests PRODUCT_NAME "DspTests")

target_sources(DspTests PRIVATE
    src/auto_offset_tests.cpp
    src/branch_tests.cpp
    src/clipboard_tests.cpp
    src/dsp_tests.cpp
    src/dual_mono_tests.cpp
    src/duplicate_tests.cpp
    src/eq_chain_rate_tests.cpp
    src/eq_post_routing_tests.cpp
    src/factory_preset_tests.cpp
    src/gate_tests.cpp
    src/host_program_tests.cpp
    src/ir_block_size_tests.cpp
    src/ir_classification_tests.cpp
    src/ir_temp_file_tests.cpp
    src/local_load_tests.cpp
    src/midi_map_tests.cpp
    src/multicore_tests.cpp
    src/outgain_tests.cpp
    src/padless_wav_tests.cpp
    src/pitch_shift_tests.cpp
    src/preset_tests.cpp
    src/processor_tests.cpp
    src/spread_tests.cpp
    src/state_cache_tests.cpp
    src/swap_fade_tests.cpp
    src/tone_refresh_tests.cpp
    src/tuner_tests.cpp
    src/worker_pool_tests.cpp
    # Compiled straight from the plugin tree so the tests exercise the real
    # processor, not a copy. GUI sources are excluded; HEADLESS=1 below
    # compiles the processor exactly like the headless plugin build.
    ../plugin/src/AutoOffset.cpp
    ../plugin/src/BlockEq.cpp
    ../plugin/src/BlockSpectrum.cpp
    ../plugin/src/LegacyParamIds.cpp
    ../plugin/src/MidiMapper.cpp
    ../plugin/src/NamEngine.cpp
    ../plugin/src/PresetFile.cpp
    ../plugin/src/PresetManager.cpp
    ../plugin/src/Processor.cpp
    ../plugin/src/ProcessorChain.cpp
    ../plugin/src/ProcessorHistory.cpp
    ../plugin/src/ProcessorModelLoader.cpp
    ../plugin/src/ProcessorPresets.cpp
    ../plugin/src/ProcessorState.cpp
    ../plugin/src/Spread.cpp
    # Processor.cpp's constructor calls StandaloneStateAutosave::install().
    # Always the portable no-op stub here, never the .mm: the real observer
    # is iOS-standalone-only and this suite never runs there (the stub is
    # also what the plugin itself compiles to everywhere but iOS).
    ../plugin/src/StandaloneStateAutosave.cpp
    ../plugin/src/PitchShift.cpp
    ../plugin/src/StereoOffset.cpp
    ../plugin/src/TunerDetector.cpp
)

target_include_directories(DspTests PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/include
    # ChainDomain.h pulls in the AudioDSPTools resampling boundary.
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/AudioDSPTools
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/AudioDSPTools/dsp/ResamplingContainer/Dependencies
    # NAM core + deps. Added explicitly (not via the NAM target) because on
    # macOS/Windows NAM is linked as a whole-archive *flag*, which doesn't
    # propagate the target's include directories.
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/NeuralAmpModelerCore
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/NeuralAmpModelerCore/Dependencies/eigen
    ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/NeuralAmpModelerCore/Dependencies/nlohmann
)

target_compile_definitions(DspTests PRIVATE
    JUCE_WEB_BROWSER=0
    JUCE_USE_WEBP=0
    JUCE_USE_CURL=0
    # Prevent windows.h min/max macros from breaking std::min/std::max in
    # AudioDSPTools and plugin code (same as plugin/CMakeLists.txt).
    $<$<PLATFORM_ID:Windows>:NOMINMAX>
    # The processor compiles in its headless configuration (no editor /
    # standalone-window code); the DSP under test is identical.
    HEADLESS=1
    # midi_map_tests pumps the dispatch loop (runDispatchLoopUntil) to
    # deliver the MidiMapper's AsyncUpdater work; the plugin itself never
    # needs modal loops.
    JUCE_MODAL_LOOPS_PERMITTED=1
    # Absolute path to the test assets, so the binary runs from anywhere.
    T3K_TEST_FILES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/files"
    # Exposes is_a2_shape, which ProcessorModelLoader.cpp uses to gate
    # drop-loaded local NAM files (same as plugin/CMakeLists.txt).
    NAM_ENABLE_A2_FAST
)

target_link_libraries(DspTests
    PRIVATE
        juce::juce_dsp
        juce::juce_audio_formats
        juce::juce_audio_processors
        # NAM must be linked whole-archive so its self-registering config
        # parsers (WaveNet/ConvNet/LSTM static initializers) survive the
        # linker (same recipe as plugin/CMakeLists.txt).
        $<$<PLATFORM_ID:Darwin>:-Wl,-force_load,$<TARGET_FILE:NAM>>
        $<$<PLATFORM_ID:Linux>:-Wl,--whole-archive>
        $<$<PLATFORM_ID:Linux>:NAM>
        $<$<PLATFORM_ID:Linux>:-Wl,--no-whole-archive>
        $<$<PLATFORM_ID:Windows>:NAM>
        $<$<PLATFORM_ID:Windows>:-WHOLEARCHIVE:$<TARGET_FILE:NAM>>
        # dsp_tests.cpp provides main() (JUCE init + InitGoogleTest).
        GTest::gtest
    PUBLIC
        juce::juce_recommended_config_flags
)

add_dependencies(DspTests NAM)

include(GoogleTest)
gtest_discover_tests(DspTests)
