Viewing: lcov-merge.sh.in

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

## Prerequisites:
# Kernel built with GCOV support (tested RHEL 9.6 running 6.12.6 kernel)
# lcov to generate html report via genhtml
# fastcov to generate JSON from gcno and gcda files.

## lcov available from epel

## fastcov via pip3
# sudo pip3 install --upgrade pip
# sudo pip3 install --root-user-action ignore --upgrade pip
# sudo pip3 install --root-user-action ignore --prefix=/usr git+https://github.com/rpgillespie6/fastcov.git

## Be verbose (optional):
VERBOSE=
SRCDIR=$(dirname $0)

## Where to place lcov output:
LVERS=$(cat /sys/fs/lustre/version)
COVERAGE_ROOT=${COVERAGE_ROOT:-/tmp}
LCOV=${COVERAGE_ROOT}/${LVERS}/lcov.out
REPORT=${COVERAGE_ROOT}/${LVERS}/lcov

## Running from checkout:
DBGFS_GCOV=/sys/kernel/debug/gcov
KERNEL_GCOV=${DBGFS_GCOV}@BUILD_SRC@
SOURCE_GCOV="/$(echo $KERNEL_GCOV | cut -d/ -f6-)"
RPMPKG=0

# Note that gcov.tar.xz is only built and needed when RPM packing.
# Running tests from the local build directory can skip this step.

if [[ -f ${SRCDIR}/gcov.tar.xz ]]; then
	tar -C / -xf ${SRCDIR}/gcov.tar.xz 2>/dev/null
	## Running from rpmbuild packages:
	RPMBUILD_SRC=$(find ${DBGFS_GCOV} -type d -name \*${LVERS})
	if [[ -d $RPMBUILD_SRC ]]; then
		KERNEL_GCOV=${RPMBUILD_SRC}
		SOURCE_GCOV=/$(cut -d/ -f6- <<< $RPMBUILD_SRC)
	fi
	if [[ -n \$VERBOSE ]]; then
		echo "LCOV: $LCOV"
		echo "KERNEL_GCOV: $KERNEL_GCOV"
		echo "SOURCE_GCOV: $SOURCE_GCOV"
	fi
fi

mkdir -p $LCOV
all_nodes=""
for n in _ $(seq 0 10)
do
	all_nodes+="\$ost${n}_HOST "
	all_nodes+="\$mgs${n}_HOST "
	all_nodes+="\$mds${n}_HOST "
done
nodes=$(eval echo $(sed -e 's/__/_/' <<< ${all_nodes}) | tr ' ' '\n' |sort|uniq)
echo "Collect data from nodes: $(echo ${nodes} | xargs echo)"
for node in ${nodes}
do
	echo ".. Collecting gcov data from $node"
	ssh -T ${node} << EOF
echo Scanning for coverage files on $node at
echo "   $KERNEL_GCOV"
VERBOSE=$VERBOSE
for F in \$(find $KERNEL_GCOV ! -type d | xargs echo)
do
	FILE=\$(echo \$F | cut -d/ -f10-)
	DIR=\$(dirname \$FILE)
	mkdir -p ${LCOV}/${node}/\${DIR}

	[[ -n \$VERBOSE ]] && echo ${LCOV}/${node}/\${FILE}
	[[ -f \$F ]] && cat \$F > ${LCOV}/${node}/\${FILE}
done
cd ${LCOV}
tar czf ${LCOV}/${node}.tar.gz ${node}
EOF
	scp ${node}:${LCOV}/${node}.tar.gz ${LCOV}
	tar xf ${LCOV}/${node}.tar.gz -C ${LCOV}
done

node=$(hostname -s)
echo Scanning for coverage files on $node at
echo "   $KERNEL_GCOV"
for F in $(find $KERNEL_GCOV ! -type d)
do
	FILE=$(echo $F | cut -d/ -f10-)
	DIR=$(dirname $FILE)
	mkdir -p ${LCOV}/${node}/${DIR}

	[[ -n $VERBOSE ]] && echo ${LCOV}/${node}/${FILE}
	[[ -f $F ]] && cat $F > ${LCOV}/${node}/${FILE}
done

for node in $(hostname -s) ${nodes}
do
	for F in $(find ${LCOV}/${node} ! -type d)
	do
		DIR=$(dirname $F)
		PKGSRC=$(sed -e s:$LCOV/${node}:$SOURCE_GCOV: -e 's:\.gc.*:\.*:' <<< $F)
		for S in $(ls -1 $PKGSRC 2>/dev/null)
		do
			if test -f ${S} -o -L ${S} ; then
				[[ -n ${VERBOSE} ]] && echo ln -s ${S} ${DIR}
				ln -s ${S} ${DIR} > /dev/null 2>&1
			fi
		done
	done
done

FASTCOV=$(command -v fastcov)
VERBOSE=1
mkdir -p ${REPORT}
reports=
for node in $(hostname -s) ${nodes}
do
	RNODE=${REPORT}/report-${node}.info
	[[ -d ${LCOV}/${node} ]] || continue
	if [[ -z $FASTCOV ]] ; then
		[[ -n $VERBOSE ]] &&
		   echo lcov -d ${LCOV}/${node} -o ${RNODE}
		lcov -d ${LCOV}/${node} -o ${RNODE}
		# ignore empty reports
		[[ -s ${RNODE} ]] &&
			reports+="--add-tracefile ${RNODE} "
	else
		[[ -n $VERBOSE ]] &&
		   echo ${FASTCOV} -n -d ${LCOV}/${node} --lcov -o ${RNODE}
		${FASTCOV} -n -d ${LCOV}/${node} --lcov -o ${RNODE}
		# ignore empty reports
		[[ -s ${RNODE} ]] &&
			reports+="--add-tracefile ${RNODE} "
	fi
done

[[ -n $VERBOSE ]] && echo lcov ${reports} -o ${REPORT}/report.info
lcov ${reports} -o ${REPORT}/report.info

[[ -n $VERBOSE ]] &&
	echo genhtml -o ${REPORT}/code_coverage ${REPORT}/report.info
genhtml -o ${REPORT}/code_coverage ${REPORT}/report.info
(cd ${REPORT}; tar cvf code_coverage.tar code_coverage; xz --threads=0 code_coverage.tar)

## view coverage report directly or copy coverage report elsewhere:
# firefox ${REPORT}/code_coverage/index.html

echo "Report [${REPORT}/code_coverage.tar.xz] is ready"