macro(dapper_init) set(MIOPEN_TEST_SINGLE_GTEST 1) set(MIOPEN_TEST_DISCRETE 1) # TRJS message(STATUS "------------------------------------ CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}") message(STATUS "------------------------------------ CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}") message(STATUS "------------------------------------ CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}") set(MIOPEN_DAPPER_SRC_DIR "${CMAKE_BINARY_DIR}/../script/dependency-parser") set(MIOPEN_DAPPER_OUT_DIR "${CMAKE_BINARY_DIR}") set(SHARDS_FILE ${MIOPEN_DAPPER_OUT_DIR}/miopen_gtest_shards.txt) set(BUILD_NINJA "${MIOPEN_DAPPER_OUT_DIR}/build.ninja") set(SHAS_JSON "${MIOPEN_DAPPER_OUT_DIR}/miopen_dapper_shas.txt") set(MAPPING_JSON "${MIOPEN_DAPPER_OUT_DIR}/miopen_dapper_mapping.json") set(FIXTURES_JSON "${MIOPEN_DAPPER_OUT_DIR}/miopen_dapper_fixtures.json") set(TESTS_JSON "${MIOPEN_DAPPER_OUT_DIR}/miopen_dapper_tests.json") set(PY_MAIN "/${MIOPEN_DAPPER_SRC_DIR}/main.py") set(PY_FIXTURES "/${MIOPEN_DAPPER_SRC_DIR}/src/extract_gtest_fixtures.py") set(MIOPEN_GTEST_RUNNER "/${MIOPEN_DAPPER_SRC_DIR}/src/miopen_gtest_runner.py") set(MIOPEN_DAPPER_DIFF ${MIOPEN_DAPPER_SRC_DIR}/src/dapper_diff.py) # shas: git merge-base and HEAD SHAs; needed by both parse and select. add_custom_target(dapper_shas COMMENT "Generating ${SHAS_JSON}" COMMAND ${Python_EXECUTABLE} ${PY_MAIN} shas WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} VERBATIM ) # fixtures: test-name -> gtest fixture mapping; reads compile_commands.json (always present). add_custom_target(dapper_fixtures COMMENT "Generating ${FIXTURES_JSON}" COMMAND ${Python_EXECUTABLE} ${PY_FIXTURES} WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} VERBATIM ) add_dependencies(dapper_fixtures dapper_shas) # mapping: file -> test-executable mapping; needs tests built so build.ninja is final. add_custom_target(dapper_mapping COMMENT "Generating ${MAPPING_JSON}" COMMAND ${Python_EXECUTABLE} ${PY_MAIN} parse ${BUILD_NINJA} WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} VERBATIM ) add_dependencies(dapper_mapping dapper_shas miopen-tests) # Drive all three pre-test files into the build graph before ctest runs. # TESTS_JSON is intentionally excluded — it is generated by the dapper_tests_generate # ctest test after the shard tests have written their XML output. add_custom_target(dapper_prebuild) add_dependencies(dapper_prebuild dapper_fixtures dapper_mapping) add_dependencies(miopen-check dapper_prebuild) add_custom_target( diff_check COMMENT "Running filtered gtests..." COMMAND ${Python_EXECUTABLE} "${MIOPEN_GTEST_RUNNER}" "${MIOPEN_DAPPER_OUT_DIR}/bin/miopen_gtest" "${TESTS_JSON}" WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} DEPENDS miopen_gtest miopen-tests VERBATIM ) endmacro() macro(dapper_dev_filters) # TODO Fix Dapper default minimal run if no work to do. It's in calc_union_filter but in mici this is ran by dapper_diff which does not run until after miopen-check message(STATUS "================== DAPPER DEVELOPMENT FILTERS") set(MIOPEN_DAPPER_DEV_FILTER_SHORT "*GPU_TestMhaFind20_FP32*:*GPU_TestMhaFind20_FP16*") set(MIOPEN_DAPPER_DEV_FILTER_LONGER "Smoke/GPU_BNCKFWDTrainLarge2D_FP16*:Smoke/GPU_BNOCLFWDTrainLarge2D_FP16*:Smoke/GPU_BNOCLFWDTrainLarge3D_FP16*:Smoke/GPU_BNCKFWDTrainLarge2D_BFP16*:Smoke/GPU_BNOCLFWDTrainLarge2D_BFP16*:Smoke/GPU_BNOCLFWDTrainLarge3D_BFP16*:Smoke/GPU_UnitTestConvSolverImplicitGemmFwdXdlops_FP16*:Smoke/GPU_UnitTestConvSolverImplicitGemmFwdXdlops_BFP16*-Smoke/GPU_BNOCLFWDTrainLarge2D_BFP16*:Smoke/GPU_BNOCLInferLarge2D_BFP16*:*/GPU_MIOpenDriver*:*GPU_TestMhaFind20_FP32*:*GPU_TestMhaFind20_FP16*:Smoke/GPU_BNOCLInferLarge2D_BFP16*:Smoke/GPU_BNOCLFWDTrainLarge2D_BFP16*") set(MIOPEN_DAPPER_DEV_FILTER_LONG "*Fusion*:*/GPU_BNBWD*_*:*/GPU_BNOCLBWD*_*:*/GPU_BNFWD*_*:*/GPU_BNOCLFWD*_*:*/GPU_BNInfer*_*:*/GPU_BNActivInfer_*:*/GPU_BNOCLInfer*_*:*/GPU_bn_infer*_*:CPU_*:*/CPU_*:*/GPU_Cat_*:*/GPU_ConvBiasActiv*:*/GPU_Conv*:*/GPU_conv*:*/GPU_UnitTestConv*:*/GPU_GetitemBwd*:*/GPU_GLU_*:*/GPU_GroupConv*:*/GPU_GroupNorm_*:*/GPU_GRUExtra_*:*/GPU_TestActivation*:*/GPU_HipBLASLtGEMMTest*:*/GPU_KernelTuningNetTestConv*:*/GPU_Kthvalue_*:*/GPU_LayerNormTest*:*/GPU_LayoutTransposeTest_*:*/GPU_Lrn*:*/GPU_lstm_extra*:*/GPU_MultiMarginLoss_*:*/GPU_ConvNonpack*:*/GPU_PerfConfig_HipImplicitGemm*:*/GPU_AsymPooling2d_*:*/GPU_WidePooling2d_*:*/GPU_PReLU_*:*/GPU_Reduce*:*/GPU_reduce_custom_*:*/GPU_regression_issue_*:*/GPU_RNNExtra_*:*/GPU_RoPE*:*/GPU_SoftMarginLoss*:*/GPU_T5LayerNormTest_*:*/GPU_Op4dTensorGenericTest_*:*/GPU_TernaryTensorOps_*:*/GPU_unaryTensorOps_*:*/GPU_Transformers*:*/GPU_TunaNetTest_*:*/") if(DEFINED MIOPEN_DEBUG_DAPPER_FILTER) if(MIOPEN_DEBUG_DAPPER_FILTER MATCHES "-") string(REGEX REPLACE "-.*$" "" MIOPEN_DEBUG_DAPPER_FILTER "${MIOPEN_DEBUG_DAPPER_FILTER}") message(WARNING "MIOPEN_DEBUG_DAPPER_FILTER is a positive-only filter; negative portion stripped. Using: '${MIOPEN_DEBUG_DAPPER_FILTER}'") endif() endif() if(DEFINED MIOPEN_DEBUG_DEV_FILTER) set(MIOPEN_DEBUG_DEV_FILTER_IN "${MIOPEN_DEBUG_DEV_FILTER}") string(TOUPPER "${MIOPEN_DEBUG_DEV_FILTER_IN}" MIOPEN_DEBUG_DEV_FILTER) message(STATUS "User-specified development category='${MIOPEN_DEBUG_DEV_FILTER}'") if(MIOPEN_DEBUG_DEV_FILTER STREQUAL "SHORT") set(MIOPEN_DEV_FILTER "${MIOPEN_DEBUG_DAPPER_FILTER}:${MIOPEN_DAPPER_DEV_FILTER_SHORT}") elseif(MIOPEN_DEBUG_DEV_FILTER STREQUAL "LONGER") set(MIOPEN_DEV_FILTER "${MIOPEN_DEBUG_DAPPER_FILTER}:${MIOPEN_DAPPER_DEV_FILTER_LONGER}") elseif(MIOPEN_DEBUG_DEV_FILTER STREQUAL "LONG") set(MIOPEN_DEV_FILTER "${MIOPEN_DEBUG_DAPPER_FILTER}:${MIOPEN_DAPPER_DEV_FILTER_LONG}") else() message(FATAL_ERROR "Aborting. Unknown MIOPEN_DEBUG_DEV_FILTER: '{MIOPEN_DEBUG_DEV_FILTER}'") endif() set(MIOPEN_CATEGORY "${MIOPEN_DEBUG_DEV_FILTER}") message(STATUS "Applying Category '${MIOPEN_DEBUG_DEV_FILTER}' with user filters '${MIOPEN_DEBUG_DAPPER_FILTER}'") set(MIOPEN_GTEST_FILTER "${MIOPEN_DEV_FILTER}") message(STATUS "gtest_filter=MIOPEN_DEV_FILTER: ${MIOPEN_DEV_FILTER}") elseif(DEFINED MIOPEN_DEBUG_DAPPER_FILTER) message(STATUS "Applying user filters '${MIOPEN_DEBUG_DAPPER_FILTER}'") set(MIOPEN_GTEST_FILTER "${MIOPEN_DEBUG_DAPPER_FILTER}:${MIOPEN_GTEST_FILTER}") endif() endmacro() macro(dapper_add_sharded_test) if(NOT DEFINED MIOPEN_CATEGORY) set(MIOPEN_CATEGORY "NONE") endif() # Run 'select' as a ctest test so it executes after the shard tests (which write the XML # output files) and before the dapper analysis test. add_test(NAME dapper_tests_generate COMMAND ${Python_EXECUTABLE} "${PY_MAIN}" select ${MAPPING_JSON} --fixturemap=${FIXTURES_JSON} --shardsfile=${SHARDS_FILE} WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} ) set_tests_properties(dapper_tests_generate PROPERTIES DEPENDS "${MIOPEN_GTEST_SHARDS}" FIXTURES_SETUP dapper_tests_fixture ) add_test(NAME miopen_gtest_sharded_dapper COMMAND ${Python_EXECUTABLE} ${MIOPEN_DAPPER_DIFF} "${TESTS_JSON}" "${MIOPEN_CATEGORY}" "${MIOPEN_GTEST_FILTER}" WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} ) set_tests_properties(miopen_gtest_sharded_dapper PROPERTIES FIXTURES_REQUIRED dapper_tests_fixture RUN_SERIAL TRUE ) # Force miopen_gtest_sharded_dapper to run dead last so its analysis summary prints at the very # end of the ctest output, not interleaved with (or buried under) the buffered output of # long-running tests that are still finishing (test_conv3d, test_immed_conv3d, ...). # # We use the DEPENDS test property rather than a FIXTURES_CLEANUP fixture on purpose. DEPENDS # only orders tests that are *already* selected to run; it never pulls extra tests into a run. # A FIXTURES_REQUIRED-on-every-test scheme would instead auto-pull the dapper setup/shard chain # into any subset run (e.g. `ctest -R conv_transposed_wrw`), which is slow and can fail because # dapper_tests_generate would run without shard XML present. # # dapper must run after every other test. The shard tests are in this directory scope # (MIOPEN_GTEST_SHARDS); the remaining tests are defined in the parent test/ directory, which is # fully processed before this subdirectory is added (add_subdirectory(gtest) is its last # statement), so the parent's TESTS directory property is complete and safe to read here. get_property(_dapper_parent_tests DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.. PROPERTY TESTS) set(_dapper_predecessors ${_dapper_parent_tests} ${MIOPEN_GTEST_SHARDS}) # dapper_tests_generate is already ordered before dapper via dapper_tests_fixture; exclude it and # dapper itself from the dependency list. list(REMOVE_ITEM _dapper_predecessors miopen_gtest_sharded_dapper dapper_tests_generate) if(_dapper_predecessors) set_property(TEST miopen_gtest_sharded_dapper APPEND PROPERTY DEPENDS "${_dapper_predecessors}") endif() unset(_dapper_parent_tests) unset(_dapper_predecessors) # CMake target equivalent to miopen_gtest_sharded_dapper add_custom_target(dapper_diff COMMAND ${Python_EXECUTABLE} ${MIOPEN_DAPPER_DIFF} "${TESTS_JSON}" "${MIOPEN_CATEGORY}" "${MIOPEN_GTEST_FILTER}" WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} DEPENDS miopen-check test_immed_conv3d test_tensor_vec test_conv3d_find2 VERBATIM ) # Full dapper pipeline using only existing shard and fixtures outputs — no rebuild. # Errors immediately if miopen_dapper_fixtures.json is missing (run dapper_fix_diff instead). add_custom_target(dapper_only_diff COMMENT "Running full dapper pipeline on existing shard outputs (no rebuild)..." COMMAND ${Python_EXECUTABLE} -c "import sys, pathlib; f=pathlib.Path('${FIXTURES_JSON}'); f.exists() or (print(f'Error: {f.name} not found. Run dapper_fix_diff to regenerate it via the preprocessor, or copy a valid file into: {f.parent}'), sys.exit(1))" COMMAND ${Python_EXECUTABLE} ${PY_MAIN} shas COMMAND ${Python_EXECUTABLE} ${PY_MAIN} parse ${BUILD_NINJA} COMMAND ${Python_EXECUTABLE} ${PY_MAIN} select ${MAPPING_JSON} --fixturemap=${FIXTURES_JSON} --shardsfile=${SHARDS_FILE} COMMAND ${Python_EXECUTABLE} ${MIOPEN_DAPPER_DIFF} ${TESTS_JSON} ${MIOPEN_CATEGORY} ${MIOPEN_GTEST_FILTER} WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} VERBATIM ) # Same as dapper_only_diff but regenerates miopen_dapper_fixtures.json via the C preprocessor. # Use this when fixture mappings may be stale or the file is missing. add_custom_target(dapper_fix_diff COMMENT "Running full dapper pipeline, regenerating fixtures (no rebuild)..." COMMAND ${Python_EXECUTABLE} ${PY_MAIN} shas COMMAND ${Python_EXECUTABLE} ${PY_FIXTURES} COMMAND ${Python_EXECUTABLE} ${PY_MAIN} parse ${BUILD_NINJA} COMMAND ${Python_EXECUTABLE} ${PY_MAIN} select ${MAPPING_JSON} --fixturemap=${FIXTURES_JSON} --shardsfile=${SHARDS_FILE} COMMAND ${Python_EXECUTABLE} ${MIOPEN_DAPPER_DIFF} ${TESTS_JSON} ${MIOPEN_CATEGORY} ${MIOPEN_GTEST_FILTER} WORKING_DIRECTORY ${MIOPEN_DAPPER_OUT_DIR} VERBATIM ) endmacro()