Skip to content

Commit

Permalink
feat: merge message assertion functions to assertion function (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
threeal authored May 27, 2024
1 parent 731063d commit bd84d80
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 101 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ mock_message()
message(ERROR "some error message")
end_mock_message()
assert_message(STATUS "some status message")
assert_message(ERROR "some error message")
assert(MESSAGE STATUS "some status message")
assert(MESSAGE ERROR "some error message")
```

## License
Expand Down
133 changes: 67 additions & 66 deletions cmake/Assertion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,60 +10,86 @@ include_guard(GLOBAL)
#
# Refer to the documentation of the 'if' function for supported conditions to
# perform the assertion.
#
# Aside from the assertions specified in the documentation of the 'if' function,
# this function also supports mocked message assertion by calling
# 'assert(MESSAGE <MODE> <EXPECTED_MESSAGE>)', where 'MODE' is the message mode
# and 'EXPECTED_MESSAGE' is the expected message.
function(assert)
list(LENGTH ARGN ARGUMENTS_LENGTH)
if(ARGUMENTS_LENGTH GREATER 0)
set(ARGUMENTS ${ARGN})

# Determines whether the given arguments start with 'NOT'.
list(GET ARGUMENTS 0 ARGUMENTS_0)
if(ARGUMENTS_0 STREQUAL NOT)
list(REMOVE_AT ARGUMENTS 0)
set(BOOLEAN_WORD " false")
set(NOT_WORD " not")
else()
set(ARGUMENT_NOT NOT)
set(BOOLEAN_WORD " true")
endif()
list(GET ARGUMENTS 0 ASSERTION)
if(ASSERTION STREQUAL MESSAGE)
list(LENGTH ARGUMENTS ARGUMENTS_LENGTH)
if(ARGUMENTS_LENGTH LESS 3)
message(FATAL_ERROR "usage: assert(MESSAGE <MODE> <EXPECTED_MESSAGE>)")
endif()
list(GET ARGUMENTS 1 MODE)
list(GET ARGUMENTS 2 EXPECTED_MESSAGE)

list(LENGTH ARGUMENTS ARGUMENTS_LENGTH)
if(ARGUMENTS_LENGTH EQUAL 2)
list(GET ARGUMENTS 0 OPERATOR)
list(GET ARGUMENTS 1 VALUE)
list(POP_FRONT ${MODE}_MESSAGES MESSAGE)
if(NOT MESSAGE STREQUAL EXPECTED_MESSAGE)
string(TOLOWER "${MODE}" MODE)
string(REPLACE "_" " " MODE "${MODE}")
message(FATAL_ERROR "expected ${MODE} message '${MESSAGE}' to be equal to '${EXPECTED_MESSAGE}'")
endif()

if(OPERATOR STREQUAL DEFINED)
set(MESSAGE "expected variable '${VALUE}'${NOT_WORD} to be defined")
elseif(OPERATOR STREQUAL EXISTS)
set(MESSAGE "expected path '${VALUE}'${NOT_WORD} to exist")
elseif(OPERATOR STREQUAL IS_DIRECTORY)
set(MESSAGE "expected path '${VALUE}'${NOT_WORD} to be a directory")
if(DEFINED ${MODE}_MESSAGES)
set(${MODE}_MESSAGES "${${MODE}_MESSAGES}" PARENT_SCOPE)
endif()
else()
# Determines whether the given arguments start with 'NOT'.
list(GET ARGUMENTS 0 ARGUMENTS_0)
if(ARGUMENTS_0 STREQUAL NOT)
list(REMOVE_AT ARGUMENTS 0)
set(BOOLEAN_WORD " false")
set(NOT_WORD " not")
else()
set(ARGUMENT_NOT NOT)
set(BOOLEAN_WORD " true")
endif()
elseif(ARGUMENTS_LENGTH EQUAL 3)
list(GET ARGUMENTS 0 LEFT_VALUE)
list(GET ARGUMENTS 1 OPERATOR)
list(GET ARGUMENTS 2 RIGHT_VALUE)

if(OPERATOR STREQUAL MATCHES)
if(DEFINED "${LEFT_VALUE}")
set(LEFT_VALUE "${${LEFT_VALUE}}")
endif()
set(MESSAGE "expected string '${LEFT_VALUE}'${NOT_WORD} to match '${RIGHT_VALUE}'")
elseif(OPERATOR STREQUAL STREQUAL)
if(DEFINED "${LEFT_VALUE}")
set(LEFT_VALUE "${${LEFT_VALUE}}")
list(LENGTH ARGUMENTS ARGUMENTS_LENGTH)
if(ARGUMENTS_LENGTH EQUAL 2)
list(GET ARGUMENTS 0 OPERATOR)
list(GET ARGUMENTS 1 VALUE)

if(OPERATOR STREQUAL DEFINED)
set(MESSAGE "expected variable '${VALUE}'${NOT_WORD} to be defined")
elseif(OPERATOR STREQUAL EXISTS)
set(MESSAGE "expected path '${VALUE}'${NOT_WORD} to exist")
elseif(OPERATOR STREQUAL IS_DIRECTORY)
set(MESSAGE "expected path '${VALUE}'${NOT_WORD} to be a directory")
endif()
if(DEFINED "${RIGHT_VALUE}")
set(RIGHT_VALUE "${${RIGHT_VALUE}}")
elseif(ARGUMENTS_LENGTH EQUAL 3)
list(GET ARGUMENTS 0 LEFT_VALUE)
list(GET ARGUMENTS 1 OPERATOR)
list(GET ARGUMENTS 2 RIGHT_VALUE)

if(OPERATOR STREQUAL MATCHES)
if(DEFINED "${LEFT_VALUE}")
set(LEFT_VALUE "${${LEFT_VALUE}}")
endif()
set(MESSAGE "expected string '${LEFT_VALUE}'${NOT_WORD} to match '${RIGHT_VALUE}'")
elseif(OPERATOR STREQUAL STREQUAL)
if(DEFINED "${LEFT_VALUE}")
set(LEFT_VALUE "${${LEFT_VALUE}}")
endif()
if(DEFINED "${RIGHT_VALUE}")
set(RIGHT_VALUE "${${RIGHT_VALUE}}")
endif()
set(MESSAGE "expected string '${LEFT_VALUE}'${NOT_WORD} to be equal to '${RIGHT_VALUE}'")
endif()
set(MESSAGE "expected string '${LEFT_VALUE}'${NOT_WORD} to be equal to '${RIGHT_VALUE}'")
endif()
endif()

if(${ARGUMENT_NOT} ${ARGUMENTS})
if(DEFINED MESSAGE)
message(FATAL_ERROR "${MESSAGE}")
else()
message(FATAL_ERROR "expected '${ARGUMENTS}' to resolve to${BOOLEAN_WORD}")
if(${ARGUMENT_NOT} ${ARGUMENTS})
if(DEFINED MESSAGE)
message(FATAL_ERROR "${MESSAGE}")
else()
message(FATAL_ERROR "expected '${ARGUMENTS}' to resolve to${BOOLEAN_WORD}")
endif()
endif()
endif()
endif()
Expand Down Expand Up @@ -106,31 +132,6 @@ function(end_mock_message)
set_property(GLOBAL PROPERTY message_mocked OFF)
endfunction()

# Asserts whether the 'message' function was called with the expected
# arguments.
#
# This function asserts whether a message with the specified mode was called
# with the expected message content.
#
# This function can only assert calls to the mocked 'message' function, which
# is enabled by calling the 'mock_message' function.
#
# Arguments:
# - MODE: The message mode.
# - EXPECTED_MESSAGE: The expected message content.
function(assert_message MODE EXPECTED_MESSAGE)
list(POP_FRONT ${MODE}_MESSAGES MESSAGE)
if(NOT MESSAGE STREQUAL EXPECTED_MESSAGE)
string(TOLOWER "${MODE}" MODE)
string(REPLACE "_" " " MODE "${MODE}")
message(FATAL_ERROR "expected ${MODE} message '${MESSAGE}' to be equal to '${EXPECTED_MESSAGE}'")
endif()

if(DEFINED ${MODE}_MESSAGES)
set(${MODE}_MESSAGES "${${MODE}_MESSAGES}" PARENT_SCOPE)
endif()
endfunction()

# Asserts whether the given command successfully executes a process.
#
# Arguments:
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ add_cmake_test(
"Directory path assertions"
"Regular expression match assertions"
"String equality assertions"
"Message assertions"
"Mock message"
"Assert messages"
"Assert successful process execution"
"Assert failed process execution"
"Assert matching process execution output"
Expand Down
69 changes: 37 additions & 32 deletions test/cmake/AssertionTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ function("Boolean assertions")
mock_message()
assert(FALSE)
end_mock_message()
assert_message(FATAL_ERROR "expected 'FALSE' to resolve to true")
assert(MESSAGE FATAL_ERROR "expected 'FALSE' to resolve to true")

mock_message()
assert(NOT TRUE)
end_mock_message()
assert_message(FATAL_ERROR "expected 'TRUE' to resolve to false")
assert(MESSAGE FATAL_ERROR "expected 'TRUE' to resolve to false")
endfunction()

function("Variable existence assertions")
Expand All @@ -27,12 +27,12 @@ function("Variable existence assertions")
mock_message()
assert(DEFINED NON_EXISTING_VARIABLE)
end_mock_message()
assert_message(FATAL_ERROR "expected variable 'NON_EXISTING_VARIABLE' to be defined")
assert(MESSAGE FATAL_ERROR "expected variable 'NON_EXISTING_VARIABLE' to be defined")

mock_message()
assert(NOT DEFINED EXISTING_VARIABLE)
end_mock_message()
assert_message(FATAL_ERROR "expected variable 'EXISTING_VARIABLE' not to be defined")
assert(MESSAGE FATAL_ERROR "expected variable 'EXISTING_VARIABLE' not to be defined")
endfunction()

function("Path existence assertions")
Expand All @@ -45,12 +45,12 @@ function("Path existence assertions")
mock_message()
assert(EXISTS non_existing_file)
end_mock_message()
assert_message(FATAL_ERROR "expected path 'non_existing_file' to exist")
assert(MESSAGE FATAL_ERROR "expected path 'non_existing_file' to exist")

mock_message()
assert(NOT EXISTS some_file)
end_mock_message()
assert_message(FATAL_ERROR "expected path 'some_file' not to exist")
assert(MESSAGE FATAL_ERROR "expected path 'some_file' not to exist")
endfunction()

function("Directory path assertions")
Expand All @@ -63,12 +63,12 @@ function("Directory path assertions")
mock_message()
assert(IS_DIRECTORY some_file)
end_mock_message()
assert_message(FATAL_ERROR "expected path 'some_file' to be a directory")
assert(MESSAGE FATAL_ERROR "expected path 'some_file' to be a directory")

mock_message()
assert(NOT IS_DIRECTORY some_directory)
end_mock_message()
assert_message(FATAL_ERROR "expected path 'some_directory' not to be a directory")
assert(MESSAGE FATAL_ERROR "expected path 'some_directory' not to be a directory")
endfunction()

function("Regular expression match assertions")
Expand All @@ -81,12 +81,12 @@ function("Regular expression match assertions")
mock_message()
assert(NOT "${VALUE}" MATCHES "so.*ing")
end_mock_message()
assert_message(FATAL_ERROR "expected string 'some string' not to match 'so.*ing'")
assert(MESSAGE FATAL_ERROR "expected string 'some string' not to match 'so.*ing'")

mock_message()
assert("${VALUE}" MATCHES "so.*other.*ing")
end_mock_message()
assert_message(FATAL_ERROR "expected string 'some string' to match 'so.*other.*ing'")
assert(MESSAGE FATAL_ERROR "expected string 'some string' to match 'so.*other.*ing'")
endforeach()
endfunction()

Expand All @@ -107,14 +107,14 @@ function("String equality assertions")
mock_message()
assert("${LEFT_VALUE}" STREQUAL "${RIGHT_VALUE}")
end_mock_message()
assert_message(FATAL_ERROR "expected string 'some string' to be equal to 'some other string'")
assert(MESSAGE FATAL_ERROR "expected string 'some string' to be equal to 'some other string'")
endforeach()

foreach(RIGHT_VALUE STRING_VAR "${STRING_VAR}")
mock_message()
assert(NOT "${LEFT_VALUE}" STREQUAL "${RIGHT_VALUE}")
end_mock_message()
assert_message(FATAL_ERROR "expected string 'some string' not to be equal to 'some string'")
assert(MESSAGE FATAL_ERROR "expected string 'some string' not to be equal to 'some string'")
endforeach()
endforeach()
endfunction()
Expand All @@ -127,6 +127,27 @@ function(call_sample_messages)
message(ERROR "some other error message")
endfunction()

function("Message assertions")
mock_message()
call_sample_messages()
end_mock_message()

assert(MESSAGE WARNING "some warning message")
assert(MESSAGE WARNING "some other warning message")
assert(MESSAGE ERROR "some error message")
assert(MESSAGE FATAL_ERROR "some fatal error message")

mock_message()
assert(MESSAGE ERROR "some other error message")
end_mock_message()
assert(MESSAGE FATAL_ERROR "expected error message '' to be equal to 'some other error message'")

mock_message()
assert(MESSAGE SOME_MODE)
end_mock_message()
assert(MESSAGE FATAL_ERROR "usage: assert(MESSAGE <MODE> <EXPECTED_MESSAGE>)")
endfunction()

function("Mock message")
mock_message()
call_sample_messages()
Expand All @@ -144,36 +165,20 @@ function("Mock message")
assert("${FATAL_ERROR_MESSAGES}" STREQUAL "some fatal error message")
endfunction()

function("Assert messages")
mock_message()
call_sample_messages()
end_mock_message()

assert_message(WARNING "some warning message")
assert_message(WARNING "some other warning message")
assert_message(ERROR "some error message")
assert_message(FATAL_ERROR "some fatal error message")

mock_message()
assert_message(ERROR "some other error message")
end_mock_message()
assert_message(FATAL_ERROR "expected error message '' to be equal to 'some other error message'")
endfunction()

function("Assert successful process execution")
assert_execute_process("${CMAKE_COMMAND}" -E true)

mock_message()
assert_not_execute_process("${CMAKE_COMMAND}" -E true)
end_mock_message()
assert_message(FATAL_ERROR "expected command '${CMAKE_COMMAND} -E true' to fail (exit code: 0)")
assert(MESSAGE FATAL_ERROR "expected command '${CMAKE_COMMAND} -E true' to fail (exit code: 0)")
endfunction()

function("Assert failed process execution")
mock_message()
assert_execute_process("${CMAKE_COMMAND}" -E false)
end_mock_message()
assert_message(FATAL_ERROR "expected command '${CMAKE_COMMAND} -E false' not to fail (exit code: 1)")
assert(MESSAGE FATAL_ERROR "expected command '${CMAKE_COMMAND} -E false' not to fail (exit code: 1)")

assert_not_execute_process("${CMAKE_COMMAND}" -E false)
endfunction()
Expand All @@ -197,15 +202,15 @@ function("Assert non-matching process execution output")
EXPECTED_OUTPUT "Hi.*!"
)
end_mock_message()
assert_message(FATAL_ERROR "expected the output of command '${CMAKE_COMMAND} -E echo Hello world!' to match 'Hi.*!'")
assert(MESSAGE FATAL_ERROR "expected the output of command '${CMAKE_COMMAND} -E echo Hello world!' to match 'Hi.*!'")

mock_message()
assert_not_execute_process(
"${CMAKE_COMMAND}" -E invalid
EXPECTED_OUTPUT "CMake Error:.*Unavailable commands:"
)
end_mock_message()
assert_message(FATAL_ERROR "expected the output of command '${CMAKE_COMMAND} -E invalid' to match 'CMake Error:.*Unavailable commands:'")
assert(MESSAGE FATAL_ERROR "expected the output of command '${CMAKE_COMMAND} -E invalid' to match 'CMake Error:.*Unavailable commands:'")
endfunction()

cmake_language(CALL "${TEST_COMMAND}")

0 comments on commit bd84d80

Please sign in to comment.