#!/bin/bash # # Run in the top of the source directory which must be a git repo, on a branch # other than master so that we can find C files that are different from # master. # # Installed binaries configured with --enable-coverage must be in PATH.. set -e # you probably want just "gcov", but I currently have loads of versions of GCC installed... GCOV=gcov-mp-6 SQL_FILES="partition_join.sql partition_join_extras.sql" TMP=tmp export PAGER= # Set up workspace and cluster. mkdir -p $TMP mkdir -p $TMP/sql mkdir -p $TMP/gcov mkdir -p $TMP/results rm -fr $TMP/pgdata initdb -D $TMP/pgdata for sql_file in $SQL_FILES ; do # Consider each file as a set of blocks separated by blank lines or lines # made from - and = characters. Number all blocks that contain SELECT or # PREPARE in a SQL comment. awk ' BEGIN { blockno = 0; numbered_buffer = ""; plain_buffer = ""; interesting = 0; } /^[\-= ]*$/ { if (interesting) { printf("%s", numbered_buffer); blockno++; } else { printf("%s", plain_buffer); } interesting = 0; numbered_buffer = ""; plain_buffer = ""; print; next; } { if ($0 ~ /^(select|SELECT|prepare|PREPARE)/ ) { interesting = 1; } numbered_buffer = numbered_buffer sprintf("/*BLOCK%s*/ %s\n", blockno, $0); plain_buffer = plain_buffer sprintf("%s\n", $0); }' < src/test/regress/sql/$sql_file > $TMP/sql/$sql_file # Find the highest block number. highest_blockno=$(sed -n 's|^/\*BLOCK\([0-9]*\)\*/.*$|\1|p' < $TMP/sql/$sql_file | tail -1) # For each block number, produce a version of the file with all numbered # blocks but that one commented out. for blockno in $(seq 0 $highest_blockno) ; do awk " /^\/\*BLOCK$blockno\*\// { print; next; } /^\/\*BLOCK[0-9]*\*\// { printf(\"-- %s\n\", \$0); next; } { print; } " < $TMP/sql/$sql_file > $TMP/sql/$sql_file.$blockno done # Run all the variants... for blockno in $(seq 0 $highest_blockno) ; do find . -name '*.gcda' -print | xargs rm pg_ctl -w -D $TMP/pgdata start psql postgres -c 'DROP SCHEMA IF EXISTS pwj_extra CASCADE; DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public' psql postgres -f $TMP/sql/$sql_file.$blockno pg_ctl -w -D $TMP/pgdata stop for c_file in $( git diff master... --stat --name-only | grep \.c\$ ) ; do echo $c_file ( cd $(dirname $c_file) && $GCOV $(basename $c_file) ) cp $c_file.gcov $TMP/gcov/$(basename $c_file).$sql_file.$blockno.gcov done done done # Merge all of this information into unreadable output file showing which # blocks of SQL hit which lines of C. for c_file in $( git diff master... --stat --name-only | grep \.c\$ ) ; do output=$TMP/results/$(basename $c_file).aggregated_coverage sed 's/$/ SQL blocks:/' < $c_file > $output codes=ABCDEFG for sql_file in $SQL_FILES ; do code=$(echo $codes | cut -c1) codes=$(echo $codes | cut -c2-) highest_blockno=$(sed -n 's|^/\*BLOCK\([0-9]*\)\*/.*$|\1|p' < $TMP/sql/$sql_file | tail -1) for blockno in $(seq 0 $highest_blockno) ; do grep -vE '^ *-: *0:' $TMP/gcov/$(basename $c_file).$sql_file.$blockno.gcov | sed "s/^ *[0-9][0-9]*:.*$/ $code$blockno/;s/^ [^A-Z].*$//" | paste -d '\0' $output - > $output.tmp mv $output.tmp $output done done sed 's/ SQL blocks:$//' < $output > $output.tmp mv $output.tmp $output done