Voici un outil bien pratique pour la phase de test d’un projet ou pour trouver du code mort : GCOV. En effet Gcov va nous permettre de voir le taux de couverture de nos jeux de tests en nous montrant le pourcentage de ligne de code et de branchements testés.
But : Détermine le taux de couverture de nos tests sur un projet afin de détecter éventuellement du code mort et surtout d’être certain de tester 100% du code produit.
Prérequis pour un programme en espace utilisateur: lcov 1.9. Pour un module noyau, cela nécessite évidemment les sources du noyau et les flags associés à GCOV d’activés dans le configure du noyau dans le cas ou nous souhaitons profiler le noyau lui même.
Voici un programme simple pour calculer un factorielle :
#include #include int usage () { printf ("usage: ./facto N\n"); printf ("\tN : decimal value (MAX : 20)\n\n"); printf ("Compute the factorial value of an integer value.\n\n"); return 1; } unsigned long long facto(unsigned long long n) { if (n == 0) return 1; return n * facto(n - 1); } int main (int argc, char *argv[]) { char* ptr; if (argc != 2) return usage (); long int n = strtol(argv[1], &ptr, 0); if (ptr[0] || n < 0 || n > 20) return usage (); printf ("%ld\n", facto(n)); return 0; }
Voici un script shell de test :
#!/bin/sh n=0 red="\033[31m"; white="\033[37m"; green="\033[32m"; blue="\\033[1;34m"; test_facto () { # $1 is facto argument # $2 is return value by program # $3 is result echo "Test $i : Run facto with n = $1." ./facto $1 2>/dev/null 1>&2 ret1=`echo $?` ./facto $1 2>/dev/null | grep $3 >/dev/null 2>&1 ret2=`echo $?` if [ $2 -eq $ret1 ] && [ $ret2 -eq 0 ]; then printf $green echo OK else printf $red echo KO fi; printf $blue i=$(($i+1)); } printf $blue test_facto 0 0 1 test_facto 1 0 1 test_facto 2 0 2 test_facto 3 0 6 test_facto 4 0 24 test_facto 5 0 120 test_facto 6 0 720 test_facto 12 0 479001600 test_facto efsf 1 usage test_facto efez54zfz 1 usage test_facto ffzeef 1 usage test_facto -4 1 usage test_facto 1.1 1 usage
Dans ce script nous testons differentes valeurs dont les cas d’erreurs. Pour utiliser lcov nous devons compiler notre code avec ces flags :
+=-fprofile-arcs -ftest-coverage
Enfin pour utiliser lcov/gcov, nous commencons par executer notre script de test :
./check_complete.sh gcov test_user_gcov lcov -o user_test.info -c -f -d . genhtml -o user_result user_test.info
Gcov va générer les résultats tandis que lcov est une surcouche permettant d’exploiter les résultats sous forme de fichier html très facile à exploiter
Dans cette image nous pouvons voir que l’ensemble du code n’est pas testé, le code de valeur max n’est pas testé ainsi que le cas ou le programme est appelé avec un nombre incorrecte d’argument. Gcov analyse deux données, le nombre de ligne de code testé, et aussi le nombre de branchement effectivement testé. Ainsi nous obtenons le nombre de fois qu’a été exécuté une ligne de code lors de nos tests ainsi que le détail sur chaque branchement possible de nos conditions. Ligne 33, nous pouvons voir que sur les 6 cas possible de la condition, 1 cas n’est pas testé par la présence d’un symbole “-” en rouge. Simple et efficace.
De plus Gcov peut aussi être utilisé dans le cas d’un module noyau. Vous trouverez dans cette tarball un exemple complet pour utiliser gcov avec un programme utilisateur et en espace noyau avec la présence d’un Makefile, le code (utilisateur et noyau), un configure pour vérifier les prérequis :gcov_example.tar.bz2