Coco has strict checks to detect that the coverage data is coherent with the source code. It is, for example, not possible to import an execution report (
.csexe file) of an earlier project version or to import the coverage information of an old version into a newer instrumentation database (
.csmes file). This prevents some usage errors and the generation of incoherent test metrics.
Coherence analysis includes verifying that every instrumented source file in the project is not modified. This is done during the build and when coverage data are imported or merged. If the C preprocessor produces different files across the build – which can occur when some files are built in debug mode and others in release mode – Coco detects it, adds a suffix like
#2 to the file name, and requires that both versions are tested to achieve full coverage.
It is possible to compile a program on several platforms and then merge the coverage data. This requires that the source code is identical for each build. If that is not the case, Coco refuses to merge.
We use a small example to illustrate how this works. The project consists of only one source file,
project.cpp, and we build it on Microsoft® Windows and Linux™.
On Linux, we compile the project with the command:
$ csg++ /home/me/project.cpp -o project-unix
project-unix.csmes file is generated and the tests can be executed and imported as usual into it.
On Windows, we compile the project with the command:
C:\code> cscl C:\Home\me\project.cpp /Feproject-windows.exe
project-windows.exe.csmes file is generated.
Merging the coverage information is possible with cmmerge:
$ cmmerge -o project.csmes project-unix.csmes project-windows.exe.csmes
Unfortunately, this operation is not enough because the file
project.csmes will then contain two
It is necessary to tell Coco that both files are the same. To do that, we use cmedit to change two absolute file names to an identical one:
$ cmedit project.csmes --rename="/home/me/,/PRJ/" --rename="C:\Home\me\,/PRJ/" --verbose
These two rules rename the base directories
/PRJ/ to a single source file:
/PRJ/project.cpp. The coverage information from both platforms can now be merged.
In some build processes, code generators are used, like
bison or, for Qt products, Meta-Object Compiler (moc). Then the code generators need to produce identical source code on each platform to make the editing work.
If this is not the case, cmedit will refuse the renaming operation because it assumes that the project is not produced from the same source code. The solution is then to skip explicitly the files that are automatically generated.
Let's consider the case of
qmake generates files with the name
moc_*.cpp. The trick could consist of using the switch
--force which skips the renaming operation for files with conflicts:
$ cmedit project.csmes --force --rename="/home/me/,/PRJ/" --rename="C:\Home\me\,/PRJ/" --verbose
As result, all source files are merged together in a directory
PRJ except the moc files on which a conflict is detected. These moc files need then to be covered separately on each platforms.
Platform dependent macros
In general, C macros expand to platform dependent code and should therefore be avoided. If macro expansions are different between the platforms, Coco will create duplicates by appending a
#2 to the source files. Both versions of the sources need then to be covered.
There are some common pitfalls that you need to know to avoid conflicts:
__FILE__macro can generate unwanted differences because it may contain the absolute source file name. To solve this issue, since this macro is often used in asserts, the easiest solution is simply to work with the release build. Another solution is to ensure that the source file names passed to the compiler are not absolute file names. In this case, on most platforms
__FILE__is not expended to be the source's absolute path.
NULLmacro may also be different on each platform. Sometimes it is expanded as
(void*)0and sometimes as
__null. The proper solution is to avoid the comparison with
NULLand to use the C++ extension