Test suite support for function coverage testing via gcov
authorMichael Rash <mbr@cipherdyne.org>
Fri, 15 Jun 2012 00:43:57 +0000 (20:43 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Fri, 15 Jun 2012 00:43:57 +0000 (20:43 -0400)
Added --enable-profile-coverage to the configure script to have the fwknop
binaries compiled with gcc profiling support in order to see which functions
get executed by the test suite via gcov.  The last test executed by the test
suite under --enable-profile-coverage contains all fwknop functions that
were not executed under the test run (function execution totals are
cumlative).

configure.ac
test/test-coverage/iptables/zero_called_functions [new file with mode: 0644]
test/test-fwknop.pl

index 2a18f9e..626b3f3 100644 (file)
@@ -120,6 +120,20 @@ AC_PROG_LN_S
 AC_PROG_MAKE_SET
 AC_PROG_LIBTOOL
 
+dnl Decide whether or not to build binaries with profiling coverage support
+dnl
+want_profile_coverage=no
+AC_ARG_ENABLE([profile-coverage],
+  [AS_HELP_STRING([--enable-profile-coverage],
+    [Build fwknop binaries with profile coverage support @<:@default is to disable@:>@])],
+  [want_profile_coverage=$enableval],
+  [])
+
+if test "x$want_profile_coverage" = "xyes"; then
+    CFLAGS="-g -O0"
+    FKO_CHECK_COMPILER_ARG([-fprofile-arcs -ftest-coverage -fno-inline])
+fi
+
 dnl Decide whether or not to enable all warnings with -Wall
 dnl
 use_wall=yes
diff --git a/test/test-coverage/iptables/zero_called_functions b/test/test-coverage/iptables/zero_called_functions
new file mode 100644 (file)
index 0000000..12b8077
--- /dev/null
@@ -0,0 +1,79 @@
+[+] TEST: [profile coverage] gcov profile coverage
+CMD: grep "called 0 returned" ../client/*.gcov
+../client/config_init.c.gcov:function digest_strtoint called 0 returned 0% blocks executed 0%
+../client/config_init.c.gcov:function proto_strtoint called 0 returned 0% blocks executed 0%
+../client/config_init.c.gcov:function create_fwknoprc called 0 returned 0% blocks executed 0%
+../client/config_init.c.gcov:function parse_rc_param called 0 returned 0% blocks executed 0%
+../client/fwknop.c.gcov:function show_last_command called 0 returned 0% blocks executed 0%
+../client/fwknop.c.gcov:function run_last_args called 0 returned 0% blocks executed 0%
+../client/getpasswd.c.gcov:function getpasswd called 0 returned 0% blocks executed 0%
+../client/http_resolve_host.c.gcov:function parse_url called 0 returned 0% blocks executed 0%
+../client/http_resolve_host.c.gcov:function resolve_ip_http called 0 returned 0% blocks executed 0%
+../client/spa_comm.c.gcov:function chksum called 0 returned 0% blocks executed 0%
+../client/spa_comm.c.gcov:function send_spa_packet_tcp_raw called 0 returned 0% blocks executed 0%
+../client/spa_comm.c.gcov:function send_spa_packet_icmp called 0 returned 0% blocks executed 0%
+../client/spa_comm.c.gcov:function send_spa_packet_http called 0 returned 0% blocks executed 0%
+../client/spa_comm.c.gcov:function write_spa_packet_data called 0 returned 0% blocks executed 0%
+../client/utils.c.gcov:function hex_dump called 0 returned 0% blocks executed 0%
+CMD: grep "called 0 returned" ../server/*.gcov
+../server/access.c.gcov:function acc_check_gpg_remote_id called 0 returned 0% blocks executed 0%
+../server/config_init.c.gcov:function config_entry_index called 0 returned 0% blocks executed 0%
+../server/extcmd.c.gcov:function run_extcmd_as called 0 returned 0% blocks executed 0%
+../server/fwknopd.c.gcov:function make_dir_path called 0 returned 0% blocks executed 0%
+../server/fwknopd.c.gcov:function daemonize_process called 0 returned 0% blocks executed 0%
+../server/log_msg.c.gcov:function set_log_facility called 0 returned 0% blocks executed 0%
+../server/replay_cache.c.gcov:function rotate_digest_cache_file called 0 returned 0% blocks executed 0%
+../server/tcp_server.c.gcov:function run_tcp_server called 0 returned 0% blocks executed 0%
+../server/utils.c.gcov:function hex_dump called 0 returned 0% blocks executed 0%
+CMD: grep "called 0 returned" ../lib/.libs/*.gcov
+../lib/.libs/digest.c.gcov:function digest_to_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function md5_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function md5_base64 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha1 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha1_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha1_base64 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha256_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha384 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha384_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha384_base64 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha512 called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha512_hex called 0 returned 0% blocks executed 0%
+../lib/.libs/digest.c.gcov:function sha512_base64 called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_spa_encryption_type called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_set_gpg_exe called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_exe called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_recipient called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signer called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_home_dir called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signature_verify called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_ignore_verify_error called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signature_fpr called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signature_id called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signature_summary called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_get_gpg_signature_status called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_gpg_signature_id_match called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_encryption.c.gcov:function fko_gpg_signature_fpr_match called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_funcs.c.gcov:function fko_set_spa_data called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_message.c.gcov:function validate_cmd_msg called 0 returned 0% blocks executed 0%
+../lib/.libs/fko_server_auth.c.gcov:function fko_set_spa_server_auth called 0 returned 0% blocks executed 0%
+../lib/.libs/gpgme.h.gcov:function gpgme_err_code called 0 returned 0% blocks executed 0%
+../lib/.libs/gpgme_funcs.c.gcov:function process_sigs called 0 returned 0% blocks executed 0%
+../lib/.libs/sha1.c.gcov:function sha1_transform called 0 returned 0% blocks executed 0%
+../lib/.libs/sha1.c.gcov:function sha1_init called 0 returned 0% blocks executed 0%
+../lib/.libs/sha1.c.gcov:function sha1_update called 0 returned 0% blocks executed 0%
+../lib/.libs/sha1.c.gcov:function sha1_transform_and_copy called 0 returned 0% blocks executed 0%
+../lib/.libs/sha1.c.gcov:function sha1_final called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA256_End called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA256_Data called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Init called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Transform called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Update called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Last called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Final called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_End called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA512_Data called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA384_Init called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA384_Update called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA384_Final called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA384_End called 0 returned 0% blocks executed 0%
+../lib/.libs/sha2.c.gcov:function SHA384_Data called 0 returned 0% blocks executed 0%
index a5f0ab2..f59e5c0 100755 (executable)
@@ -4,6 +4,7 @@ use File::Copy;
 use File::Path;
 use IO::Socket;
 use Data::Dumper;
+use Cwd;
 use Getopt::Long 'GetOptions';
 use strict;
 
@@ -85,7 +86,9 @@ my $valgrind_str = '';
 my $saved_last_results = 0;
 my $diff_mode = 0;
 my $enable_recompilation_warnings_check = 0;
+my $enable_profile_coverage_check = 0;
 my $sudo_path = '';
+my $gcov_path = '';
 my $platform = '';
 my $help = 0;
 my $YES = 1;
@@ -115,6 +118,7 @@ exit 1 unless GetOptions(
     'test-exclude=s'    => \$test_exclude,
     'exclude=s'         => \$test_exclude,  ### synonym
     'enable-recompile-check' => \$enable_recompilation_warnings_check,
+    'enable-profile-coverage-check' => \$enable_profile_coverage_check,
     'List-mode'         => \$list_mode,
     'enable-valgrind'   => \$use_valgrind,
     'valgrind-path=s'   => \$valgrindCmd,
@@ -1307,6 +1311,14 @@ my @tests = (
         'function' => \&digest_cache_structure,
         'fatal'    => $NO
     },
+
+    {
+        'category' => 'profile coverage',
+        'detail'   => 'gcov profile coverage',
+        'err_msg'  => 'profile coverage failed',
+        'function' => \&profile_coverage,
+        'fatal'    => $NO
+    },
 );
 
 my %test_keys = (
@@ -1526,7 +1538,8 @@ sub compile_warnings() {
 
     ### look for compilation warnings - something like:
     ###     warning: ‘test’ is used uninitialized in this function
-    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/], $current_test_file);
+    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
+        $current_test_file);
 
     ### the new binaries should exist
     unless (-e $fwknopCmd and -x $fwknopCmd) {
@@ -1541,6 +1554,32 @@ sub compile_warnings() {
     return 1;
 }
 
+sub profile_coverage() {
+
+    ### check for any *.gcno files - if they don't exist, then fwknop was
+    ### not compiled with profile support
+    unless (glob('../client/*.gcno') and glob('../server/*.gcno')) {
+        &write_test_file("[-] ../client/*.gcno and " .
+            "../server/*.gcno files do not exist.\n", $current_test_file);
+        return 0;
+    }
+
+    my $curr_dir = getcwd() or die $!;
+
+    ### gcov -b ../client/*.gcno
+    for my $dir ('../client', '../server', '../lib/.libs') {
+        next unless -d $dir;
+        chdir $dir or die $!;
+        system "$gcov_path -b -u *.gcno > /dev/null 2>&1";
+        chdir $curr_dir or die $!;
+
+        &run_cmd(qq|grep "called 0 returned" $dir/*.gcov|,
+                $cmd_out_tmp, $current_test_file);
+    }
+
+    return 1;
+}
+
 sub binary_exists() {
     my $test_hr = shift;
     return 0 unless $test_hr->{'binary'};
@@ -2576,6 +2615,10 @@ sub init() {
         push @tests_to_exclude, 'recompilation';
     }
 
+    unless ($enable_profile_coverage_check) {
+        push @tests_to_exclude, 'profile coverage';
+    }
+
     $sudo_path = &find_command('sudo');
 
     unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
@@ -2583,6 +2626,19 @@ sub init() {
         push @tests_to_exclude, 'recompilation';
     }
 
+    $gcov_path = &find_command('gcov');
+
+    if ($gcov_path) {
+        if ($enable_profile_coverage_check) {
+            for my $extension ('*.gcov', '*.gcda') {
+                ### remove profile output from any previous run
+                system qq{find .. -name $extension | xargs rm 2> /dev/null};
+            }
+        }
+    } else {
+        push @tests_to_exclude, 'profile coverage';
+    }
+
     open UNAME, "uname |" or die "[*] Could not execute uname: $!";
     while (<UNAME>) {
         if (/linux/i) {
@@ -2766,3 +2822,7 @@ sub logr() {
     close F;
     return;
 }
+
+sub usage() {
+    return;
+}