# ============================================================================ # # Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. # # All rights reserved. # # # # This source code and the accompanying materials are made available under # # the terms of the Apache License 2.0 which accompanies this distribution. # # ============================================================================ # SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-ctad-maybe-unsupported") # clear any flags for static linking SET(CMAKE_EXE_LINKER_FLAGS "") SET(CMAKE_SHARED_LINKER_FLAGS "") set(CUDAQ_RUNTIME_TEST_SOURCES # Integration tests integration/adjoint_tester.cpp integration/builder_tester.cpp integration/ccnot_tester.cpp integration/deuteron_variational_tester.cpp integration/draw_tester.cpp integration/ghz_nisq_tester.cpp integration/gradient_tester.cpp integration/grover_test.cpp integration/nlopt_tester.cpp integration/qpe_ftqc.cpp integration/qpe_nisq.cpp integration/qubit_allocation.cpp integration/vqe_tester.cpp integration/bug67_vqe_then_sample.cpp integration/bug77_vqe_with_shots.cpp integration/bug116_cusv_measure_bug.cpp integration/async_tester.cpp integration/negative_controls_tester.cpp integration/observe_result_tester.cpp integration/noise_tester.cpp integration/get_state_tester.cpp integration/measure_reset_tester.cpp qir/NVQIRTester.cpp qis/QubitQISTester.cpp integration/kernels_tester.cpp common/MeasureCountsTester.cpp common/NoiseModelTester.cpp integration/tracer_tester.cpp integration/gate_library_tester.cpp ) # Make it so we can get function symbols set (CMAKE_ENABLE_EXPORTS TRUE) ## This Macro allows us to create a test_runtime executable for ## the sources in CUDAQ_RUNTIME_TEST_SOURCE for a specific backend simulator macro (create_tests_with_backend NVQIR_BACKEND EXTRA_BACKEND_TESTER) set(TEST_EXE_NAME "test_runtime_${NVQIR_BACKEND}") string(REPLACE "-" "_" NVQIR_BACKEND_OUT ${NVQIR_BACKEND}) add_executable(${TEST_EXE_NAME} main.cpp ${CUDAQ_RUNTIME_TEST_SOURCES} ${EXTRA_BACKEND_TESTER}) target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DNVQIR_BACKEND_NAME=${NVQIR_BACKEND_OUT}) target_compile_definitions(${TEST_EXE_NAME} PRIVATE __MATH_LONG_DOUBLE_CONSTANTS) target_include_directories(${TEST_EXE_NAME} PRIVATE .) # On GCC, the default is --as-needed for linking, and therefore the # nvqir-simulation plugin may not get picked up. This works as is on clang # But here we add it purposefully to avoid that bug. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(${TEST_EXE_NAME} PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(${TEST_EXE_NAME} PUBLIC nvqir-${NVQIR_BACKEND} nvqir cudaq fmt::fmt-header-only cudaq-platform-default cudaq-builder gtest_main) set(TEST_LABELS "") if (${NVQIR_BACKEND} STREQUAL "qpp") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_SIMULATION_SCALAR_FP64) endif() if (${NVQIR_BACKEND} STREQUAL "dm") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_DM -DCUDAQ_SIMULATION_SCALAR_FP64) endif() if (${NVQIR_BACKEND} STREQUAL "stim") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_STIM -DCUDAQ_SIMULATION_SCALAR_FP64) endif() if (${NVQIR_BACKEND} STREQUAL "tensornet") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_TENSORNET -DCUDAQ_SIMULATION_SCALAR_FP64) set(TEST_LABELS "gpu_required") endif() if (${NVQIR_BACKEND} STREQUAL "tensornet-mps") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_TENSORNET -DCUDAQ_BACKEND_TENSORNET_MPS -DCUDAQ_SIMULATION_SCALAR_FP64) set(TEST_LABELS "gpu_required") endif() if (${NVQIR_BACKEND} STREQUAL "tensornet-fp32") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_TENSORNET -DCUDAQ_SIMULATION_SCALAR_FP32) set(TEST_LABELS "gpu_required") endif() if (${NVQIR_BACKEND} STREQUAL "tensornet-mps-fp32") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_TENSORNET -DCUDAQ_BACKEND_TENSORNET_MPS -DCUDAQ_SIMULATION_SCALAR_FP32) set(TEST_LABELS "gpu_required") endif() if (${NVQIR_BACKEND} STREQUAL "custatevec-fp32") target_compile_definitions(${TEST_EXE_NAME} PRIVATE -DCUDAQ_BACKEND_CUSTATEVEC_FP32 -DCUDAQ_SIMULATION_SCALAR_FP32) target_link_libraries(${TEST_EXE_NAME} PRIVATE ${CUDA_LIBRARIES} ${CUDA_CUDART_LIBRARY}) set(TEST_LABELS "gpu_required") endif() if ("${TEST_LABELS}" STREQUAL "") gtest_discover_tests(${TEST_EXE_NAME}) else() gtest_discover_tests(${TEST_EXE_NAME} PROPERTIES LABELS "${TEST_LABELS}") endif() endmacro() # We will always have the QPP backend, create a tester for it create_tests_with_backend(qpp backends/QPPTester.cpp) create_tests_with_backend(dm backends/QPPDMTester.cpp) create_tests_with_backend(stim "") if (CUSTATEVEC_ROOT AND CUDA_FOUND) find_program(NVIDIA_SMI "nvidia-smi") if(${NVIDIA_SMI} STREQUAL "NVIDIA_SMI-NOTFOUND") # libcustatevec.so has linkage to libnvdia-ml.so.1, which is part of NVIDIA driver. # On a build system without NVIDIA GPUs, this lib cannot be resolved; # hence, linking these test executables will fail. # On these CPU-only build systems, we directly link the nvidia-ml-dev library, which provides # stub symbols for the actual driver library, to these test executables. # Running these tests will ultimately requires a system with GPUs, i.e., the proper nvidia-ml lib # will be loaded by the runtime linker/loader. find_package(CUDAToolkit REQUIRED) # make sure CUDA_TOOLKIT_ROOT_DIR is set if(NOT DEFINED CUDA_TOOLKIT_ROOT_DIR) set(CUDA_TOOLKIT_ROOT_DIR ${CUDAToolkit_BIN_DIR}/..) endif() if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") set(NVIDIA_ML_PATH ${CUDA_TOOLKIT_ROOT_DIR}/targets/x86_64-linux/lib/stubs) elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") set(NVIDIA_ML_PATH ${CUDA_TOOLKIT_ROOT_DIR}/targets/sbsa-linux/lib/stubs) else() message(FATAL_ERROR "Neither x86_64 nor aarch64 was detected." ) endif() # Find nvidia-ml manually find_library(NVIDIA_ML NAMES nvidia-ml PATHS ${NVIDIA_ML_PATH}) message(STATUS "NVIDIA ML lib: ${NVIDIA_ML}") # Inject the file during build and remove it after build (install) file(CREATE_LINK ${NVIDIA_ML} ${CMAKE_CURRENT_BINARY_DIR}/libnvidia-ml.so.1) link_directories(${CMAKE_CURRENT_BINARY_DIR}) install(CODE "file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/libnvidia-ml.so.1)") endif() create_tests_with_backend(custatevec-fp32 "") # Given that the fp32 and fp64 difference is largely inherited # from a dependency, we omit fp64 tests here and rely on the # dependency to to validate that functionality. # create_tests_with_backend(custatevec-fp64 "") add_executable(test_mqpu main.cpp mqpu/mqpu_tester.cpp) # Need to force the link to nvqir-qpp here if gcc. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_mqpu PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_mqpu PRIVATE cudaq cudaq-builder cudaq-platform-mqpu nvqir-custatevec-fp64 gtest_main) gtest_discover_tests(test_mqpu PROPERTIES LABELS "gpu_required") # Test CUDAQ_OBSERVE_FROM_SAMPLING=ON mode. # (term-by-term expectation value calculation by applying change-of-basis gates then reverting them) add_executable(test_custatevec_observe_from_sampling integration/builder_tester.cpp integration/deuteron_variational_tester.cpp integration/gradient_tester.cpp integration/nlopt_tester.cpp ) target_include_directories(test_custatevec_observe_from_sampling PRIVATE .) target_compile_definitions(test_custatevec_observe_from_sampling PRIVATE -DNVQIR_BACKEND_NAME=custatevec_fp32) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_custatevec_observe_from_sampling PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_custatevec_observe_from_sampling PRIVATE cudaq cudaq-builder cudaq-platform-default nvqir-custatevec-fp32 gtest_main) # Run this test with "CUDAQ_OBSERVE_FROM_SAMPLING=1" gtest_discover_tests(test_custatevec_observe_from_sampling TEST_SUFFIX _DirectObserve PROPERTIES ENVIRONMENT "CUDAQ_OBSERVE_FROM_SAMPLING=1" PROPERTIES LABELS "gpu_required") if (MPI_CXX_FOUND) # Count the number of GPUs find_program(NVIDIA_SMI "nvidia-smi") if(NVIDIA_SMI) execute_process(COMMAND bash -c "nvidia-smi --list-gpus | wc -l" OUTPUT_VARIABLE NGPUS) # Only build this test if we have more than 1 GPU if (${NGPUS} GREATER_EQUAL 2) add_executable(test_mpi main.cpp mqpu/mpi_mqpu_tester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_mpi PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_mpi PRIVATE cudaq cudaq-platform-mqpu nvqir-custatevec-fp32 gtest_main) configure_file("mqpu/run_mpi.sh.in" "${CMAKE_BINARY_DIR}/unittests/run_mpi.sh" @ONLY) add_test(NAME MPITest COMMAND ${MPIEXEC} --allow-run-as-root -np 2 bash ${CMAKE_BINARY_DIR}/unittests/run_mpi.sh) set_tests_properties(MPITest PROPERTIES LABELS "gpu_required;mgpus_required") endif() endif() add_executable(test_gpu_get_state main.cpp gpu/get_state_tester.cu) # Need to force the link to nvqir-qpp here if gcc. if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_gpu_get_state PRIVATE -Wl,--no-as-needed) endif() target_compile_options(test_gpu_get_state PRIVATE -Wno-suggest-override -Wno-attributes) target_include_directories(test_gpu_get_state PRIVATE .) target_link_libraries(test_gpu_get_state PRIVATE cudaq cudaq-builder cudaq-platform-mqpu nvqir-custatevec-fp64 gtest_main) gtest_discover_tests(test_gpu_get_state PROPERTIES LABELS "gpu_required") endif() endif() if(TARGET nvqir-tensornet) message(STATUS "Building cutensornet backend tests.") create_tests_with_backend(tensornet "") create_tests_with_backend(tensornet-mps "") create_tests_with_backend(tensornet-fp32 "") create_tests_with_backend(tensornet-mps-fp32 "") if (MPI_CXX_FOUND) # Count the number of GPUs find_program(NVIDIA_SMI "nvidia-smi") if(NVIDIA_SMI) execute_process(COMMAND bash -c "nvidia-smi --list-gpus | wc -l" OUTPUT_VARIABLE NGPUS) # Only build this test if we have more than 1 GPUs if (${NGPUS} GREATER_EQUAL 2) message(STATUS "Building cutensornet MPI tests.") add_executable(test_tensornet_mpi mpi/tensornet_mpi_tester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_tensornet_mpi PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_tensornet_mpi PRIVATE cudaq fmt::fmt-header-only cudaq-platform-default nvqir-tensornet gtest) add_test(NAME TensornetMPITest COMMAND ${MPIEXEC} --allow-run-as-root -np 2 ${CMAKE_BINARY_DIR}/unittests/test_tensornet_mpi) set_tests_properties(TensornetMPITest PROPERTIES LABELS "gpu_required;mgpus_required") endif() # NGPUS endif() # NVIDIA_SMI endif() # MPI_CXX_FOUND # Test CUDAQ_TENSORNET_OBSERVE_CONTRACT_PATH_REUSE=ON mode (on a few test cases that have cudaq::observe) add_executable(test_tensornet_observe_path_reuse integration/builder_tester.cpp integration/deuteron_variational_tester.cpp integration/observe_result_tester.cpp integration/noise_tester.cpp # This test contains noisy observe test cases. ) target_include_directories(test_tensornet_observe_path_reuse PRIVATE .) target_compile_definitions(test_tensornet_observe_path_reuse PRIVATE -DNVQIR_BACKEND_NAME=tensornet) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_tensornet_observe_path_reuse PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_tensornet_observe_path_reuse PRIVATE cudaq cudaq-builder cudaq-platform-default nvqir-tensornet gtest_main) # Run this test with "CUDAQ_TENSORNET_OBSERVE_CONTRACT_PATH_REUSE=TRUE" gtest_discover_tests(test_tensornet_observe_path_reuse TEST_SUFFIX _PathReuse PROPERTIES ENVIRONMENT "CUDAQ_TENSORNET_OBSERVE_CONTRACT_PATH_REUSE=ON" PROPERTIES LABELS "gpu_required") endif() # Create an executable for SpinOp UnitTests set(CUDAQ_SPIN_TEST_SOURCES spin_op/SpinOpTester.cpp operators/utils.cpp ) add_executable(test_spin main.cpp ${CUDAQ_SPIN_TEST_SOURCES}) target_link_libraries(test_spin PRIVATE cudaq cudaq-operator gtest_main) target_include_directories(test_spin PRIVATE operators) gtest_discover_tests(test_spin) # Create an executable for operators UnitTests set(CUDAQ_OPERATOR_TEST_SOURCES operators/utils.cpp operators/scalar_op.cpp operators/matrix_op.cpp operators/spin_op.cpp operators/boson_op.cpp operators/fermion_op.cpp operators/conversions.cpp operators/product_op.cpp operators/sum_op.cpp operators/rydberg_hamiltonian.cpp operators/manipulation.cpp ) add_executable(test_operators main.cpp ${CUDAQ_OPERATOR_TEST_SOURCES}) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_operators PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_operators PRIVATE cudaq-operator cudaq gtest_main) gtest_discover_tests(test_operators) if (CUDA_FOUND) find_package(CUDAToolkit REQUIRED) find_library(CUTENSOR_LIB NAMES cutensor libcutensor.so.2 HINTS ${CUTENSOR_ROOT}/lib64 ${CUTENSOR_ROOT}/lib ${CUTENSOR_ROOT}/lib64/${CUDAToolkit_VERSION_MAJOR} ${CUTENSOR_ROOT}/lib/${CUDAToolkit_VERSION_MAJOR} ) find_library(CUTENSORNET_LIB NAMES cutensornet libcutensornet.so.2 HINTS ${CUTENSORNET_ROOT}/lib64 ${CUTENSORNET_ROOT}/lib ${CUTENSORNET_ROOT}/lib64/${CUDAToolkit_VERSION_MAJOR} ${CUTENSORNET_ROOT}/lib/${CUDAToolkit_VERSION_MAJOR} ${CUDENSITYMAT_ROOT}/lib/ ) # Create an executable for dynamics UnitTests set(CUDAQ_DYNAMICS_TEST_SOURCES dynamics/test_RungeKuttaIntegrator.cpp dynamics/test_CuDensityMatState.cpp dynamics/test_CuDensityMatTimeStepper.cpp dynamics/test_CuDensityMatExpectation.cpp dynamics/test_EvolveSingle.cpp dynamics/test_EvolveApi.cpp dynamics/test_EvolveBatchedImpl.cpp dynamics/test_BatchedEvolveApi.cpp dynamics/test_BatchingDetection.cpp ) add_executable(test_dynamics main.cpp ${CUDAQ_DYNAMICS_TEST_SOURCES}) target_compile_definitions(test_dynamics PRIVATE -DCUDAQ_ANALOG_TARGET) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_dynamics PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_dynamics PRIVATE cudaq-operator cudaq nvqir-dynamics ${CUDENSITYMAT_ROOT}/lib/libcudensitymat.so.0 CUDA::cudart CUDA::cublas ${CUTENSOR_LIB} CUDA::cusparse ${CUTENSORNET_LIB} gtest_main fmt::fmt-header-only) target_include_directories(test_dynamics PRIVATE ${CMAKE_SOURCE_DIR}/runtime/nvqir/cudensitymat) gtest_discover_tests(test_dynamics PROPERTIES LABELS "gpu_required") # Multi-QPU evolve_async test add_executable(test_evolve_async mqpu/dynamics_async_tester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_evolve_async PRIVATE -Wl,--no-as-needed) endif() target_compile_definitions(test_evolve_async PRIVATE -DCUDAQ_ANALOG_TARGET) target_link_libraries(test_evolve_async PRIVATE cudaq-operator cudaq cudaq-platform-mqpu nvqir-dynamics ${CUDENSITYMAT_ROOT}/lib/libcudensitymat.so.0 CUDA::cudart CUDA::cublas ${CUTENSOR_LIB} CUDA::cusparse ${CUTENSORNET_LIB} gtest_main fmt::fmt-header-only) # Count the number of GPUs find_program(NVIDIA_SMI "nvidia-smi") if(NVIDIA_SMI) execute_process(COMMAND bash -c "nvidia-smi --list-gpus | wc -l" OUTPUT_VARIABLE NGPUS) # Only add this test if we have more than 1 GPU if (${NGPUS} GREATER_EQUAL 2) gtest_discover_tests(test_evolve_async PROPERTIES LABELS "gpu_required;mgpus_required") endif() endif() endif() add_subdirectory(plugin) # build the test qudit execution manager add_subdirectory(qudit) add_executable(test_qudit main.cpp qudit/SimpleQuditTester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_qudit PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_qudit PRIVATE cudaq cudaq-platform-default cudaq-em-qudit gtest_main) gtest_discover_tests(test_qudit) # build the test photonics execution manager add_executable(test_photonics main.cpp photonics/PhotonicsTester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_photonics PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_photonics PRIVATE cudaq cudaq-platform-default cudaq-em-photonics nvqir-qpp gtest_main) gtest_discover_tests(test_photonics) add_executable(test_utils main.cpp utils/UtilsTester.cpp utils/Matrix.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_utils PRIVATE -Wl,--no-as-needed) endif() target_link_libraries(test_utils PRIVATE cudaq cudaq-platform-default cudaq-em-photonics nvqir nvqir-qpp fmt::fmt-header-only gtest_main) gtest_discover_tests(test_utils) # Create an executable for MPI UnitTests # (only if MPI was found, i.e., the builtin plugin is available) if (MPI_CXX_FOUND) set(CUDAQ_MPI_TEST_SOURCES mpi/mpi_tester.cpp ) add_executable(test_mpi_plugin ${CUDAQ_MPI_TEST_SOURCES}) set(NUM_PROCS 4) target_compile_definitions(test_mpi_plugin PRIVATE -DNUM_PROCS=${NUM_PROCS}) target_link_libraries(test_mpi_plugin PRIVATE cudaq cudaq-platform-default nvqir-qpp gtest ) target_link_options(test_mpi_plugin PRIVATE -Wl,--no-as-needed) # Check if `--allow-run-as-root` is supported (OpenMPI) # Note: MPICH doesn't need `--allow-run-as-root`. execute_process(COMMAND ${MPIEXEC} --allow-run-as-root -np ${NUM_PROCS} hostname ERROR_VARIABLE CHECK_ALLOW_RUN_AS_ROOT_RESULTS ERROR_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET) if ("${CHECK_ALLOW_RUN_AS_ROOT_RESULTS}" STREQUAL "") set(MPI_EXEC_CMD_ARGS "--allow-run-as-root") endif() add_test(NAME MPIApiTest COMMAND ${MPIEXEC} ${MPI_EXEC_CMD_ARGS} -np ${NUM_PROCS} ${CMAKE_BINARY_DIR}/unittests/test_mpi_plugin) endif() add_subdirectory(backends) add_subdirectory(Optimizer) add_subdirectory(output_record) add_subdirectory(target_config) if (CUDAQ_ENABLE_PYTHON) if (NOT Python_FOUND) message(FATAL_ERROR "find_package(Python) not run?") endif() execute_process(COMMAND ${Python_EXECUTABLE} -c "import openfermionpyscf" OUTPUT_VARIABLE PYSCF_output ERROR_VARIABLE PYSCF_error RESULT_VARIABLE PYSCF_result) if(NOT ${PYSCF_result} EQUAL 0) message(STATUS "OpenFermion PySCF not available for chemistry tests.") return() endif() message(STATUS "OpenFermion PySCF found, enabling chemistry tests.") add_executable(test_domains main.cpp domains/ChemistryTester.cpp) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) target_link_options(test_domains PRIVATE -Wl,--no-as-needed) endif() target_compile_definitions(test_domains PRIVATE -DNVQIR_BACKEND_NAME=qpp -DCUDAQ_SIMULATION_SCALAR_FP64) target_include_directories(test_domains PRIVATE .) set_property(TARGET test_domains PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/python") target_link_libraries(test_domains PRIVATE cudaq cudaq-platform-default nvqir nvqir-qpp cudaq-operator cudaq-chemistry cudaq-pyscf gtest_main) gtest_discover_tests(test_domains TEST_SUFFIX _Sampling PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/python") endif()