Skip to content

Commit 54dea46

Browse files
committed
misc: Add missing coverage aggregation scripts
1 parent 4c37cac commit 54dea46

3 files changed

Lines changed: 174 additions & 1 deletion

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ gen_*.c
2323
gen_*.h
2424
wire/gen_*_csv
2525
cli/lightning-cli
26-
coverage
2726
# Coverage profiling data files
2827
*.profraw
2928
*.profdata
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/bin/bash -eu
2+
# Merge all .profraw files into a single .profdata file
3+
# Usage: ./collect-coverage.sh [COVERAGE_DIR] [OUTPUT_FILE]
4+
5+
COVERAGE_DIR="${1:-${CLN_COVERAGE_DIR:-/tmp/cln-coverage}}"
6+
OUTPUT="${2:-coverage/merged.profdata}"
7+
8+
echo "Collecting coverage from: $COVERAGE_DIR"
9+
10+
# Find all profraw files
11+
mapfile -t PROFRAW_FILES < <(find "$COVERAGE_DIR" -name "*.profraw" 2>/dev/null || true)
12+
13+
if [ ${#PROFRAW_FILES[@]} -eq 0 ]; then
14+
echo "ERROR: No .profraw files found in $COVERAGE_DIR"
15+
exit 1
16+
fi
17+
18+
echo "Found ${#PROFRAW_FILES[@]} profile files"
19+
20+
# Validate each profraw file and filter out corrupt/incomplete ones
21+
# Define validation function for parallel execution
22+
validate_file() {
23+
local profraw="$1"
24+
25+
# Check if file is empty
26+
if [ ! -s "$profraw" ]; then
27+
return 1 # Empty
28+
fi
29+
30+
# Check if file is suspiciously small (likely incomplete write)
31+
# Valid profraw files are typically > 1KB
32+
filesize=$(stat -c%s "$profraw" 2>/dev/null || stat -f%z "$profraw" 2>/dev/null)
33+
if [ "$filesize" -lt 1024 ]; then
34+
return 2 # Too small
35+
fi
36+
37+
# Try to validate the file by checking if llvm-profdata can read it
38+
if llvm-profdata show "$profraw" >/dev/null 2>&1; then
39+
echo "$profraw" # Valid - output to stdout
40+
return 0
41+
else
42+
return 3 # Corrupt
43+
fi
44+
}
45+
46+
# Export function for parallel execution
47+
export -f validate_file
48+
49+
TOTAL=${#PROFRAW_FILES[@]}
50+
NPROC=$(nproc 2>/dev/null || echo 4)
51+
echo "Validating ${TOTAL} files in parallel (using ${NPROC} cores)..."
52+
53+
# Run validation in parallel and collect valid files
54+
mapfile -t VALID_FILES < <(
55+
printf '%s\n' "${PROFRAW_FILES[@]}" | \
56+
xargs -P "$NPROC" -I {} bash -c 'validate_file "$@"' _ {}
57+
)
58+
59+
# Calculate error counts
60+
CORRUPT_COUNT=$((TOTAL - ${#VALID_FILES[@]}))
61+
62+
if [ ${#VALID_FILES[@]} -eq 0 ]; then
63+
echo "ERROR: No valid .profraw files found (all $CORRUPT_COUNT files were corrupt/incomplete)"
64+
exit 1
65+
fi
66+
67+
echo "Valid files: ${#VALID_FILES[@]}"
68+
if [ $CORRUPT_COUNT -gt 0 ]; then
69+
echo "Filtered out: $CORRUPT_COUNT files (empty/small/corrupt)"
70+
fi
71+
mkdir -p "$(dirname "$OUTPUT")"
72+
73+
# Merge with -sparse flag for efficiency
74+
# Use batched merging to avoid "Argument list too long" errors
75+
BATCH_SIZE=500
76+
TOTAL_FILES=${#VALID_FILES[@]}
77+
78+
if [ "$TOTAL_FILES" -le "$BATCH_SIZE" ]; then
79+
# Small enough to merge in one go
80+
echo "Merging ${TOTAL_FILES} files..."
81+
llvm-profdata merge -sparse "${VALID_FILES[@]}" -o "$OUTPUT"
82+
else
83+
# Need to merge in batches
84+
echo "Merging ${TOTAL_FILES} files in batches of ${BATCH_SIZE}..."
85+
86+
# Create temp directory for intermediate files
87+
TEMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/profdata-merge.XXXXXX")
88+
trap 'rm -rf "$TEMP_DIR"' EXIT
89+
90+
BATCH_NUM=0
91+
INTERMEDIATE_FILES=()
92+
93+
# Merge files in batches
94+
for ((i=0; i<TOTAL_FILES; i+=BATCH_SIZE)); do
95+
BATCH_NUM=$((BATCH_NUM + 1))
96+
END=$((i + BATCH_SIZE))
97+
if [ "$END" -gt "$TOTAL_FILES" ]; then
98+
END=$TOTAL_FILES
99+
fi
100+
101+
BATCH_FILES=("${VALID_FILES[@]:$i:$BATCH_SIZE}")
102+
INTERMEDIATE="$TEMP_DIR/batch-$BATCH_NUM.profdata"
103+
104+
echo " Batch $BATCH_NUM: merging files $((i+1))-$END..."
105+
llvm-profdata merge -sparse "${BATCH_FILES[@]}" -o "$INTERMEDIATE"
106+
INTERMEDIATE_FILES+=("$INTERMEDIATE")
107+
done
108+
109+
# Merge all intermediate files into final output
110+
echo "Merging ${#INTERMEDIATE_FILES[@]} intermediate files into final output..."
111+
llvm-profdata merge -sparse "${INTERMEDIATE_FILES[@]}" -o "$OUTPUT"
112+
113+
# Cleanup handled by trap
114+
fi
115+
116+
echo "✓ Merged profile: $OUTPUT"
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/bin/bash -eu
2+
# Generate HTML and text coverage reports from merged profile data
3+
# Usage: ./generate-coverage-report.sh [PROFDATA_FILE] [OUTPUT_DIR]
4+
5+
PROFDATA="${1:-coverage/merged.profdata}"
6+
OUTPUT_DIR="${2:-coverage/html}"
7+
8+
if [ ! -f "$PROFDATA" ]; then
9+
echo "ERROR: Profile not found: $PROFDATA"
10+
echo "Run collect-coverage.sh first to create the merged profile"
11+
exit 1
12+
fi
13+
14+
# Get all binaries from Makefile (includes plugins, tools, test binaries)
15+
echo "Discovering instrumented binaries from Makefile..."
16+
mapfile -t BINARIES < <(make -qp 2>/dev/null | awk '/^ALL_PROGRAMS :=/ {$1=$2=""; print}' | tr ' ' '\n' | grep -v '^$')
17+
mapfile -t TEST_BINARIES < <(make -qp 2>/dev/null | awk '/^ALL_TEST_PROGRAMS :=/ {$1=$2=""; print}' | tr ' ' '\n' | grep -v '^$')
18+
19+
# Combine all binaries
20+
ALL_BINARIES=("${BINARIES[@]}" "${TEST_BINARIES[@]}")
21+
22+
# Build llvm-cov arguments
23+
ARGS=()
24+
for bin in "${ALL_BINARIES[@]}"; do
25+
if [ -f "$bin" ]; then
26+
if [ ${#ARGS[@]} -eq 0 ]; then
27+
ARGS+=("$bin") # First binary is primary
28+
else
29+
ARGS+=("-object=$bin") # Others use -object=
30+
fi
31+
fi
32+
done
33+
34+
if [ ${#ARGS[@]} -eq 0 ]; then
35+
echo "ERROR: No instrumented binaries found"
36+
echo "Make sure you've built with --enable-coverage"
37+
exit 1
38+
fi
39+
40+
echo "Generating coverage report for ${#ARGS[@]} binaries..."
41+
42+
# Generate HTML report
43+
llvm-cov show "${ARGS[@]}" \
44+
-instr-profile="$PROFDATA" \
45+
-format=html \
46+
-output-dir="$OUTPUT_DIR" \
47+
-show-line-counts-or-regions \
48+
-show-instantiations=false
49+
50+
echo "✓ HTML report: $OUTPUT_DIR/index.html"
51+
52+
# Generate text summary
53+
mkdir -p coverage
54+
llvm-cov report "${ARGS[@]}" \
55+
-instr-profile="$PROFDATA" \
56+
| tee coverage/summary.txt
57+
58+
echo "✓ Summary: coverage/summary.txt"

0 commit comments

Comments
 (0)