From 7aacae4e0e08ce20bb2d46c2394eeae005d249d2 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 6 Jan 2024 03:30:34 -0500 Subject: Tests: Add unit tests for property redefinition From reading `Source/cmDefinePropertyCommand.cxx` and `Source/cmPropertyDefinition.cxx`, attempts to use `define_property()` to redefine an existing property will be silently ignored. Once a property is defined, it cannot be redefined. Add some unit tests to confirm this behavior of `define_property()` remains as expected based on the current implementation. --- Tests/RunCMake/define_property/RunCMakeTest.cmake | 1 + .../define_property/define_property-redefine.cmake | 88 ++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 Tests/RunCMake/define_property/define_property-redefine.cmake diff --git a/Tests/RunCMake/define_property/RunCMakeTest.cmake b/Tests/RunCMake/define_property/RunCMakeTest.cmake index 93eaf1b..0a457df 100644 --- a/Tests/RunCMake/define_property/RunCMakeTest.cmake +++ b/Tests/RunCMake/define_property/RunCMakeTest.cmake @@ -1,6 +1,7 @@ include(RunCMake) run_cmake(define_property) +run_cmake(define_property-redefine) run_cmake(define_property-INITIALIZE_FROM_VARIABLE) run_cmake(define_property-INITIALIZE_FROM_VARIABLE-invalid_1) run_cmake(define_property-INITIALIZE_FROM_VARIABLE-invalid_2) diff --git a/Tests/RunCMake/define_property/define_property-redefine.cmake b/Tests/RunCMake/define_property/define_property-redefine.cmake new file mode 100644 index 0000000..b0b5e95 --- /dev/null +++ b/Tests/RunCMake/define_property/define_property-redefine.cmake @@ -0,0 +1,88 @@ +function(verify_value type prop attrib expected actual) + if(expected STREQUAL "FALSE") + if(actual) + message(FATAL_ERROR + "Expected ${type} property ${prop}'s ${attrib} to be false") + endif() + elseif(expected STREQUAL "TRUE") + if(NOT actual) + message(FATAL_ERROR + "Expected ${type} property ${prop}'s ${attrib} to be true") + endif() + elseif(NOT actual STREQUAL expected) + message(FATAL_ERROR + "Expected value of ${type} property ${prop}'s ${attrib}:\n" + " ${expected}\n" + "Actual value:\n" + " ${actual}" + ) + endif() +endfunction() + +function(assert_tgt_prop_attrib_eq prop attrib expected) + get_property(actual TARGET NONE PROPERTY "${prop}" "${attrib}") + verify_value(TARGET "${prop}" "${attrib}" "${expected}" "${actual}") +endfunction() + +function(assert_dir_prop_attrib_eq prop attrib expected) + get_property(actual DIRECTORY "" PROPERTY "${prop}" "${attrib}") + verify_value(DIRECTORY "${prop}" "${attrib}" "${expected}" "${actual}") +endfunction() + +# +# TESTS +# + +# Define a new target property +message(CHECK_START "Testing define_property(TARGET ...)") +define_property(TARGET PROPERTY TGT1 + BRIEF_DOCS "Brief") +assert_tgt_prop_attrib_eq(TGT1 BRIEF_DOCS "Brief") +assert_tgt_prop_attrib_eq(TGT1 FULL_DOCS "NOTFOUND") +message(CHECK_PASS "Complete") + +# Attempt to redefine with different/additional attributes +message(CHECK_START "Testing TARGET property redefinition") +define_property(TARGET PROPERTY TGT1 + BRIEF_DOCS "Changed" + FULL_DOCS "Full") +assert_tgt_prop_attrib_eq(TGT1 BRIEF_DOCS "Brief") +assert_tgt_prop_attrib_eq(TGT1 FULL_DOCS "NOTFOUND") +message(CHECK_PASS "Complete") + +# Query undefined property +message(CHECK_START "Testing undefined TARGET property query") +assert_tgt_prop_attrib_eq(TGT2 DEFINED FALSE) +assert_tgt_prop_attrib_eq(TGT2 BRIEF_DOCS "NOTFOUND") +message(CHECK_PASS "Complete") + +# Define after query +message(CHECK_START "Testing TARGET property definition after query") +define_property(TARGET PROPERTY TGT2 + BRIEF_DOCS "Brief" + FULL_DOCS "Full" +) +assert_tgt_prop_attrib_eq(TGT2 DEFINED TRUE) +assert_tgt_prop_attrib_eq(TGT2 BRIEF_DOCS "Brief") +assert_tgt_prop_attrib_eq(TGT2 FULL_DOCS "Full") +message(CHECK_PASS "Complete") + +# Define a new directory property +message(CHECK_START "Testing define_property(DIRECTORY ...)") +define_property(DIRECTORY PROPERTY DIR1 + BRIEF_DOCS "Brief" + FULL_DOCS "Full" +) +assert_dir_prop_attrib_eq(DIR1 DEFINED TRUE) +assert_dir_prop_attrib_eq(DIR1 BRIEF_DOCS "Brief") +assert_dir_prop_attrib_eq(DIR1 FULL_DOCS "Full") +message(CHECK_PASS "Complete") + +# Attempt to redefine existing attributes +message(CHECK_START "Testing DIRECTORY property redefinition") +define_property(DIRECTORY PROPERTY DIR1 + BRIEF_DOCS "Overwritten" +) +assert_dir_prop_attrib_eq(DIR1 BRIEF_DOCS "Brief") +assert_dir_prop_attrib_eq(DIR1 FULL_DOCS "Full") +message(CHECK_PASS "Complete") -- cgit v0.12 From 6c3311d53beed5bd229efeaaa4fefc330de3ddea Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 6 Jan 2024 04:19:45 -0500 Subject: Help: Document property redefinition semantics Add a section to the `define_property()` documentation which details the behavior when attempting to redefine an existing property. (The command is silently ignored.) Provide an example using `get_property()` to examine a property definition created with `define_property()`. --- Help/command/define_property.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Help/command/define_property.rst b/Help/command/define_property.rst index 5278e30..06f2823 100644 --- a/Help/command/define_property.rst +++ b/Help/command/define_property.rst @@ -74,6 +74,42 @@ project via corresponding options to the :command:`get_property` command. underscore. It is recommended that the property name have a prefix specific to the project. +Property Redefinition +^^^^^^^^^^^^^^^^^^^^^ + +Once a property is defined for a particular type of scope, it cannot be +redefined. Attempts to redefine an existing property by calling +:command:`define_property` with the same scope type and property name +will be silently ignored. Defining the same property name for two different +kinds of scope is valid. + +:command:`get_property` can be used to determine whether a property is +already defined for a particular kind of scope, and if so, to examine its +definition. For example: + +.. code-block:: cmake + + # Initial definition + define_property(TARGET PROPERTY MY_NEW_PROP + BRIEF_DOCS "My new custom property" + ) + + # Later examination + get_property(my_new_prop_exists + TARGET NONE + PROPERTY MY_NEW_PROP + DEFINED + ) + + if(my_new_prop_exists) + get_property(my_new_prop_docs + TARGET NONE + PROPERTY MY_NEW_PROP + BRIEF_DOCS + ) + # ${my_new_prop_docs} is now set to "My new custom property" + endif() + See Also ^^^^^^^^ -- cgit v0.12