Browse Source

Initial commit.

Signed-off-by: John <[email protected]>
John 2 năm trước cách đây
mục cha
commit
07d0fa06fb

+ 1 - 0
CMakeLists.txt

@@ -46,6 +46,7 @@ include(cmake/Install.cmake)
 include(cmake/LYWrappers.cmake)
 include(cmake/Gems.cmake)
 include(cmake/UnitTest.cmake)
+include(cmake/TestImpactFramework/TestImpactTestTargetConfig.cmake) # LYTestWrappers dependency
 include(cmake/LYTestWrappers.cmake)
 include(cmake/Monolithic.cmake)
 include(cmake/SettingsRegistry.cmake)

+ 1 - 1
Code/Tools/TestImpactFramework/CMakeLists.txt

@@ -10,7 +10,7 @@ o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O
 
 include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
 
-if(PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED AND LY_TEST_IMPACT_ACTIVE)
+if(PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED AND O3DE_TEST_IMPACT_ACTIVE)
     add_subdirectory(Runtime)
     add_subdirectory(Frontend)
     ly_add_pytest(

+ 8 - 3
cmake/TestImpactFramework/ConsoleFrontendConfig.in

@@ -5,9 +5,6 @@
       "timestamp": "${timestamp}",
       "build_config": "${build_config}"
     },
-    "jenkins": {
-      "use_test_impact_analysis": ${use_tiaf}
-    },
     "repo": {
       "root": "${repo_dir}",
       "build": "${bin_dir}"
@@ -49,6 +46,10 @@
     }
   },
   "native": {
+    "jenkins": {
+      "enabled": ${native_jenkins_enabled},
+      "use_test_impact_analysis": ${use_tiaf}
+    },
     "workspace": {
       "temp": {
         "root": "${native_temp_dir}",
@@ -100,6 +101,10 @@
     }
   },
   "python": {
+    "jenkins": {
+      "enabled": ${python_jenkins_enabled},
+      "use_test_impact_analysis": true
+    },
     "workspace": {
       "temp": {
         "root": "${python_temp_dir}",

+ 39 - 33
cmake/TestImpactFramework/LYTestImpactFramework.cmake

@@ -6,9 +6,6 @@
 #
 #
 
-# Path to test instrumentation binary
-set(LY_TEST_IMPACT_INSTRUMENTATION_BIN "" CACHE PATH "Path to test impact framework instrumentation binary")
-
 # Name of test impact framework console static library target
 set(LY_TEST_IMPACT_CONSOLE_NATIVE_STATIC_TARGET "TestImpact.Frontend.Console.Native.Static")
 
@@ -69,15 +66,6 @@ set(LY_TEST_IMPACT_NATIVE_TEST_RUN_DIR "${GTEST_XML_OUTPUT_DIR}")
 # Path to the directory that the result of python runs will be stored in.
 set(LY_TEST_IMPACT_PYTHON_TEST_RUN_DIR "${PYTEST_XML_OUTPUT_DIR}")
 
-# If we are not provided a path to the Instrumentation bin,
-# set LY_TEST_IMPACT to false so that our tests don't get added
-# and TIAF doesn't get built.
-if(LY_TEST_IMPACT_INSTRUMENTATION_BIN)
-    set(LY_TEST_IMPACT_ACTIVE true)
-else()
-    set(LY_TEST_IMPACT_ACTIVE false)
-endif()
-
 #! ly_test_impact_rebase_file_to_repo_root: rebases the relative and/or absolute path to be relative to repo root directory and places the resulting path in quotes.
 #
 # \arg:INPUT_FILE the file to rebase
@@ -193,16 +181,18 @@ function(ly_test_impact_extract_google_test_params COMPOSITE_TEST COMPOSITE_SUIT
 
     set(test_suites "")
     foreach(composite_suite ${COMPOSITE_SUITES})
-        # Command, suite, timeout
+        # Command, suite, timeout, labels
         string(REPLACE "#" ";" suite_components ${composite_suite})
         list(LENGTH suite_components num_suite_components)
-        if(num_suite_components LESS 3)
-            message(FATAL_ERROR "The suite components ${composite_suite} are required to be in the following format: command#suite#string.")
+        if(num_suite_components LESS 4)
+            message(FATAL_ERROR "Test ${test_components} suite components ${composite_suite} are required to be in the following format: command#suite#timeout#labels.")
         endif()
         list(GET suite_components 0 test_command)
         list(GET suite_components 1 test_suite)
         list(GET suite_components 2 test_timeout)
-        set(suite_params "{ \"suite\": \"${test_suite}\",  \"command\": \"${test_command}\", \"timeout\": ${test_timeout} }")
+        list(GET suite_components 3 test_labels)
+        string(REPLACE "," "\",\"" test_labels "${test_labels}")
+        set(suite_params "{ \"suite\": \"${test_suite}\",  \"command\": \"${test_command}\", \"timeout\": ${test_timeout}, \"labels\": [\"${test_labels}\"] }")
         list(APPEND test_suites "${suite_params}")
     endforeach()
     string(REPLACE ";" ", " test_suites "${test_suites}")
@@ -239,22 +229,24 @@ function(ly_test_impact_extract_python_test_params COMPOSITE_TEST COMPOSITE_SUIT
     
     set(test_suites "")
     foreach(composite_suite ${COMPOSITE_SUITES})
-        # Script path, suite, timeout
+        # Script path, suite, timeout, labels
         string(REPLACE "#" ";" suite_components ${composite_suite})
         list(LENGTH suite_components num_suite_components)
-        if(num_suite_components LESS 3)
-            message(FATAL_ERROR "The suite components ${composite_suite} are required to be in the following format: script_path#suite#string.")
+        if(num_suite_components LESS 4)
+            message(FATAL_ERROR "Test ${test_components} suite components ${composite_suite} are required to be in the following format: script_path#suite#timeout#labels.")
         endif()
         list(GET suite_components 0 script_path)
         list(GET suite_components 1 test_suite)
         list(GET suite_components 2 test_timeout)
+        list(GET suite_components 3 test_labels)
         # Get python script path relative to repo root
         ly_test_impact_rebase_file_to_repo_root(
             "${script_path}"
             script_path
             "${LY_ROOT_FOLDER}"
         )
-        set(suite_params "{ \"suite\": \"${test_suite}\",  \"script\": \"${script_path}\", \"timeout\": ${test_timeout}, \"command\": \"${test_command}\" }")
+        string(REPLACE "," "\",\"" test_labels "${test_labels}")
+        set(suite_params "{ \"suite\": \"${test_suite}\",  \"script\": \"${script_path}\", \"timeout\": ${test_timeout}, \"command\": \"${test_command}\", \"labels\": [\"${test_labels}\"] }")
         list(APPEND test_suites "${suite_params}")
     endforeach()
     string(REPLACE ";" ", " test_suites "${test_suites}")
@@ -278,12 +270,13 @@ function(ly_test_impact_write_test_enumeration_file TEST_ENUMERATION_TEMPLATE_FI
         message(TRACE "Parsing ${test}")
         get_property(test_params GLOBAL PROPERTY LY_ALL_TESTS_${test}_PARAMS)
         get_property(test_type GLOBAL PROPERTY LY_ALL_TESTS_${test}_TEST_LIBRARY)
+
         if("${test_type}" STREQUAL "pytest")
             # Python tests
             ly_test_impact_extract_python_test_params(${test} "${test_params}" test_namespace test_name test_suites)
             list(APPEND python_tests "        { \"namespace\": \"${test_namespace}\", \"name\": \"${test_name}\", \"suites\": [${test_suites}] }")
         elseif("${test_type}" STREQUAL "pytest_editor")
-            # Python editor tests            
+            # Python editor tests
             ly_test_impact_extract_python_test_params(${test} "${test_params}" test_namespace test_name test_suites)
             list(APPEND python_editor_tests "        { \"namespace\": \"${test_namespace}\", \"name\": \"${test_name}\", \"suites\": [${test_suites}] }")
         elseif("${test_type}" STREQUAL "googletest")
@@ -296,9 +289,8 @@ function(ly_test_impact_write_test_enumeration_file TEST_ENUMERATION_TEMPLATE_FI
             ly_test_impact_extract_google_test_params(${test} "${test_params}" test_namespace test_name test_suites)
             list(APPEND google_benchmarks "        { \"namespace\": \"${test_namespace}\", \"name\": \"${test_name}\", \"launch_method\": \"${launch_method}\", \"suites\": [${test_suites}] }")
         else()
-            ly_test_impact_extract_python_test_params(${test} "${test_params}" test_namespace test_name test_suites)
             message("${test_name} is of unknown type (TEST_LIBRARY property is \"${test_type}\")")
-            list(APPEND unknown_tests "        { \"namespace\": \"${test_namespace}\", \"name\": \"${test}\", \"type\": \"${test_type}\" }")
+            list(APPEND unknown_tests "        { \"name\": \"${test}\" }")
         endif()
     endforeach()
 
@@ -334,9 +326,9 @@ function(ly_test_impact_write_gem_target_enumeration_file GEM_TARGET_TEMPLATE_FI
         endif()
     endforeach()
     string (REPLACE ";" ",\n" enumerated_gem_targets "${enumerated_gem_targets}")
-     # Write out source to target mapping file
-     set(mapping_path "${LY_TEST_IMPACT_GEM_TARGET_FILE}")
-     configure_file(${GEM_TARGET_TEMPLATE_FILE} ${mapping_path})
+    # Write out source to target mapping file
+    set(mapping_path "${LY_TEST_IMPACT_GEM_TARGET_FILE}")
+    configure_file(${GEM_TARGET_TEMPLATE_FILE} ${mapping_path})
 endfunction()
 
 #! ly_extract_aliased_target_dependencies: recursively extracts the aliases of a target to retrieve the true de-aliased target.
@@ -513,14 +505,26 @@ function(ly_test_impact_write_config_file CONFIG_TEMPLATE_FILE BIN_DIR)
     set(build_config "$<CONFIG>")
 
     # Instrumentation binary
-    if(NOT LY_TEST_IMPACT_INSTRUMENTATION_BIN)
+    if(NOT O3DE_TEST_IMPACT_INSTRUMENTATION_BIN)
         # No binary specified is not an error, it just means that the test impact analysis part of the framework is disabled
         message("No test impact framework instrumentation binary was specified, test impact analysis framework will fall back to regular test sequences instead")
         set(use_tiaf false)
         set(instrumentation_bin "")
     else()
         set(use_tiaf true)
-        file(TO_CMAKE_PATH ${LY_TEST_IMPACT_INSTRUMENTATION_BIN} instrumentation_bin)
+        file(TO_CMAKE_PATH ${O3DE_TEST_IMPACT_INSTRUMENTATION_BIN} instrumentation_bin)
+    endif()
+
+    if(O3DE_TEST_IMPACT_NATIVE_TEST_TARGETS_ENABLED)
+        set(native_jenkins_enabled true)
+    else()
+        set(native_jenkins_enabled false)
+    endif()
+
+    if(O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED)
+        set(python_jenkins_enabled true)
+    else()
+        set(python_jenkins_enabled false)
     endif()
 
     # Testrunner binary
@@ -595,7 +599,7 @@ function(ly_test_impact_write_pytest_file CONFIGURATION_FILE)
         set(config_path "${LY_TEST_IMPACT_WORKING_DIR}/${config_type}/${LY_TEST_IMPACT_PERSISTENT_DIR}/${LY_TEST_IMPACT_CONFIG_FILE_NAME}")
         list(APPEND build_configs "\"${config_type}\" : { \"config\" : \"${config_path}\"}")
     endforeach()
- 
+
     # Configure our list of entries
     string(REPLACE ";" ",\n" build_configs "${build_configs}")
     
@@ -604,7 +608,8 @@ function(ly_test_impact_write_pytest_file CONFIGURATION_FILE)
     string(CONFIGURE ${test_file} test_file)
     file(GENERATE
         OUTPUT "${LY_TEST_IMPACT_PYTEST_FILE_PATH}/ly_test_impact_test_data.json"
-        CONTENT "${test_file}")
+        CONTENT "${test_file}"
+    )
 
 endfunction()
 
@@ -630,9 +635,10 @@ endfunction()
 
 #! ly_test_impact_post_step: runs the post steps to be executed after all other cmake scripts have been executed.
 function(ly_test_impact_post_step)
-    if(NOT LY_TEST_IMPACT_ACTIVE)
-        return()
-    endif()
+    #if(NOT O3DE_TEST_IMPACT_ACTIVE)
+    #    message("TIAF is disabled, no post step will be performed.")
+    #    return()
+    #endif()
 
     # Clean temporary and persistent directories
     ly_test_impact_clean_directories()

+ 66 - 0
cmake/TestImpactFramework/TestImpactTestTargetConfig.cmake

@@ -0,0 +1,66 @@
+#
+# Copyright (c) Contributors to the Open 3D Engine Project.
+# For complete copyright and license terms please see the LICENSE at the root of this distribution.
+#
+# SPDX-License-Identifier: Apache-2.0 OR MIT
+#
+#
+
+# Path to test instrumentation binary
+set(O3DE_TEST_IMPACT_INSTRUMENTATION_BIN "" CACHE PATH "Path to test impact framework instrumentation binary")
+
+# Test impact analysis opt-in for native test targets
+set(O3DE_TEST_IMPACT_NATIVE_TEST_TARGETS_ENABLED FALSE CACHE BOOL "Whether to enable native C++ test targets for test impact analysis (otherwise, CTest will be used to run these targets).")
+
+# Test impact analysis opt-in for Python test targets
+#set(O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED FALSE CACHE BOOL "Whether to enable Python test targets for test impact analysis (otherwise, CTest will be used to run these targets).")
+set(O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED TRUE)
+
+# If we are not provided a path to the Instrumentation bin,
+# set LY_TEST_IMPACT to false so that our tests don't get added
+# and TIAF doesn't get built.
+if(O3DE_TEST_IMPACT_INSTRUMENTATION_BIN)
+    # TIAF is only enabled if at least one supported test target type has opted in for test impact analysis
+    if(O3DE_TEST_IMPACT_NATIVE_TEST_TARGETS_ENABLED OR O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED)
+        set(O3DE_TEST_IMPACT_ACTIVE true)
+        if(O3DE_TEST_IMPACT_NATIVE_TEST_TARGETS_ENABLED)
+            message("TIAF enabled for native tests.")
+        else()
+            message("TIAF disabled for native tests.")
+        endif()
+        if(O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED)
+            message("TIAF enabled for Python tests.")
+        else()
+            message("TIAF disabled for Python tests.")
+        endif()
+    else()
+        set(O3DE_TEST_IMPACT_ACTIVE false)
+        message("TIAF disabled. No test target types have opted in.")
+    endif()
+else()
+    set(O3DE_TEST_IMPACT_ACTIVE false)
+    message("TIAF disabled. Instrumentation bin not provided.")
+endif()
+
+#! o3de_test_impact_apply_test_labels: applies the the appropriate label to a test target for running in CTest according to whether
+#  or not their test framework type is enabled for running in TIAF.
+#
+# \arg:TEST_NAME The test target name
+# \arg:TEST_FRAMEWORK The test framework type of the test target
+# \arg:TEST_LABELS The existing test labels list that the TIAF label will be appended to
+function(o3de_test_impact_apply_test_labels TEST_FRAMEWORK TEST_LABELS)
+    if("${TEST_FRAMEWORK}" STREQUAL "pytest" OR "${TEST_FRAMEWORK}" STREQUAL "pytest_editor")
+        if(O3DE_TEST_IMPACT_PYTHON_TEST_TARGETS_ENABLED)
+            set(label REQUIRES_tiaf)
+        endif()
+    elseif("${TEST_FRAMEWORK}" STREQUAL "googletest" OR "${TEST_FRAMEWORK}" STREQUAL "googlebenchmark")
+        if(O3DE_TEST_IMPACT_NATIVE_TEST_TARGETS_ENABLED)
+            set(label REQUIRES_tiaf)
+        endif()
+    endif()
+    
+    if(label)
+        list(APPEND ${TEST_LABELS} ${label})
+        set(${TEST_LABELS} ${${TEST_LABELS}} PARENT_SCOPE)
+    endif()
+endfunction()