mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
Add a `CMAKE` value for the `CoverageTool` setting, next to `LLVM-COV`. With it, ctest gives each test its own scratch folder, `<test-name>_cmake-coverage`, next to the `CTestTestfile.cmake` that describes the test, and runs the test with CMAKE_LISTFILE_COVERAGE_DIR set to that folder. An ambient value of the variable is replaced. Before the test, ctest removes the folder and the merged file of an earlier run. After the test, ctest merges the tracefiles in the folder into one `<test-name>.cmake-coverage.info` file with a `TN:` record, and removes the folder. Coverage problems are warnings and never change the test result: a folder that cannot be created, an unreadable file, a merged file that cannot be written, and a test that timed out. The folder is kept for inspection when a file was skipped or the write failed. The merge leaves out the files under ctest's build directory, such as generated files and `try_compile` projects, unless the build directory is the source directory. If no file is left, the test gets no merged file, as for a test that runs no CMake code. ctest now also records coverage of the CMake code that it runs itself, such as `CTestTestfile.cmake` files and dashboard scripts, when CMAKE_LISTFILE_COVERAGE_DIR is set at startup. ctest reads the top `CTestTestfile.cmake` by a relative path, so the collector now makes a relative listfile path absolute with the current working directory. Document the tool and add a recipe for CMake's own test suite to `Tests/RunCMake/README.rst`. Issue: #28192
89 lines
3.2 KiB
C++
89 lines
3.2 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#pragma once
|
|
|
|
#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "cmLcovTracefile.h"
|
|
|
|
class cmListFileFunction;
|
|
|
|
/** \class cmListFileCoverage
|
|
* \brief Record line hits and function calls of CMake listfiles.
|
|
*
|
|
* The environment variable CMAKE_LISTFILE_COVERAGE_DIR turns the collector
|
|
* on. One collector exists per process. At exit it writes one lcov
|
|
* tracefile into that directory. CMake runs listfile code on one thread,
|
|
* so the collector does no locking.
|
|
*/
|
|
class cmListFileCoverage
|
|
{
|
|
public:
|
|
/** Read CMAKE_LISTFILE_COVERAGE_DIR. Unset or empty: coverage stays off,
|
|
returns true. Otherwise check the path, create the directory, and
|
|
test that a file can be written there. On failure return false and
|
|
set error to the message text, without the "CMake Error: " prefix.
|
|
A second call while coverage is on does nothing and returns true. */
|
|
static bool Start(std::string& error);
|
|
|
|
/** The collector, or nullptr while coverage is off. */
|
|
static cmListFileCoverage* Get();
|
|
|
|
/** Write the tracefile if any registered file has a line or a
|
|
function. Ignore write failures. Turn coverage off. */
|
|
static void Finish();
|
|
|
|
/** While alive, CommandRan(lff, ...) ignores this exact object. Used
|
|
where one command builds another on its own line. */
|
|
class SyntheticCommandScope
|
|
{
|
|
public:
|
|
explicit SyntheticCommandScope(cmListFileFunction const& lff);
|
|
~SyntheticCommandScope();
|
|
|
|
SyntheticCommandScope(SyntheticCommandScope const&) = delete;
|
|
SyntheticCommandScope& operator=(SyntheticCommandScope const&) = delete;
|
|
|
|
private:
|
|
cmListFileFunction const* Command = nullptr;
|
|
};
|
|
|
|
/** Register the executable lines and the function and macro definitions
|
|
of a parsed file. A second call for the same path adds new lines and
|
|
functions and keeps existing counts. A relative path, as ctest uses
|
|
for its top CTestTestfile.cmake, is made absolute with the current
|
|
working directory, here and in CommandRan and FunctionCalled. */
|
|
void FileParsed(std::string const& path,
|
|
std::vector<cmListFileFunction> const& functions);
|
|
|
|
/** Count a hit on a line of a registered file. */
|
|
void CommandRan(cmListFileFunction const& lff, std::string const& path,
|
|
long line);
|
|
|
|
/** Count a call of the function or macro defined on a line of a
|
|
registered file. */
|
|
void FunctionCalled(std::string const& path, long definitionLine);
|
|
|
|
/** The recorded data, with no test name. */
|
|
cmLcovTracefile ToTracefile() const;
|
|
|
|
/** The sorted, unique start lines of the commands that count. */
|
|
static std::vector<long> ExecutableLines(
|
|
std::vector<cmListFileFunction> const& functions);
|
|
|
|
private:
|
|
explicit cmListFileCoverage(std::string outputPath);
|
|
|
|
std::map<std::string, cmLcovSourceFile>::iterator FindFile(
|
|
std::string const& path);
|
|
|
|
std::string OutputPath;
|
|
std::map<std::string, cmLcovSourceFile> Files;
|
|
std::set<cmListFileFunction const*> SyntheticCommands;
|
|
};
|