expcov - Code coverage analyzer based on clang

expcov is a clang-based compiler. It generates executable which can collect coverage data and create HTML reports.
expcov means 'expression coverage'. that can analyze source code by each expression.
General coverage analyzers such as gcov can only analyze by each line.
If many expressions exists at one line, gcov will treat them as one processing unit.

gcov versus expcov
gcov expcov

Demo

You can try expcov by online demo page.
News:
2022/12/01 - Update compiler on demo page. Fixed a problem that could cause MC/DC coverage to be measured incorrectly.
2022/11/08 - Update MC/DC description.
2022/06/25 - Update compiler on demo page.
2022/05/26 - Server moved to Amazon EC2.
2016/10/15 - Update demo page.

System specifications
ComponentSpec.
CPUIntel® Xeon® Processor
OSLinux 5.15 (Ubuntu)
Memory1GB
Compilerexpcov based on clang 14.0.5

Demo limits
ItemLimits
Source file1 file
Processing time5 seconds
Memory allocation8MB
File generation1MB
System callsDisallow fork, exec, mkdir, socket, ...
FunctionDisable SIGSEGV/SIGBUS detection

Features

Expression coverage

Appearance Meaning
= b The expression was executed.
= b The expression was not executed.
= b Excluded expression from code coverage.
< b The expression was executed.
The result was ever been set to true once or more.
The result was ever been set to false once or more.
< b The expression was executed.
The result was ever been set to true once or more.
The result was never been set to false.
< b The expression was executed.
The result has never been set to true.
The result was ever been set to false once or more.
< b The expression was not executed.

MC/DC coverage

expcov can analyze logical expression that independently affect the decision's outcome.


Appearance Meaning
<TF 0 && b <TF 1 for example: a = 1, b = 2

The expression a < 0 was executed.
a was ever greater than or equal to 0 once or more. If the value on the left side of logical-and is false, this expression affects the decision independently.
a was never been less than 0.
The expression && was executed.
The decision's outcome was never been set to true.
The decision's outcome was ever been set to false once or more.
The expression b < 1 was not executed due to short circuit evaluation.
<TF 0 && b <TF 1 for example: a = -1, b = 2

The expression a < 0 was executed.
a was ever less than 0 once or more.
a was never been greater than or equal to 0.
The expression && was executed.
The decision's outcome was never been set to true.
The decision's outcome was ever been set to false once or more.
The expression b < 1 was executed.
b was ever greater than or equal to 1 once or more. If the value on the left side of logical-and is true, right side of logical-and evaluated as false affects the decision independently.
b was never been less than 1.
<TF 0 && b <TF 1 for example: a = -1, b = 0

The expression a < 0 was executed.
a was ever less than 0 once or more. If the value on the right side of logical-and is true, left side of logical-and evaluated as true affects the decision independently.
a was never been greater than or equal to 0.
The expression && was executed.
The decision's outcome was ever been set to true once or more.
The decision's outcome was never been set to false.
The expression b < 1 was executed.
b was ever been less than 1 once or more. If the value on the left side of logical-and is true, right side of logical-and evaluated as true affects the decision independently.
b was never greater than or equal to 1.
<TF 0 && b <TF 1 All patterns covered, MC/DC was satisfied.

Appearance Meaning
<TF 0 || b <TF 1 for example: a = -1, b = 2

The expression a < 0 was executed.
a was ever less than 0 once or more. The value true on the left side of logical-or affects the decision independently.
a was never been greater than or equal to 0.
The expression || was executed.
The decision's outcome was ever been set to true once or more.
The decision's outcome was never been set to false.
The expression b < 1 was not executed due to short circuit evaluation.
<TF 0 || b <TF 1 for example: a = 1, b = 2

The expression a < 0 was executed.
a was ever greater than or equal to 0 once or more. If the value on the right side of logical-or is false, left side of logical-or evaluated as false affects the decision independently.
a was never been less than 0.
The expression || was executed.
The decision's outcome was never been set to true.
The decision's outcome was ever been set to false once or more.
The expression b < 1 was executed.
b was ever greater than or equal to 1 once or more. If the value on the left side of logical-or is false, right side of logical-or evaluated as false affects the decision independently.
b was never been less than 1.
<TF 0 || b <TF 1 for example: a = 1, b = 0

The expression a < 0 was executed.
a was ever greater than or equal to 0 once or more.
a was never been less than 0.
The expression || was executed.
The decision's outcome was ever been set to true once or more.
The decision's outcome was never been set to false.
The expression b < 1 was executed.
b was ever less than 1 once or more. If the value on the left side of logical-or is false, right side of logical-or evaluated as true affects the decision independently.
b was never been greater than or equal to 1.
<TF 0 || b <TF 1 All patterns covered, MC/DC was satisfied.

HTML report

The executable which compiled by expcov can collect coverage data and generates HTML reports.
It creates a coverage data file when a program exit.
If you execute program with environment variable 'EXPCOV_REPORT', it generates HTML reports and exits program immediately.

Source codes have been included in executable. you can set a password for encrypt them.

When you use Firefox 37 or older version, you need to install
'HTML Ruby' plugin.
Sample: Dhrystone(new window)
Sample: Apache(new window)

Enter/Leave analysis

expcov can analyze enter/leave count in some types of expression.

Threading support

expcov can work in a multi threaded application.
gcov expcov

Performance

Compiler gcc 4.8.2 gcc 4.8.2 gcc 4.8.2 gcc 4.8.2 clang 3.2 clang 3.2 expcov(clang) expcov(clang) expcov(clang) expcov(clang)
Optimize
Coverage
Multi-thread suport
Compile option -O2 -fprofile-arcs
-ftest-coverage
-fprofile-arcs
-ftest-coverage
-O2
-O2 --expcov --expcov
-O2
--expcov
--expcov-singlethread
--expcov
--expcov-singlethread
-O2
Metrics - - 134 lines
46 branches
29 calls
134 lines
46 branches
29 calls
- - 13 functions
178 expressions
23(46) branches
13 functions
178 expressions
23(46) branches
13 functions
178 expressions
23(46) branches
13 functions
178 expressions
23(46) branches
Dhrystone(1.1)
Core2 Duo 2.66GHz
6289473 28571428 6172996 23255813 5272439 30303030 330943 416614 1888163 5825286
Speed 100.00% 454.27% 98.14% 369.75% 83.82% 481.80% 5.26% 6.62% 30.02% 92.61%

How to use

  1. Write source code
    test1.c
    #include <stdio.h>
    
    void message()
    {
    	printf("Hello, world\n");
    }
    

    test2.c
    #include <stdio.h>
    
    void message();
    
    int main(int argc, char *argv[])
    {
    	message();
    	return 0;
    }
    

  2. Compile source code with '--expcov' option.
    clang --expcov -c test1.c
    clang --expcov -c test2.c
    

  3. Link object file with '--expcov' option.
    clang --expcov test1.o test2.o -o test
    

  4. Execute program.
    ./test
    
    The program 'test' generates coverage data file 'test.cov' when exit.

  5. Execute program with environment variable 'EXPCOV_REPORT'.
    EXPCOV_REPORT=1 ./test
    
    The program 'test' generates HTML reports and exit program immediately;

Compare coverage tools

Featuresexpcovgcovlcov
Coverage unitExpressionLineLine
Compilerclang-basedgccgcc
Librarylibexpcovlibgcovlibgcov
Coverage data fileappname + .cov
(1 file)
sourcename + .gcno
sourcename + .gcda
sourcename + .gcno
sourcename + .gcda
Bit width of counter64bit32bit32bit
Report formatHTMLPlain textHTML
C0 metrics
C1 metrics
C2 metrics---
MC/DC metrics--
Threading support--
Enter/Leave analysis--
SIGSEGV/SIGBUS detection--
Separation of the last result--

Contact

Kenji Koyanagi


Copyright © 2009-2022 Kenji Koyanagi All rights reserved.