Skip to content

Commit

Permalink
feat: add option to specify predefined variables in script tests (#248)
Browse files Browse the repository at this point in the history
* feat: add `DEFINES` option to the `add_cmake_script_test` function

Signed-off-by: Alfi Maulana <alfi.maulana.f@gmail.com>

* test: refactor `add_cmake_script_test.cmake` and add support to test `DEFINES` option

Signed-off-by: Alfi Maulana <alfi.maulana.f@gmail.com>

* docs: update example for the `add_cmake_script_test` function

Signed-off-by: Alfi Maulana <alfi.maulana.f@gmail.com>

---------

Signed-off-by: Alfi Maulana <alfi.maulana.f@gmail.com>
  • Loading branch information
threeal authored Oct 16, 2024
1 parent fe4dfe3 commit f6f1bf3
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 42 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,26 @@ This variable contains the version of the included `Assertion.cmake` module.
Adds a new test that processes the given CMake file in script mode.

```cmake
add_cmake_script_test(<file> [NAME <name>])
add_cmake_script_test(<file> [NAME <name>] [DEFINES <variables>...])
```

This function adds a new test that processes the given `<file>` in script mode.
If `NAME` is specified, it will use `<name>` as the test name; otherwise, it
will use `<file>`.

If `DEFINES` is specified, the script is processed with predefined variables
listed in `<variables>...`. Each entry in `<variables>...` should be in the
format `<name>=<value>`, where `<name>` is the variable name and `<value>` is
the variable value.

#### Example

```cmake
add_cmake_script_test(test/first_test.cmake)
add_cmake_script_test(test/second_test.cmake NAME "Second Test")
add_cmake_script_test(test_foo.cmake NAME "Test Foo" DEFINES FOO=foo BAR=bar)
```

The above example adds two new tests. The first one is named
`test/first_test.cmake`, which will process the file with the same name as the
test. The second one is named `Second Test`, which will process the
`test/second_test.cmake` file.
The example above adds a new test named `Test Foo`, which processes the
`test_foo.cmake` file in script mode with predefined `FOO` and `BAR` variables.

### `fail`

Expand Down
17 changes: 14 additions & 3 deletions cmake/Assertion.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ set(ASSERTION_VERSION 2.0.0)

# Adds a new test that processes the given CMake file in script mode.
#
# add_cmake_script_test(<file> [NAME <name>])
# add_cmake_script_test(<file> [NAME <name>] [DEFINES <variables>...])
#
# This function adds a new test that processes the given `<file>` in script
# mode. If `NAME` is specified, it will use `<name>` as the test name;
# otherwise, it will use `<file>`.
#
# If `DEFINES` is specified, the script is processed with predefined variables
# listed in `<variables>...`. Each entry in `<variables>...` should be in the
# format `<name>=<value>`, where `<name>` is the variable name and `<value>` is
# the variable value.
function(add_cmake_script_test FILE)
cmake_parse_arguments(PARSE_ARGV 1 ARG "" NAME "")
cmake_parse_arguments(PARSE_ARGV 1 ARG "" NAME DEFINES)

if(NOT DEFINED ARG_NAME)
set(ARG_NAME "${FILE}")
Expand All @@ -42,7 +47,13 @@ function(add_cmake_script_test FILE)
message(SEND_ERROR "Cannot find test file:\n ${FILE}")
endif()

add_test(NAME "${ARG_NAME}" COMMAND "${CMAKE_COMMAND}" -P ${FILE})
set(TEST_COMMAND "${CMAKE_COMMAND}")
foreach(DEFINE IN LISTS ARG_DEFINES)
list(APPEND TEST_COMMAND -D "${DEFINE}")
endforeach()
list(APPEND TEST_COMMAND -P "${FILE}")

add_test(NAME "${ARG_NAME}" COMMAND ${TEST_COMMAND})
endfunction()

# Throws a formatted fatal error message.
Expand Down
58 changes: 27 additions & 31 deletions test/add_cmake_script_test.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ cmake_minimum_required(VERSION 3.24)
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/Assertion.cmake
RESULT_VARIABLE ASSERTION_LIST_FILE)

set(CMAKELISTS_HEADER
"cmake_minimum_required(VERSION 3.24)\n"
"project(Sample LANGUAGES NONE)\n"
"include(${ASSERTION_LIST_FILE})\n"
"enable_testing()\n")


file(REMOVE_RECURSE project)
file(WRITE project/test.cmake "message(\"all ok\")\n")

section("it should create a new test")
file(WRITE project/CMakeLists.txt
"cmake_minimum_required(VERSION 3.24)\n"
"project(Sample LANGUAGES NONE)\n"
"\n"
"include(${ASSERTION_LIST_FILE})\n"
"\n"
"enable_testing()\n"
file(WRITE project/CMakeLists.txt ${CMAKELISTS_HEADER}
"add_cmake_script_test(test.cmake)\n")

assert_execute_process("${CMAKE_COMMAND}" --fresh -S project -B project/build)
Expand All @@ -23,13 +24,7 @@ endsection()

section("it should create a new test "
"with the file specified using an absolute path")
file(WRITE project/CMakeLists.txt
"cmake_minimum_required(VERSION 3.24)\n"
"project(Sample LANGUAGES NONE)\n"
"\n"
"include(${ASSERTION_LIST_FILE})\n"
"\n"
"enable_testing()\n"
file(WRITE project/CMakeLists.txt ${CMAKELISTS_HEADER}
"add_cmake_script_test(\${CMAKE_CURRENT_SOURCE_DIR}/test.cmake)\n")

assert_execute_process("${CMAKE_COMMAND}" --fresh -S project -B project/build)
Expand All @@ -38,33 +33,34 @@ section("it should create a new test "
endsection()

section("it should create a new test with the specified name")
file(WRITE project/CMakeLists.txt
"cmake_minimum_required(VERSION 3.24)\n"
"project(Sample LANGUAGES NONE)\n"
"\n"
"include(${ASSERTION_LIST_FILE})\n"
"\n"
"enable_testing()\n"
file(WRITE project/CMakeLists.txt ${CMAKELISTS_HEADER}
"add_cmake_script_test(test.cmake NAME \"a test\")\n")

assert_execute_process("${CMAKE_COMMAND}" --fresh -S project -B project/build)
assert_execute_process(
ctest --test-dir project/build -R "^a test$" --no-tests=error)
endsection()

section("it should fail to create a new test due to a non-existing file")
file(WRITE project/CMakeLists.txt
"cmake_minimum_required(VERSION 3.24)\n"
"project(Sample LANGUAGES NONE)\n"
"\n"
"include(${ASSERTION_LIST_FILE})\n"
"\n"
"enable_testing()\n"
"add_cmake_script_test(invalid.cmake)\n")
file(WRITE project/test.cmake
"include(\"\${ASSERTION_LIST_FILE}\")\n"
"assert(FOO STREQUAL foo)\n")

section("it should create a new test with predefined variables")
file(WRITE project/CMakeLists.txt ${CMAKELISTS_HEADER}
"add_cmake_script_test(test.cmake\n"
" DEFINES ASSERTION_LIST_FILE=\${ASSERTION_LIST_FILE} FOO=foo)\n")

assert_execute_process("${CMAKE_COMMAND}" --fresh -S project -B project/build)
assert_execute_process(
ctest --test-dir project/build -R --no-tests=error)
endsection()

file(REMOVE project/test.cmake)

section("it should fail to create a new test due to a non-existent file")
assert_execute_process(
COMMAND "${CMAKE_COMMAND}" --fresh -S project -B project/build
ERROR "Cannot find test file:.*invalid.cmake")
ERROR "Cannot find test file:.*test.cmake")
endsection()

file(REMOVE_RECURSE project)

0 comments on commit f6f1bf3

Please sign in to comment.