From 8002e1b2e6a4e188b047957712f37a524105c994 Mon Sep 17 00:00:00 2001 From: Branden Butler Date: Thu, 21 Sep 2023 14:36:38 -0500 Subject: [PATCH 1/4] Allow types as test section names --- cmake/cmake_test/add_section.cmake | 9 ++++++ .../detail_/utilities/print_result.cmake | 4 +-- cmake/cmake_test/execution_unit.cmake | 4 +-- tests/cmake_test/add_section.cmake | 29 +++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/cmake/cmake_test/add_section.cmake b/cmake/cmake_test/add_section.cmake index c1381fe..6be3f4e 100644 --- a/cmake/cmake_test/add_section.cmake +++ b/cmake/cmake_test/add_section.cmake @@ -83,7 +83,16 @@ function(ct_add_section) cmake_parse_arguments(CT_ADD_SECTION "${_as_options}" "${_as_one_value_args}" "${_as_multi_value_args}" ${ARGN} ) + # This is to set a default value for the print length + # argument to prevent any weird empty strings from getting through + if(NOT DEFINED CT_ADD_SECTION_PRINT_LENGTH) + set(CT_ADD_SECTION_PRINT_LENGTH 0) + endif() + # Assert sig doesn't work too well with the position agnostic kwargs, + # so first we parse the arguments and then we check their types. + # Right now, allow any type for the name + cpp_assert_signature("${CT_ADD_SECTION_NAME};${CT_ADD_SECTION_PRINT_LENGTH}" str int) set(_as_print_length_forced "NO") diff --git a/cmake/cmake_test/detail_/utilities/print_result.cmake b/cmake/cmake_test/detail_/utilities/print_result.cmake index 0b9f263..9450b2c 100644 --- a/cmake/cmake_test/detail_/utilities/print_result.cmake +++ b/cmake/cmake_test/detail_/utilities/print_result.cmake @@ -103,7 +103,7 @@ endfunction() # :type print_length: int #]] function(_ct_print_pass _pp_name _pp_depth _pp_print_length) - cpp_assert_signature("${ARGV}" desc int int) + cpp_assert_signature("${ARGV}" str int int) _ct_print_result("${_pp_name}" "${CT_BoldGreen}PASSED${CT_ColorReset}" "${_pp_depth}" "${_pp_print_length}") endfunction() @@ -124,6 +124,6 @@ endfunction() # :type print_length: int #]] function(_ct_print_fail _pf_name _pf_depth _pf_print_length) - cpp_assert_signature("${ARGV}" desc int int) + cpp_assert_signature("${ARGV}" str int int) _ct_print_result("${_pf_name}" "${CT_BoldRed}FAILED${CT_ColorReset}" "${_pf_depth}" "${_pf_print_length}") endfunction() diff --git a/cmake/cmake_test/execution_unit.cmake b/cmake/cmake_test/execution_unit.cmake index 0c396a2..87fa442 100644 --- a/cmake/cmake_test/execution_unit.cmake +++ b/cmake/cmake_test/execution_unit.cmake @@ -177,9 +177,9 @@ cpp_class(CTExecutionUnit) # :param expect_fail: Whether this unit is expected to fail. # #]] - cpp_constructor(CTOR CTExecutionUnit str desc* bool) + cpp_constructor(CTOR CTExecutionUnit str str bool) function("${CTOR}" self test_id friendly_name expect_fail) - # Name could be a description or a function because it + # Name could be a description, a type, or a function because it # isn't considered invalid to do so, such as using # a test name of "set" # diff --git a/tests/cmake_test/add_section.cmake b/tests/cmake_test/add_section.cmake index e131301..a520c2c 100644 --- a/tests/cmake_test/add_section.cmake +++ b/tests/cmake_test/add_section.cmake @@ -18,6 +18,33 @@ function(${test_add_section_top_level}) function(${subsection_0}) cpp_set_global(TEST_ADD_SECTION_S_S0 TRUE) endfunction() + + ct_add_section(NAME bool) + function(${bool}) + cpp_set_global(TEST_ADD_SECTION_S_S1 TRUE) + endfunction() + endfunction() + + ct_add_section(NAME wrong_sig EXPECTFAIL) + function("${wrong_sig}") + ct_add_section(NAME "invalid_print_length" PRINT_LENGTH FALSE) + function("${invalid_print_length}") + message("This cannot be") + endfunction() + endfunction() + + ct_add_section(NAME invalid_name EXPECTFAIL) + function("${invalid_name}") + # CMake won't allow a variable name with spaces, so making a test + # with such a name is impossible with the current implementation. + # Well, technically not impossible, if you set a different + # variable to the text "incomprehensible with spaces" + # you can then double deference it to get the function identifier out. + # We probably don't want to deal with that though + ct_add_section(NAME "incomprehensible with spaces") + function("${incomprehensible with spaces}") + message("This cannot be") + endfunction() endfunction() endfunction() @@ -27,9 +54,11 @@ function(${test_sections_were_run}) cpp_get_global(s0 TEST_ADD_SECTION_S0) cpp_get_global(s1 TEST_ADD_SECTION_S1) cpp_get_global(s_s0 TEST_ADD_SECTION_S_S0) + cpp_get_global(s_s1 TEST_ADD_SECTION_S_S1) ct_assert_true(s0) ct_assert_true(s1) ct_assert_true(s_s0) + ct_assert_true(s_s1) endfunction() From f3cca2a4547a9c5276e472831bddcbf49cdc8940 Mon Sep 17 00:00:00 2001 From: Branden Butler Date: Sat, 30 Sep 2023 15:55:07 -0500 Subject: [PATCH 2/4] Add CMAKETEST_SECTION and CMAKETEST_TEST result variables for arbitrary test and section names --- cmake/cmake_test/add_section.cmake | 121 ++++++++++++++++++++++------- cmake/cmake_test/add_test.cmake | 7 ++ tests/cmake_test/add_section.cmake | 19 +++-- tests/cmake_test/add_test.cmake | 14 ++++ 4 files changed, 126 insertions(+), 35 deletions(-) diff --git a/cmake/cmake_test/add_section.cmake b/cmake/cmake_test/add_section.cmake index 6be3f4e..c7131b9 100644 --- a/cmake/cmake_test/add_section.cmake +++ b/cmake/cmake_test/add_section.cmake @@ -16,28 +16,36 @@ include_guard() #[[[ -# Adds a test section, should be called inside of a declared test function directly before declaring the section function. -# The NAME parameter will be populated as by set() with the generated section function name. Declare the section function using this generated name. Ex: +# Adds a test section, should be called inside of a +# declared test function directly before declaring the section function. +# +# A variable named :code:`CMAKETEST_SECTION` will be set in the +# calling scope that holds the section function ID. Use this variable +# to define the CMake function holding the section code. Ex: # # .. code-block:: cmake # # #This is inside of a declared test function # ct_add_section(NAME this_section) -# function(${this_section}) +# function(${CMAKETEST_SECTION}) # message(STATUS "This code will run in a test section") # endfunction() # -# Upon being executed, this function will check if the section should be executed. -# If it is not, ct_add_section() will generate an ID for the section function and sets the variable pointed to by the NAME parameter to it. -# It will also construct a new CTExecutionUnit instance to represent the section. # -# If the section is supposed to be executed, ct_add_section() will call the ``execute`` member function of the CTExecutionUnit representing this section. -# Exceptions will be tracked while the function is being executed. After completion of the test, the test status will be output -# to the screen. The section subsections will then be executed, following this same flow until there are no more subsections. +# Additionally, the NAME parameter will be populated as by set() with the +# generated section function name. This is for backwards-compatibility +# purposes. Ex: # -# If a section raises an exception when it is not expected to, it will be marked as a failing section and its subsections -# will not be executed, due to limitations in how CMake handles failures. However, sibling sections as well as -# other tests will continue to execute, and the failures will be aggregated and printed after all tests have been ran. +# .. code-block:: cmake +# +# #This is inside of a declared test function +# ct_add_section(NAME this_section) +# function(${this_section}) +# message(STATUS "This code will run in a test section") +# endfunction() +# +# This behavior is considered deprecated, use the first form +# for new sections. # # Print length of pass/fail lines can be adjusted with the `PRINT_LENGTH` option. # @@ -47,11 +55,18 @@ include_guard() # 3. Length set by ct_set_print_length() # 4. Built-in default of 80. # +# If a section raises an exception when it is not expected to, +# it will be marked as a failing section and its subsections +# will not be executed, due to limitations in how CMake handles failures. +# However, sibling sections as well as other tests +# will continue to execute, and the failures will be aggregated +# and printed after all tests have been ran. +# # **Keyword Arguments** # # :keyword NAME: Required argument specifying the name variable of the section. Will set a variable with # specified name containing the generated function ID to use. -# :type NAME: pointer +# :type NAME: str* # :keyword EXPECTFAIL: Option indicating whether the section is expected to fail or not, if # specified will cause test failure when no exceptions were caught and success # upon catching any exceptions. @@ -60,19 +75,43 @@ include_guard() # print length of pass/fail output lines. # :type PRINT_LENGTH: int # -# .. seealso:: :func:`add_test.cmake.ct_add_test` for details on EXPECTFAIL. +# .. seealso:: :func:`~cmake_test/add_test.ct_add_test` for details on EXPECTFAIL. +# +# .. seealso:: :func:`~cmake_test/exec_tests.ct_exec_tests` for details on halting tests on exceptions. +# +# Implementation Details +# ---------------------- +# +# Upon being executed, this function will check if the section should be executed. +# If it is not, this function will generate an ID for the section +# function and sets the variable pointed to by the NAME parameter to it. +# It will also construct a new :class:`~cmake_test/execution_unit.CTExecutionUnit` +# instance to represent the section. +# +# If the section is supposed to be executed, this function +# will call the :meth:`~cmake_test/execution_unit.CTExecutionUnit.execute` +# method of the unit representing this section. +# Exceptions will be tracked while the function is being executed. +# After completion of the test, the test status will be output +# using :meth:`~cmake_test/execution_unit.CTExecutionUnit.print_pass_or_fail`. +# The section's subsections will then be executed recursively, following +# this same flow until there are no more subsections. # -# .. seealso:: :func:`exec_test.cmake.ct_exec_test` for details on halting tests on exceptions. # #]] function(ct_add_section) + ##################################### + # Context switch and arg parsing # + ##################################### + # Set debug mode to what it should be for cmaketest, in case the test changed it set(_as_temp_debug_mode "${CMAKEPP_LANG_DEBUG_MODE}") cpp_get_global(_as_ct_debug_mode "CT_DEBUG_MODE") set(CMAKEPP_LANG_DEBUG_MODE "${_as_ct_debug_mode}") cpp_set_global("CT_CURR_TEST_DEBUG_MODE" "${_as_temp_debug_mode}") + # Parse the arguments cpp_get_global(_as_curr_instance "CT_CURRENT_EXECUTION_UNIT_INSTANCE") CTExecutionUnit(GET "${_as_curr_instance}" _as_parent_print_length print_length) CTExecutionUnit(GET "${_as_curr_instance}" _as_parent_print_length_forced print_length_forced) @@ -89,11 +128,16 @@ function(ct_add_section) set(CT_ADD_SECTION_PRINT_LENGTH 0) endif() + # Assert sig doesn't work too well with the position agnostic kwargs, # so first we parse the arguments and then we check their types. # Right now, allow any type for the name cpp_assert_signature("${CT_ADD_SECTION_NAME};${CT_ADD_SECTION_PRINT_LENGTH}" str int) + ##################################### + # Print length detection # + ##################################### + set(_as_print_length_forced "NO") # Set default print length to CT_PRINT_LENGTH. Can be overriden @@ -106,38 +150,57 @@ function(ct_add_section) set(_as_print_length "${_as_parent_print_length}") endif() + + ##################################### + # Name retrieval and generation # + ##################################### + CTExecutionUnit(GET "${_as_curr_instance}" _as_sibling_sections_map section_names_to_ids) cpp_map(GET "${_as_sibling_sections_map}" _as_curr_section_id "${CT_ADD_SECTION_NAME}") #Unset in main interpreter, TRUE in subprocess cpp_get_global(_as_exec_expectfail "CT_EXEC_EXPECTFAIL") + # The name is set to "_" in the expectfail subprocess + # if the test is not intended to be ran if(_as_exec_expectfail) if("${${CT_ADD_SECTION_NAME}}" STREQUAL "" OR "${${CT_ADD_SECTION_NAME}}" STREQUAL "_") set("${CT_ADD_SECTION_NAME}" "_" PARENT_SCOPE) + set(CMAKETEST_SECTION "_" PARENT_SCOPE) # Reset debug mode in case test changed it set(CMAKEPP_LANG_DEBUG_MODE "${_as_temp_debug_mode}") return() #If section is not part of the call tree, immediately return endif() endif() + # Check if the name for this section is set, + # if so then retrieve it, else generation + CTExecutionUnit(GET "${_as_curr_instance}" _as_siblings section_names_to_ids) cpp_map(HAS_KEY "${_as_siblings}" _as_unit_created "${CT_ADD_SECTION_NAME}") if(NOT _as_unit_created) cpp_unique_id(_as_section_name) #Generate random section ID - - # Need to duplicate because CMake scoping rules are inconsistent. - # Setting in parent scope does not set in current scope - set("${CT_ADD_SECTION_NAME}" "${_as_section_name}") - set("${CT_ADD_SECTION_NAME}" "${_as_section_name}" PARENT_SCOPE) else() cpp_map(GET "${_as_siblings}" _as_section_name "${CT_ADD_SECTION_NAME}") - set("${CT_ADD_SECTION_NAME}" "${_as_section_name}") - set("${CT_ADD_SECTION_NAME}" "${_as_section_name}" PARENT_SCOPE) endif() - #Get whether we should execute section now + + # Set the output variables + + # Need to duplicate because CMake scoping rules are inconsistent. + # Setting in parent scope does not set in current scope + set("${CT_ADD_SECTION_NAME}" "${_as_section_name}") + set("${CT_ADD_SECTION_NAME}" "${_as_section_name}" PARENT_SCOPE) + + set("CMAKETEST_SECTION" "${_as_section_name}") + set("CMAKETEST_SECTION" "${_as_section_name}" PARENT_SCOPE) + + ##################################### + # Execution and unit construction # + ##################################### + + # Get whether we should execute section now CTExecutionUnit(GET "${_as_curr_instance}" _as_exec_section execute_sections) if(_as_exec_section) #Time to execute our section @@ -151,9 +214,9 @@ function(ct_add_section) CTExecutionUnit(GET "${_as_curr_instance}" _as_siblings section_names_to_ids) cpp_map(HAS_KEY "${_as_siblings}" _as_unit_created "${CT_ADD_SECTION_NAME}") if(NOT _as_unit_created) - #First time run, construct and configure - #the new section unit, as well as add it - #to its parent + # First time run, construct and configure + # the new section unit, as well as add it + # to its parent @@ -165,7 +228,7 @@ function(ct_add_section) CTExecutionUnit( CTOR _as_new_section - "${${CT_ADD_SECTION_NAME}}" + "${CMAKETEST_SECTION}" "${CT_ADD_SECTION_NAME}" "${CT_ADD_SECTION_EXPECTFAIL}" ) @@ -175,9 +238,9 @@ function(ct_add_section) CTExecutionUnit(SET "${_as_new_section}" test_file "${_as_parent_file}") CTExecutionUnit(SET "${_as_new_section}" section_depth "${_as_new_section_depth}") CTExecutionUnit(SET "${_as_new_section}" debug_mode "${_as_temp_debug_mode}") - CTExecutionUnit(append_child "${_as_curr_instance}" "${${CT_ADD_SECTION_NAME}}" "${_as_new_section}") + CTExecutionUnit(append_child "${_as_curr_instance}" "${CMAKETEST_SECTION}" "${_as_new_section}") CTExecutionUnit(GET "${_as_curr_instance}" _as_siblings section_names_to_ids) - cpp_map(SET "${_as_siblings}" "${CT_ADD_SECTION_NAME}" "${${CT_ADD_SECTION_NAME}}") + cpp_map(SET "${_as_siblings}" "${CT_ADD_SECTION_NAME}" "${CMAKETEST_SECTION}") endif() # Reset debug mode in case test changed it diff --git a/cmake/cmake_test/add_test.cmake b/cmake/cmake_test/add_test.cmake index 7710d5c..63cce1f 100644 --- a/cmake/cmake_test/add_test.cmake +++ b/cmake/cmake_test/add_test.cmake @@ -53,6 +53,11 @@ include_guard() # #]] macro(ct_add_test) + + ##################################### + # Context switch and arg parsing # + ##################################### + # Set debug mode to what it should be for cmaketest, in case the test changed it set(_at_temp_debug_mode "${CMAKEPP_LANG_DEBUG_MODE}") cpp_get_global(_at_ct_debug_mode "CT_DEBUG_MODE") @@ -79,6 +84,7 @@ macro(ct_add_test) if(_at_exec_expectfail AND ("${${CT_ADD_TEST_NAME}}" STREQUAL "" OR "${${CT_ADD_TEST_NAME}}" STREQUAL "_")) set("${CT_ADD_TEST_NAME}" "_") + set(CMAKETEST_TEST "_" PARENT_SCOPE) # Reset debug mode in case test changed it set(CMAKEPP_LANG_DEBUG_MODE "${_at_temp_debug_mode}") else() @@ -96,6 +102,7 @@ macro(ct_add_test) if(_at_old_id STREQUAL "") cpp_unique_id("${CT_ADD_TEST_NAME}") + set(CMAKETEST_TEST "${${CT_ADD_TEST_NAME}}") endif() if(_at_exec_expectfail OR ("${_at_old_id}" STREQUAL "")) diff --git a/tests/cmake_test/add_section.cmake b/tests/cmake_test/add_section.cmake index a520c2c..3480026 100644 --- a/tests/cmake_test/add_section.cmake +++ b/tests/cmake_test/add_section.cmake @@ -35,30 +35,37 @@ function(${test_add_section_top_level}) ct_add_section(NAME invalid_name EXPECTFAIL) function("${invalid_name}") - # CMake won't allow a variable name with spaces, so making a test - # with such a name is impossible with the current implementation. - # Well, technically not impossible, if you set a different - # variable to the text "incomprehensible with spaces" - # you can then double deference it to get the function identifier out. - # We probably don't want to deal with that though + # CMake won't allow a variable dereference with spaces, + # so the old way of naming sections should fail ct_add_section(NAME "incomprehensible with spaces") function("${incomprehensible with spaces}") message("This cannot be") endfunction() endfunction() + ct_add_section(NAME arbitrary_name) + function("${arbitrary_name}") + # CMakeTest should now support arbitrary section names + ct_add_section(NAME "Whatever we want to call it, with $pecial ch&rs") + function("${CMAKETEST_SECTION}") + cpp_set_global(TEST_ADD_SECTION_S4 TRUE) + endfunction() + endfunction() + endfunction() ct_add_test(NAME test_sections_were_run) function(${test_sections_were_run}) cpp_get_global(s0 TEST_ADD_SECTION_S0) cpp_get_global(s1 TEST_ADD_SECTION_S1) + cpp_get_global(s4 TEST_ADD_SECTION_S4) cpp_get_global(s_s0 TEST_ADD_SECTION_S_S0) cpp_get_global(s_s1 TEST_ADD_SECTION_S_S1) ct_assert_true(s0) ct_assert_true(s1) + ct_assert_true(s4) ct_assert_true(s_s0) ct_assert_true(s_s1) endfunction() diff --git a/tests/cmake_test/add_test.cmake b/tests/cmake_test/add_test.cmake index a4f596c..60066c1 100644 --- a/tests/cmake_test/add_test.cmake +++ b/tests/cmake_test/add_test.cmake @@ -16,3 +16,17 @@ function(${test_test_was_run_once}) cpp_get_global(counter "TEST_ADD_TEST_COUNTER") ct_assert_equal(counter 1) endfunction() + + +ct_add_test(NAME [[arbitrary test name with $pecial ch&rs]]) +function(${CMAKETEST_TEST}) + cpp_get_global(counter "TEST_ADD_TEST_2_COUNTER") + math(EXPR counter ${counter}+1) + cpp_set_global("TEST_ADD_TEST_2_COUNTER" ${counter}) +endfunction() + +ct_add_test(NAME test_test_2_was_run_once) +function(${test_test_2_was_run_once}) + cpp_get_global(counter "TEST_ADD_TEST_2_COUNTER") + ct_assert_equal(counter 1) +endfunction() \ No newline at end of file From 5b875c857ea58b1b3a53580c8d39a96701c72cd6 Mon Sep 17 00:00:00 2001 From: Branden Butler Date: Sat, 28 Oct 2023 18:46:31 -0500 Subject: [PATCH 3/4] Use new style section and test function names for tests used in documentation --- docs/source/writing_tests/basic_test.rst | 10 ++++------ tests/cmake_test/basic_section.cmake | 4 ++-- tests/cmake_test/expectfail.cmake | 2 +- tests/cmake_test/tutorials/1_hello_world.cmake | 2 +- tests/cmake_test/tutorials/2_sections.cmake | 8 ++++---- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/docs/source/writing_tests/basic_test.rst b/docs/source/writing_tests/basic_test.rst index d438e9c..610a543 100644 --- a/docs/source/writing_tests/basic_test.rst +++ b/docs/source/writing_tests/basic_test.rst @@ -26,12 +26,10 @@ a particular string is printed. The :obj:`~cmake_test/add_test.ct_add_test` call tells CMakeTest that there is a test with the name :code:`hello_world`. The function definition below it -defines the test. Note the odd :code:`${hello_world}` used as the -function name. This is required to link the function definition with -the :code:`ct_add_test()` call. :code:`ct_add_test()` takes the test name -and assigns a unique identifier to it to keep track of the accompanying -definition. Thus, if you use the same name for multiple tests in the same -scope they will conflict. +defines the test. Note the odd :code:`${CMAKETEST_TEST}` as the function name. +This is required to link the function definition with the test. The +value of the implicitly set :code:`CMAKETEST_TEST` variable is a unique +identifier for the test, it's only used internally. Inside the function one will notice a call to :obj:`~cmake_test/asserts/prints.ct_assert_prints`. diff --git a/tests/cmake_test/basic_section.cmake b/tests/cmake_test/basic_section.cmake index e9c05e1..cd8e3aa 100644 --- a/tests/cmake_test/basic_section.cmake +++ b/tests/cmake_test/basic_section.cmake @@ -2,10 +2,10 @@ # This file just shows how to write a basic test section. #]] ct_add_test(NAME basic_test) -function(${basic_test}) +function(${CMAKETEST_TEST}) ct_add_section(NAME basic_section) - function(${basic_section}) + function(${CMAKETEST_SECTION}) message("Basic Section") ct_assert_prints("Basic Section") diff --git a/tests/cmake_test/expectfail.cmake b/tests/cmake_test/expectfail.cmake index d2944ba..ce7457d 100644 --- a/tests/cmake_test/expectfail.cmake +++ b/tests/cmake_test/expectfail.cmake @@ -5,7 +5,7 @@ include(cmake_test/cmake_test) # in an EXPECTFAIL test will allow the test to succeed. #]] ct_add_test(NAME "make_sure_function_fails" EXPECTFAIL) -function("${make_sure_function_fails}") +function("${CMAKETEST_TEST}") function(failing_fxn) message(FATAL_ERROR "I have erred.") diff --git a/tests/cmake_test/tutorials/1_hello_world.cmake b/tests/cmake_test/tutorials/1_hello_world.cmake index 6e8c8f4..21d0c85 100644 --- a/tests/cmake_test/tutorials/1_hello_world.cmake +++ b/tests/cmake_test/tutorials/1_hello_world.cmake @@ -27,7 +27,7 @@ include(cmake_test/cmake_test) #As an introductory example we write a simple unit test that prints #"Hello World" and asserts that "Hello World" was indeed printed. ct_add_test(NAME hello_world) -function(${hello_world}) +function(${CMAKETEST_TEST}) message("Hello World") ct_assert_prints("Hello World") endfunction() diff --git a/tests/cmake_test/tutorials/2_sections.cmake b/tests/cmake_test/tutorials/2_sections.cmake index a3090b5..b2bb4b6 100644 --- a/tests/cmake_test/tutorials/2_sections.cmake +++ b/tests/cmake_test/tutorials/2_sections.cmake @@ -20,7 +20,7 @@ #think it does. include(cmake_test/cmake_test) ct_add_test(NAME "_test_sections") -function(${_test_sections}) +function(${CMAKETEST_TEST}) set(common "This variable is available to all tests") ct_assert_equal(common "This variable is available to all tests") @@ -51,7 +51,7 @@ function(${_test_sections}) #``ct_end_test``, whereas all inner scopes (even scopes within sections) are #started with ``ct_add_section`` and ended with ``endfunction``. ct_add_section(NAME "_scoped_variable") - function(${_scoped_variable}) + function(${CMAKETEST_SECTION}) #TUTORIAL # @@ -78,7 +78,7 @@ function(${_test_sections}) # 3. Length set by ct_set_print_length() # 4. Built-in default of 80. ct_add_section(NAME "_nested_section" PRINT_LENGTH 180) - function(${_nested_section}) + function(${CMAKETEST_SECTION}) set(not_common "This change only matters here") ct_assert_equal(common "This variable is available to all tests") ct_assert_equal(not_common "This change only matters here") @@ -93,7 +93,7 @@ function(${_test_sections}) set(not_common "Only visible from here forward") ct_add_section(NAME "_another_nested_section") - function(${_another_nested_section}) + function(${CMAKETEST_SECTION}) ct_assert_equal(not_common "Only visible from here forward") endfunction() endfunction() From 01d981cb81a5ad4a0749181cca6340ceb29113f2 Mon Sep 17 00:00:00 2001 From: Branden Butler Date: Sat, 28 Oct 2023 19:00:56 -0500 Subject: [PATCH 4/4] Document restrictions of deprecated naming scheme --- cmake/cmake_test/add_test.cmake | 24 ++++++++++++++++++++---- docs/source/writing_tests/basic_test.rst | 11 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/cmake/cmake_test/add_test.cmake b/cmake/cmake_test/add_test.cmake index 63cce1f..9f5a1aa 100644 --- a/cmake/cmake_test/add_test.cmake +++ b/cmake/cmake_test/add_test.cmake @@ -18,17 +18,33 @@ include_guard() # # Unit testing in CMakeTest works by `include()`ing each unit test, determining which ones # need to be ran, and then executing them sequentially in-process. This macro defines which functions -# are to be interpretted as actual unit tests. It does so by setting a variable in the calling scope -# that is to be used as the function identifier. For example: +# are to be interpretted as actual unit tests. +# +# A variable named :code:`CMAKETEST_TEST` will be set in the +# calling scope that holds the test function ID. Use this variable +# to define the CMake function holding the section code. Ex: +# +# .. code-block:: cmake +# +# ct_add_test(NAME [=[Any test name here]=]) +# function(${CMAKETEST_TEST}) +# message(STATUS "This code will run in a test") +# endfunction() +# +# +# Additionally, the NAME parameter will be populated as by set() with the +# generated section function name. This is for backwards-compatibility +# purposes. Ex: # # .. code-block:: cmake # # ct_add_test(NAME this_test) # function(${this_test}) -# message(STATUS "This code will run in a unit test") +# message(STATUS "This code will run in a test") # endfunction() # -# This helps tests avoid name collisions and also allows the testing framework to keep track of them. +# This behavior is considered deprecated, use the first form +# for new tests. # # Print length of pass/fail lines can be adjusted with the `PRINT_LENGTH` option. # diff --git a/docs/source/writing_tests/basic_test.rst b/docs/source/writing_tests/basic_test.rst index 610a543..26d813d 100644 --- a/docs/source/writing_tests/basic_test.rst +++ b/docs/source/writing_tests/basic_test.rst @@ -31,6 +31,17 @@ This is required to link the function definition with the test. The value of the implicitly set :code:`CMAKETEST_TEST` variable is a unique identifier for the test, it's only used internally. +The name of the test may be any string and can include special characters. +If the name has such special characters, pass it as a bracket argument +instead of as a quoted argument. + +.. note:: + There is a secondary, deprecated form of naming tests and sections. + This secondary form has restrictions on the name given such that it + is a valid CMake variable identifier. New tests and sections should + use the above form instead. See :obj:`~cmake_test/add_test.ct_add_test` + for information on the deprecated form. + Inside the function one will notice a call to :obj:`~cmake_test/asserts/prints.ct_assert_prints`. This is one of the included assertion functions. If an assertion fails,