You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9.6 KiB

CMake Tests/RunCMake Directory
******************************

This directory contains tests that run CMake and/or other tools while
precisely checking their return code and stdout/stderr content.
The RunCMake infrastructure is useful for testing error cases and
diagnostic output.

See also `../README.rst`_ and the `CMake Source Code Guide`_.

.. _`../README.rst`: ../README.rst
.. _`CMake Source Code Guide`: ../../Help/dev/source.rst
.. _`CMakeLists.txt`: CMakeLists.txt

Adding a Test
=============

To add a test:

1. Add a subdirectory named for the test, say ``<test>/``.

2. In `CMakeLists.txt`_ call ``add_RunCMake_test`` and pass the
test directory name ``<test>``.

3. Create script ``<test>/RunCMakeTest.cmake`` in the directory containing::

include(RunCMake)
run_cmake(Case1)
...
run_cmake(CaseN)

where ``Case1`` through ``CaseN`` are case names each corresponding to
an independent CMake run and project configuration.

One may also add calls of the form::

run_cmake_command(CaseI ${CMAKE_COMMAND} ...)

to fully customize the test case command-line.

Alternatively, if the test is to cover running ``ctest -S`` then use::

include(RunCTest)
run_ctest(Case1)
...
run_ctest(CaseN)

and create ``test.cmake.in``, ``CTestConfig.cmake.in``, and
``CMakeLists.txt.in`` files to be configured for each case.

Alternatively, if the test is to cover running ``cpack -G`` then use::

include(RunCPack)
run_cpack(Sample1)
...
run_cpack(SampleN)

where ``Sample1`` through ``SampleN`` are sample project directories
in the ``RunCPack/`` directory adjacent to this file.

4. Create file ``<test>/CMakeLists.txt`` in the directory containing::

cmake_minimum_required(...)
project(${RunCMake_TEST} NONE) # or languages needed
include(${RunCMake_TEST}.cmake)

where ``${RunCMake_TEST}`` is literal. A value for ``RunCMake_TEST``
will be passed to CMake by the ``run_cmake`` macro when running each
case.

5. Create a ``<test>/<case>.cmake`` file for each case named
above containing the actual test code. Optionally create files
containing expected test results:

``<case>-result.txt``
Regex matching expected process result, if not ``0``
``<case>-stdout.txt``
Regex matching expected stdout content
``<case>-stderr.txt``
Regex matching expected stderr content, if not ``^$``
``<case>-check.cmake``
Custom result check.

To specify platform-specific matches, create files of the form
``<case>-{stdout,stderr}-<platform_lower_case>.txt``.

Note that trailing newlines will be stripped from actual and expected
test output before matching against the stdout and stderr expressions.
The code in ``<case>-check.cmake`` may use the `RunCMake Variables`_.
On failure the script must store a message in ``RunCMake_TEST_FAILED``.
The check script may optionally set ``RunCMake_TEST_FAILURE_MESSAGE``
with additional text to be included in the message if the test fails.

RunCMake Commands
=================

A ``RunCMakeTest.cmake`` script, after ``include(RunCMake)``, may use
the following commands.

``run_cmake(<case>)``
Run CMake or another command and check expected results described by
``<case>-{result,stdout,stderr}.txt`` and ``<case>-check.cmake``.
The command is executed by a call of the form::

execute_process(
COMMAND ${RunCMake_TEST_COMMAND} ${RunCMake_TEST_OPTIONS}
WORKING_DIRECTORY &#34;${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}&#34;
[TIMEOUT &#34;${RunCMake_TEST_TIMEOUT}&#34;]
...
)

Behavior may be customized by setting `RunCMake Variables`_ before
the call.

``run_cmake_command(<case> <command> <args>...)``
Sets ``RunCMake_TEST_COMMAND`` to ``<command>;<args>...``
and calls ``run_cmake(<case>)``.

This is useful to run an arbitrary command.

``run_cmake_script(<case> <args>...)``
Sets ``RunCMake_TEST_COMMAND`` to
``${CMAKE_COMMAND};<args>...;-P;${RunCMake_SOURCE_DIR}/<case>.cmake``
and calls ``run_cmake(<case>)``.

This is useful to run CMake in script mode without configuring a project.

``run_cmake_with_options(<case> <opts>...)``
Sets ``RunCMake_TEST_OPTIONS`` to ``<opts>...``
and calls ``run_cmake(<case>)``.

``run_cmake_with_raw_args(<case> &#34;<args>&#34;)``
Calls ``run_cmake(<case>)`` with the underlying ``execute_process()``
call extended with the content of ``<args>`` treated as literal source
code of CMake language command arguments::

execute_process(
COMMAND ${RunCMake_TEST_COMMAND} ${RunCMake_TEST_OPTIONS} <args>
...
)

This is useful to pass arguments to the test command that cannot be
encoded in CMake language ``;``-separated lists.

RunCMake Variables
==================

The behavior of `RunCMake Commands`_ such as ``run_cmake()`` may be
customized by setting the following variables before a call.

``RunCMake_GENERATOR``
CMake generator to use when configuring projects.
This provided to ``RunCMakeTest.cmake`` scripts automatically
when they are executed, based on the CMake generator used to
configure the test suite.

For some generators, additional variables are also provided:

``RunCMake_GENERATOR_PLATFORM``
Specifies the ``CMAKE_GENERATOR_PLATFORM``.

``RunCMake_GENERATOR_TOOLSET``
Specifies the ``CMAKE_GENERATOR_TOOLSET``.

``RunCMake_GENERATOR_INSTANCE``
Specifies the ``CMAKE_GENERATOR_INSTANCE``.

``RunCMake_GENERATOR_IS_MULTI_CONFIG``
Boolean value indicating whether ``${RunCMake_GENERATOR}`` is a
multi-config generator.
This provided to ``RunCMakeTest.cmake`` scripts automatically
when they are executed, based on the CMake generator used to
configure the test suite.

``RunCMake_SOURCE_DIR``
Absolute path to the ``Tests/RunCMake/<test>`` directory in
the CMake source tree. This provided to ``RunCMakeTest.cmake``
scripts automatically when they are executed.

``RunCMake_BINARY_DIR``
Absolute path to the ``Tests/RunCMake/<test>`` directory in
the CMake binary tree. This provided to ``RunCMakeTest.cmake``
scripts automatically when they are executed.

``RunCMake_TEST_SOURCE_DIR``
Absolute path to the individual test case&#39;s source tree.
If not set, defaults to ``${RunCMake_SOURCE_DIR}``.

``RunCMake_TEST_BINARY_DIR``
Absolute path to the individual test case&#39;s binary tree.
If not set, defaults to ``${RunCMake_BINARY_DIR}/<case>-build``.

``RunCMake_TEST_NO_CLEAN``
Boolean value indicating whether ``run_cmake(<case>)`` should remove the
``${RunCMake_TEST_BINARY_DIR}`` directory before running the test case.
If not set, or if set to a false value, the directory is removed.

This is useful to run `Multi-Step Test Cases`_.

``RunCMake_TEST_COMMAND``
The command for ``run_cmake(<case>)`` to execute.
If not set, defaults to running CMake to generate a project::

${CMAKE_COMMAND} ${RunCMake_TEST_SOURCE_DIR} \
-G ${RunCMake_GENERATOR} ... -DRunCMake_TEST=<case>

``RunCMake_TEST_COMMAND_WORKING_DIRECTORY``
The working directory in which ``run_cmake(<case>)`` to execute its command.
If not set, defaults to ``${RunCMake_TEST_BINARY_DIR}``.

``RunCMake_TEST_OPTIONS``
Additional command-line options for ``run_cmake(<case>)`` to pass to
CMake when configuring a project with a default ``RunCMake_TEST_COMMAND``.
If not set, defaults to empty.
If ``RunCMake_TEST_COMMAND`` is set, ``RunCMake_TEST_OPTIONS`` is forced
to empty.

``RunCMake_TEST_OUTPUT_MERGE``
Boolean value indicating whether ``run_cmake(<case>)`` should redirect
the test process&#39;s ``stderr`` into its ``stdout``.

``RunCMake_TEST_TIMEOUT``
Specify a timeout, in seconds, for ``run_cmake(<case>)`` to pass to its
underlying ``execute_process()`` call using the ``TIMEOUT`` option.

Multi-Step Test Cases
=====================

Normally each ``run_cmake(<case>)`` call corresponds to one standalone
test case with its own build tree. However, some test cases may require
multiple steps to be performed in a single build tree. This can be
achieved as follows::

block()
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/example-build)
run_cmake(example)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(example-build ${CMAKE_COMMAND} --build . --config Debug)
endblock()

In this example, ``block() ... endblock()`` is used to isolate the
variable settings from later cases. A single build tree is used for
all cases inside the block. The first step cleans the build tree and
runs CMake to configure the case&#39;s project. The second step runs
``cmake --build`` to drive the generated build system and merges the
build tool&#39;s ``stderr`` into its ``stdout``. Note that each call uses
a unique case name so that expected results can be expressed individually.

Running a Test
==============

Each call to ``add_RunCMake_test(Example)`` in `CMakeLists.txt`_ creates
a test named ``RunCMake.Example`` that may be run with ``ctest``::

$ ctest -R &#34;^RunCMake\.Example$&#34;

To speed up local testing, you can choose to run only a subset of
``run_cmake()`` tests in a ``RunCMakeTest.cmake`` script by using the
``RunCMake_TEST_FILTER`` environment variable. If this variable is set,
it is treated as a regular expression, and any tests whose names don&#39;t
match the regular expression are not run. For example::

$ RunCMake_TEST_FILTER=&#34;^example&#34; ctest -R &#39;^RunCMake\.Example$&#39;

This will only run cases in ``RunCMake.Example`` that start with
``example``.

To speed up the process of creating a new ``RunCMake`` test, you can run a
script that will automatically perform steps 1 through 4 for you::

cmake -DRunCMake_TEST_SUITE=<test suite="" name=""> -P Tests/RunCMake/AddRunCMakeTestSuite.cmake

Be sure to run this from the top-level CMake source directory.