{"id":1655,"date":"2012-02-12T09:59:07","date_gmt":"2012-02-12T08:59:07","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=1655"},"modified":"2012-02-12T09:59:07","modified_gmt":"2012-02-12T08:59:07","slug":"development-of-a-dynamic-library-33","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2012\/02\/12\/development-of-a-dynamic-library-33\/","title":{"rendered":"Development of a dynamic library (3\/3)"},"content":{"rendered":"<p style=\"text-align: justify;\">(version originale en fran\u00e7ais <a title=\"Mise au point de biblioth\u00e8que dynamique (3\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/02\/12\/mise-au-point-de-bibliotheque-dynamique-33\/\">ici<\/a>)<\/p>\n<p style=\"text-align: justify;\">In the two previous posts, we started the development of a dynamic library on Linux: the <a title=\"Development of a dynamic library (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/development-of-a-dynamic-library-13\/\" target=\"_blank\">first one<\/a> saw us building the library and managing version numbers using symbolic links, in the <a title=\"Development of a dynamic library (2\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/02\/04\/development-of-a-dynamic-library-23\/\" target=\"_blank\">second one<\/a> we traced library calls and did step-by-step debugging. Now we are interested in checking the coverage of the library.<\/p>\n<p>\n<!--more-->\n<\/p>\n<p style=\"padding-left: 60px; text-align: justify;\"><strong><em>Code coverage<\/em><\/strong> is a measure indicating the percentage of lines of code that were actually covered during a program execution. We can gradually expand the set of tests to obtain 100% coverage (and ensure that the code has been fully verified).<\/p>\n<p style=\"text-align: justify;\">The best known tool under Linux for code coverage is <code>gcov<\/code>, which instruments the source code and provide us detailed statistics after execution. It is easy to use it to verify coverage of a source file compiled into an executable. We will use it for library code which requires some more attention.<\/p>\n<h1>Compilation<\/h1>\n<p style=\"text-align: justify;\">Let&rsquo;s start with the same files and directories (grouped in <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-12\/factorial-3.tar.bz2\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-12\/factorial-3.tar.bz2\" target=\"_blank\">this archive<\/a>) as in the previous articles. A directory named \u00ab\u00a0<code>factorial<\/code>\u00a0\u00bb contains four subdirectories: <code>src<\/code>, <code>include<\/code> and <code>lib<\/code> respectively where the source files, header files and compiled files of the library are. The fourth sub-directory \u00ab\u00a0<code>test<\/code>\u00a0\u00bb contains the source and executable files of a program using our library <code>libfact<\/code>.<\/p>\n<pre>[~]$ <strong>cd factorial\/<\/strong>\n[factorial]$ <strong>ls<\/strong>\ninclude  lib  src  test\n[factorial]$ <strong>ls include\/<\/strong>\nfact.h\n[factorial]$ <strong>ls lib\/<\/strong>\nlibfact.so  libfact.so.2  libfact.so.2.0\n[factorial]$ <strong>ls src\/<\/strong>\nfact.c\n[factorial]$ <strong>ls test\/<\/strong>\nfactorial.c\n[factorial]$<\/pre>\n<p style=\"padding-left: 60px; text-align: justify;\">NB: The library was already compiled in the above example, but we will rebuild it.<\/p>\n<p style=\"text-align: justify;\">At first we will compile the library code, as in the first article, but adding the <code>--coverage<\/code> option of <code>gcc<\/code>. This option has two different roles:<\/p>\n<ul>\n<li style=\"text-align: justify;\">During compilation, it has the same meaning as <code>-fprofile-arcs<\/code> and <code>-ftest-coverage<\/code> options (which were used with the previous versions of <code>gcc<\/code>): the first one added instrumentation data to the executable code (counters), the second one created a table of correspondence between instructions blocks and lines of source code (in a file named after the source file with the extension <code>.gcno<\/code>)<\/li>\n<li style=\"text-align: justify;\">During linking, it is equivalent to <code>-lgcov<\/code> (which was added automatically by <code>-ftest-coverage<\/code>) that incorporates the necessary entry points for the subsequent use of <code>gcov<\/code>.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Here&rsquo;s the compilation of our library.<\/p>\n<pre>[factorial]$ <strong>gcc -c --coverage -fPIC -I include\/ -o .\/src\/fact.o .\/src\/fact.c <\/strong>\n[factorial]$ <strong>ls src\/<\/strong>\nfact.c  fact.gcno  fact.o\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">We see that with the <code>--coverage<\/code> option, the compilation generated, in addition to the <code>fact.o<\/code> object file, a <code>fact.gcno<\/code> file, containing the relationships between the blocks of code and the line numbers. We continue.<\/p>\n<pre>[factorial]$ <strong>gcc -shared -I include\/ -Wl,-soname,libfact.so.2 -o lib\/libfact.so.2.0 .\/src\/fact.o --coverage <\/strong>\n[factorial]$ <strong>ls -l lib\/<\/strong>\ntotal 20\nlrwxrwxrwx 1 cpb cpb    12 2012-02-11 13:39 libfact.so -&gt; libfact.so.2\nlrwxrwxrwx 1 cpb cpb    14 2012-02-11 13:39 libfact.so.2 -&gt; libfact.so.2.0\n-rwxrwxr-x 1 cpb cpb 16866 2012-02-11 17:10 libfact.so.2.0\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">We have rebuilt the <code>libfact.so.2.0<\/code> library. Symbolic links are used to manage the major and minor version numbers, as we saw in the <a title=\"Development of a dynamic library (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/development-of-a-dynamic-library-13\/\">first article<\/a>. Now compile an executable file, without <code>--coverage<\/code> option (or use the executable file of previous articles).<\/p>\n<pre>[factorial]$ <strong>gcc -I include\/ -L lib\/ -o test\/factorial test\/factorial.c -lfact<\/strong>\n[factorial]$ <strong>ls test\/<\/strong>\nfactorial  factorial.c\n[factorial]$<\/pre>\n<h1>Execution<\/h1>\n<p style=\"text-align: justify;\">Program execution takes place quite normally (although in practice it is slightly slower). We must, of course, set the environment variable <code>LD_LIBRARY_PATH<\/code> to specify where the dynamic linker will find the library needed to run the application.<\/p>\n<pre>[factorial]$ <strong>export LD_LIBRARY_PATH=lib\/<\/strong>\n[factorial]$ <strong>test\/factorial 4 5 6<\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorial]$ <strong>ls src\/<\/strong>\nfact.c  fact.gcda  fact.gcno  fact.o\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">A new file named <code>fact.gcda<\/code> appeared, containing the execution statistics for <code>fact.gcno<\/code> blocks of code (and block transitions).<\/p>\n<h1>Results<\/h1>\n<p style=\"text-align: justify;\">For information on the code coverage of a source file, we invoke <code>gcov<\/code> indicating the source file name. The results are computed independently for each source file of the application (or library).<\/p>\n<p style=\"text-align: justify;\">We will use the <code>-o<\/code> option of <code>gcov<\/code> to specify the directory name for the <code>.c<\/code>, <code>.gcno<\/code> and <code>.gcda<\/code> files.<\/p>\n<pre>[factorial]$ <strong>gcov -o src\/ fact.c<\/strong>\nFile 'src\/fact.c'\nLines executed:87.50% of 8\nsrc\/fact.c:creating 'fact.c.gcov'\n\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\"><code>gcov<\/code> tells us that we have only performed 87.5% of the eight lines of code in our function. What happened? We see that <code>gcov<\/code> also created a file named \u00ab\u00a0<code>fact.c.gcov<\/code>\u00a0\u00bb in which he puts a copy of our source code, numbering the lines, adding a header and a column of statistics at the beggining of the line.<\/p>\n<pre>[factorial]$ <strong>ls<\/strong>\nfact.c.gcov  include  lib  src  test\n[factorial]$ <strong>cat fact.c.gcov <\/strong>\n        -:    0:Source:src\/fact.c\n        -:    0:Graph:src\/fact.gcno\n        -:    0:Data:src\/fact.gcda\n        -:    0:Runs:1\n        -:    0:Programs:1\n        -:    1:#include\n        -:    2:\n        3:    3:int factorial(long int n, long long int * result)\n        -:    4:{\n        3:    5:    * result = 1;\n        3:    6:    if (n &lt; 0)\n   \u00a0#####:    7:        return -1;\n       \u00a0-:    8:    do {\n      \u00a012:    9:        (*result) = (*result) * n;\n      \u00a012:   10:        n = n - 1;\n      \u00a012:   11:    } while (n &gt; 1);\n        3:   12:    return 0;\n        -:   13:}\n        -:   14:\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">The header describes the files involved and the number of executions (only one here). The left column shows the number of passes on each line. Lines containing a dash \u00ab\u00a0&#8211;\u00a0\u00bb do not match any compiled code. We see that lines 3, 5, 6 and 12 were scanned three times (one invocation for each argument on the command line), and that lines 9, 10 and 11 were executed 12 times (iterations to calculate factorial).<\/p>\n<p style=\"text-align: justify;\">If we repeat the operation, the counters are cumulated.<\/p>\n<pre>[factorial]$ <strong>test\/factorial 3 8<\/strong>\n3! = 6\n8! = 40320\n[factorial]$ <strong>gcov -o src\/ fact.c<\/strong>\nFile 'src\/fact.c'\nLines executed:87.50% of 8\nsrc\/fact.c:creating 'fact.c.gcov'\n\n[factorial]$ <strong>cat fact.c.gcov <\/strong>\n        -:    0:Source:src\/fact.c\n        -:    0:Graph:src\/fact.gcno\n        -:    0:Data:src\/fact.gcda\n        -:    0:Runs:2\n        -:    0:Programs:1\n        -:    1:#include\n        -:    2:\n        5:    3:int factorial(long int n, long long int * result)\n        -:    4:{\n        5:    5:    * result = 1;\n        5:    6:    if (n &lt; 0)\n    #####:    7:        return -1;\n        -:    8:    do {\n       21:    9:        (*result) = (*result) * n;\n       21:   10:        n = n - 1;\n       21:   11:    } while (n &gt; 1);\n        5:   12:    return 0;\n        -:   13:}\n        -:   14:\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">But, what about line 7? Why these \u00ab\u00a0<code>#####<\/code>\u00ab\u00a0?<\/p>\n<p style=\"text-align: justify;\">Unlike spreadsheet programs, this symbol does not mean that the number is too large to fit in the column, but that the line (which corresponds to compiled code) was never executed. Two advantages with this notation:<\/p>\n<ul>\n<li style=\"text-align: justify;\">it attracts the eye better than a single \u00ab\u00a00\u00a0\u00bb would do,<\/li>\n<li style=\"text-align: justify;\">it allows us to do an automated search of unexecuted lines using <code>grep<\/code>.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Let&rsquo;s see:<\/p>\n<pre>[factorial]$ <strong>gcov -o src fact.c<\/strong>\nFile 'src\/fact.c'\nLines executed:87.50% of 8\nsrc\/fact.c:creating 'fact.c.gcov'\n\n[factorial]$ <strong>grep '#####' fact.c.gcov <\/strong>\n    #####:    7:        return -1;\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">The line number (7) being printed with the content, we can have a quick overview of non executed code.<\/p>\n<h1>Correction<\/h1>\n<p style=\"text-align: justify;\">We have detected a problem with our test library, since a branch was never executed. This may be due to different reasons.<\/p>\n<ul>\n<li style=\"text-align: justify;\">An incomplete tests set. This is the case here and we will fix it easily below.<\/li>\n<li style=\"text-align: justify;\">Legacy code that is never invoked again (dead code). It is important to make it disappear because it disrupts the maintenance of the program.<\/li>\n<li>Lines of code used to handle rare error cases, difficult to test. We will deal with this problem in the next paragraph.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Here the solution is simple: the uncovered line corresponds to an invocation of the function with a negative argument. It is easy to test.<\/p>\n<pre>[factorial]$ <strong>.\/test\/factorial -1<\/strong>\n-1! doesn't exist\n[factorial]$ <strong>gcov -o src fact.c<\/strong>\nFile 'src\/fact.c'\nLines executed:100.00% of 8\nsrc\/fact.c:creating 'fact.c.gcov'\n\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Now <code>gcov<\/code> tells us that all the lines of our program have been covered by our test set. This reduces the probability of remaining bug.<\/p>\n<h1>Error handling<\/h1>\n<p style=\"text-align: justify;\">A major difficulty to achieve 100% code coverage during software testing is to validate the behavior in case of system error.<\/p>\n<p style=\"text-align: justify;\">Take a look at a well-known system call: <code>malloc()<\/code>. We asked him to allocate a memory area of \u200b\u200ba certain size (given in bytes) and he returns a pointer. All documentation tell you that in case of lack of memory, <code>malloc()<\/code> returns a <code>NULL<\/code> pointer. (Although this case is particularly difficult to produce with Linux, we will discuss this in a future article). Also, the conscientious programmer will write something like.<\/p>\n<pre>    char * buffer;\n    buffer = malloc(BUFFER_SIZE);\n    if (buffer == NULL) {\n        display_error(\"Insufficient memory\");\n        register_error_code(-ENOMEM);\n        return -1;\n    }\n    \/\/ ...<\/pre>\n<p style=\"text-align: justify;\">Unfortunately the lines in between braces are difficult to test because we can not \u00ab\u00a0force\u00a0\u00bb <code>malloc()<\/code> to fail. The failure circumstances are based on too many parameters external to the application to be reproducible.<\/p>\n<p style=\"padding-left: 60px; text-align: justify;\">In the specific case of <code>malloc()<\/code>, the <code>Glibc<\/code> library provides us entry points that can be used to replace the function &#8211; see <code>malloc_hook(3)<\/code> &#8211; but it is not possible for other system calls.<\/p>\n<p style=\"text-align: justify;\">However there are several solutions. One of them, I have used several times, is to use a software layer that replicates the minimum system calls we need and simulates a failure if certain criteria are met. For example the following routine reproduces <code>malloc()<\/code> but fails after a number of invocations contained in the environment variable <code>MALLOC_FAIL<\/code>.<\/p>\n<pre><strong>src\/my_malloc.c:<\/strong>\n\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n\nvoid * my_malloc(size_t length)\n{\n\tchar * string;\n\tchar buffer[32];\n\tint count;\n\tstring = getenv (\"MALLOC_FAIL\");\n\tif (string != NULL) {\n\t\tif (sscanf(string, \"%d\", &amp; count)  == 1) {\n\t\t\tcount --;\n\t\t\tif (count == 0)\n\t\t\t\treturn NULL;\n\t\t\tsnprintf(buffer, 80, \"%d\", count);\n\t\t\tsetenv(\"MALLOC_FAIL\", buffer, 1 );\n\t\t}\n\t}\n\treturn malloc(length);\n}<\/pre>\n<p style=\"text-align: justify;\">We can declare it in a header file as follows:<\/p>\n<pre><strong>include\/my_malloc.h:<\/strong>\n\n#ifndef MY_MALLOC_H\n#define MY_MALLOC_H\n\n#ifndef NDEBUG\n        extern void * my_malloc(size_t);\n#else\n#define my_malloc(L) malloc(L)\n#endif\n\n#endif<\/pre>\n<p style=\"text-align: justify;\">In this way, depending on the presence or absence of the <code>NDEBUG<\/code> constant, which traditionally represents for the C library the production version of the code, our routine will be compiled as usual <code>malloc()<\/code> or with our management of the environment variable.<\/p>\n<p style=\"text-align: justify;\">Compile a dynamic library with our minimal abstraction layer minimum.<\/p>\n<pre>[factorial]$ <strong>gcc -c -fPIC -Wall -I include\/ -o src\/my_malloc.o src\/my_malloc.c <\/strong>\n[factorial]$ <strong>gcc -shared -Wl,-soname,libmytest.so.1 -o lib\/libmytest.so.1.0 src\/my_malloc.o<\/strong>\n[factorial]$ <strong>ldconfig -n lib\/<\/strong>\n[factorial]$ <strong>ln -sf libmytest.so.1 lib\/libmytest.so<\/strong>\n[factorial]$ <strong>ls -l lib\/libmy*<\/strong>\nlrwxrwxrwx 1 cpb cpb   14 2012-02-12 04:12 lib\/libmytest.so -&gt; libmytest.so.1\nlrwxrwxrwx 1 cpb cpb   16 2012-02-12 04:11 lib\/libmytest.so.1 -&gt; libmytest.so.1.0\n-rwxrwxr-x 1 cpb cpb 7014 2012-02-12 04:11 lib\/libmytest.so.1.0\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Let&rsquo;s write a small program that uses our test library by looping around <code>my_malloc()<\/code>.<\/p>\n<pre><strong>test\/test-mymalloc.c:<\/strong>\n\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;my_malloc.h&gt;\n\nint main(void)\n{\n        int i = 1;\n        while(1) {\n                fprintf(stderr, \"i = %2d...\", i);\n                if (<strong>my_malloc<\/strong>(10) == NULL) {\n                        fprintf(stderr, \"failure!n\");\n                        break;\n                }\n                fprintf(stderr, \"okn\");\n                i ++;\n        }\n        return 0;\n}<\/pre>\n<p style=\"text-align: justify;\">Compilation&#8230;<\/p>\n<pre>[factorial]$ <strong>gcc -I include\/ -L lib\/ -Wall -o test\/test-mymalloc test\/test-mymalloc.c -lmytest<\/strong>\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">First test, without the environment variable.<\/p>\n<pre>[factorial]$ <strong>unset MALLOC_FAIL<\/strong>\n[factorial]$ <strong>.\/test\/test-mymalloc <\/strong>\ni =  1...ok\ni =  2...ok\ni =  3...ok\ni =  4...ok\ni =  5...ok\n[...]\ni = 21928...ok\ni = 21929...ok\ni = 21930...ok\ni = 21931...ok\ni = 21932...\n  (<strong><em>Control-C<\/em><\/strong>)\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Of course, our program does not stop. Or rather it will stop after a long runtime when exhausting its 3GB address space (on a 32-bits machine).<\/p>\n<p style=\"text-align: justify;\">Try again by forcing a failure in the fourth <code>malloc()<\/code> call.<\/p>\n<pre>[factorial]$ <strong>export MALLOC_FAIL=4<\/strong>\n[factorial]$ <strong>.\/test\/test-mymalloc<\/strong>\ni =  1...ok\ni =  2...ok\ni =  3...ok\ni =  4...failure!\n[factorial]$<\/pre>\n<p style=\"text-align: justify;\">Of course, this principle of forcing system call failures under the control of an environment variable &#8211; or other parameters (global variable, file, shared memory area, etc.) &#8211; can be applied equally to a library code when you need 100% code coverage over the entire set of tests for an application.<\/p>\n<h1>Conclusion<\/h1>\n<p style=\"text-align: justify;\">We observed in this small series of articles, how to create, debug and test a dynamic library. I encourage you to do your own tests, referring to the documentation of <code>gcc<\/code>, <code>gdb<\/code>, <code>gcov<\/code>, but also other complementary tools such as <code>gprof<\/code>, <code>ldconfig<\/code>, <code>valgrind<\/code>, etc.<\/p>\n<p style=\"text-align: center;\">All comments, remarks, corrections, etc.. are welcome.<\/p>","protected":false},"excerpt":{"rendered":"<p>(version originale en fran&ccedil;ais ici) In the two previous posts, we started the development of a dynamic library on Linux: the first one saw us building the library and managing version numbers using symbolic links, in the second one we traced library calls and did step-by-step debugging. Now we are interested in checking the coverage [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1655","post","type-post","status-publish","format-standard","hentry","category-linux-2"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=1655"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1655\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=1655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=1655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=1655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}