I was working on a C++ project recently where gcov inexplicitly failed to report correct results, especially for template files. Some templated code was incorrectly being reported as not-covered by my tests. Instead of doing the right thing by finding out why gcov was not working with my source code, I decided to write a python script that combined the outputs of objdump and valgrind into a test coverage report. It worked well enough and I thought I would share it. Here is an extract of a test coverage report:
---------------------------------
File: HTTPmsg.h
Code not executed in: HTTPmsg<TCPfragmsg>::getContentEncoding() const
line no: 110
Code not executed in: HTTPmsg<TCPfragmsg>::DJBHash(char const*, char const*)
line no: 271
Code not executed in: HTTPmsg<TCPmsg>::isCandidateRequest() const
line no: 215
Code not executed in: HTTPmsg<TCPfragmsg>::isCandidateResponse() const
line no: 236 238 239 242 248 251 252
Code not executed in: HTTPmsg<TCPfragmsg>::getContentDirection() const
line no: 105
Compiled lines: 82, Not executed: 11
Code coverage: 86%
---------------------------------
The script can be found here: coverage
Tested on objdump (GNU Binutils for Ubuntu) 2.20.1 and valgrind-3.6.0.SVN-Debian.
Below, you can see the output of objdump and valgrind's for the 'isCandidateRequest' member function. The objdump output describes what code was compiled and the output of callgrind describes what code was executed. The script works by checking for common line numbers between them. Line numbers that appear in the object dump and not in the valgrind output are marked as non-executed source code.
objdump: 'isCandidateRequest' member function:
080e9498 <HTTPmsg<TCPmsg>::isCandidateRequest() const>:
_ZNK7HTTPmsgI6TCPmsgE18isCandidateRequestEv():
/projects/conduits/conduits/HTTPmsg.h:203
80e9498: 55 push %ebp
80e9499: 89 e mov %esp,%ebp
80e949b: 83 e28 sub $0x28,%esp
/projects/conduits/conduits/HTTPmsg.h:205
80e949e: 8b 45 08 mov 0x8(%ebp),%eax
80e94a1: 8b 80 e0 00 mov 0xe0(%eax),%eax
80e94a7: 85 c0 test %eax,%eax
80e94a9: 75 26 jne 80e94d1 <HTTPmsg<TCPmsg>::isCandidateRequest() const+0x39>
/projects/conduits/conduits/HTTPmsg.h:206
80e94ab: b9 00 00 00 00 mov $0x0,%ecx
80e94b0: a1 e8 7e 26 08 mov 0x8267ee8,%eax
80e94b5: 8b 15 ec 7e 26 mov 0x8267eec,%edx
80e94bb: 83 c0 01 add $0x1,%eax
80e94be: 83 d2 00 adc $0x0,%edx
/projects/conduits/conduits/HTTPmsg.h:215
80e9624: b9 00 00 00 00 mov $0x0,%ecx
80e9629: a1 20 7f 26 08 mov 0x8267f20,%eax
80e962e: 8b 15 24 7f 26 mov 0x8267f24,%edx
80e9634: 83 c0 01 add $0x1,%eax
80e9637: 83 d2 00 adc $0x0,%edx
80e963a: a3 20 7f 26 08 mov %eax,0x8267f20
Callgrind: 'isCandidateRequest' member function:
fn=HTTPmsg<TCPmsg>::isCandidateRequest() const
203 87
205 116
jcnd=29/29 206
205
206 174
Wednesday, March 02, 2011
Test Code Coverage with Objdump and Valgrind
Subscribe to:
Post Comments (Atom)
0 comments:
Post a Comment