Skip to content

Commit d35043f

Browse files
committed
fix(coverage): match .gcno to .gcda by basename, not path-strip
The previous algorithm in run-tests-isolated.bash's collect_coverage function stripped leading path components off a .gcda relative path and looked up `${WORKSPACE}/<stripped>.gcno`. That only works when the .gcda relative path is a path-suffix of the .gcno absolute path -- and for the ProxySQL daemon it's not. The proxysql binary is built with CWD=/opt/proxysql/lib/, so the embedded path in each .gcda is /opt/proxysql/lib/obj/X.gcda. The daemon container runs with GCOV_PREFIX=/gcov and GCOV_PREFIX_STRIP=3, which drops /opt/proxysql/lib/, landing the .gcda at /gcov/obj/X.gcda. The matching .gcno is at ${WORKSPACE}/lib/obj/X.gcno -- but the previous lookup only tried ${WORKSPACE}/obj/X.gcno and ${WORKSPACE}/X.gcno, never thinking to prepend lib/. Result: every daemon .gcda was logged by fastcov as "Missing 'current_working_directory'" with an empty files list, and the .info report came out 0 bytes. This replaces the strip-and-retry loop with an index built from `find ${WORKSPACE} -name '*.gcno'` mapping basename -> path, and looks each .gcda up by basename. Robust to GCOV_PREFIX_STRIP, build CWD, and arbitrary path layouts. ProxySQL doesn't reuse .cpp basenames across directories, so basename collision is not a concern. Also emits a `matched=N unmatched=M` summary so the next time something goes wrong with coverage, the failure mode is loud. Requires the companion change on GH-Actions ci-builds.yml (extends the _src cache to include proxysql/lib/obj/*.gcno) -- without that, the .gcno files for daemon-side lib code aren't available in the test workflow's WORKSPACE at all.
1 parent 3a594d2 commit d35043f

1 file changed

Lines changed: 40 additions & 16 deletions

File tree

test/infra/control/run-tests-isolated.bash

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -319,27 +319,51 @@ docker run \
319319
echo \">>> Collecting code coverage data (exit code was: \${exit_code})...\"
320320
321321
if [ -d \"/gcov\" ] && [ \"\$(ls -A /gcov 2>/dev/null)\" ]; then
322-
# Copy .gcno files adjacent to each .gcda file.
323-
# .gcda paths have a GCOV_PREFIX_STRIP offset (e.g. proxysql/lib/obj/X.gcda)
324-
# while .gcno files are at \${WORKSPACE}/lib/obj/X.gcno. We strip leading
325-
# components from the .gcda relative path until we find the matching .gcno.
322+
# Match .gcno files to .gcda files by basename and copy
323+
# adjacent so fastcov can find them.
324+
#
325+
# The previous algorithm tried to find a matching .gcno
326+
# by stripping leading path components off the .gcda
327+
# relative path and looking up \${WORKSPACE}/<stripped>.gcno
328+
# -- which only works when the .gcda relative path is a
329+
# path-suffix of the .gcno absolute path. For the
330+
# ProxySQL daemon, GCOV_PREFIX_STRIP=3 eats
331+
# /opt/proxysql/lib/ from /opt/proxysql/lib/obj/X.gcda,
332+
# so the .gcda lands at /gcov/obj/X.gcda. The matching
333+
# .gcno is at \${WORKSPACE}/lib/obj/X.gcno -- not a
334+
# suffix of any strip of obj/X, so the lookup always
335+
# missed and fastcov reported every .gcda as
336+
# \"Missing 'current_working_directory'\" with an empty
337+
# files list, producing a 0-byte .info report.
338+
#
339+
# Basename matching is robust to GCOV_PREFIX_STRIP and
340+
# build CWD. ProxySQL doesn't reuse .cpp basenames
341+
# across directories (verified by inspection of lib/
342+
# and src/), so basename collision is not a concern.
343+
echo \">>> Indexing .gcno files in \${WORKSPACE}...\"
344+
GCNO_INDEX=\$(mktemp)
345+
find \"\${WORKSPACE}\" -name '*.gcno' -type f -printf '%f %p\\n' 2>/dev/null \\
346+
| sed 's/\\.gcno / /' > \"\${GCNO_INDEX}\"
347+
echo \">>> Found \$(wc -l < \"\${GCNO_INDEX}\") .gcno files\"
326348
echo \">>> Copying .gcno files adjacent to .gcda files in /gcov...\"
349+
matched=0
350+
unmatched=0
327351
cd /gcov && find . -name '*.gcda' -type f | while read gcda; do
328352
relpath=\"\${gcda#./}\"
329353
base=\"\${relpath%.gcda}\"
330-
remaining=\"\${base}\"
331-
while [ -n \"\${remaining}\" ]; do
332-
if [ -f \"\${WORKSPACE}/\${remaining}.gcno\" ]; then
333-
target=\"/gcov/\${base}.gcno\"
334-
mkdir -p \"\$(dirname \"\${target}\")\"
335-
cp -f \"\${WORKSPACE}/\${remaining}.gcno\" \"\${target}\"
336-
break
337-
fi
338-
next=\"\${remaining#*/}\"
339-
[ \"\${next}\" = \"\${remaining}\" ] && break
340-
remaining=\"\${next}\"
341-
done
354+
bname=\$(basename \"\${base}\")
355+
gcno_src=\$(awk -v k=\"\${bname}\" '\$1==k {print \$2; exit}' \"\${GCNO_INDEX}\")
356+
if [ -n \"\${gcno_src}\" ]; then
357+
target=\"/gcov/\${base}.gcno\"
358+
mkdir -p \"\$(dirname \"\${target}\")\"
359+
cp -f \"\${gcno_src}\" \"\${target}\"
360+
matched=\$((matched + 1))
361+
else
362+
unmatched=\$((unmatched + 1))
363+
fi
342364
done
365+
rm -f \"\${GCNO_INDEX}\"
366+
echo \">>> .gcno copy: matched=\${matched} unmatched=\${unmatched}\"
343367
344368
if [ \"\${MULTI_GROUP}\" = \"1\" ]; then
345369
# Multi-group mode: data is ready in /gcov for centralized collection

0 commit comments

Comments
 (0)