Merge pull request #10 from cozis/claude/measure-branch-coverage-0168rdcTg6viLER3ufRwoAye
Measure branch coverage of the simulation testing
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
# Ensure shell scripts always use LF line endings
|
||||||
|
*.sh text eol=lf
|
||||||
@@ -3,3 +3,8 @@
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
chunk_server_data_*
|
chunk_server_data_*
|
||||||
|
# Coverage reports
|
||||||
|
coverage_report/
|
||||||
|
*.gcov
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
CFLAGS = -Wall -Wextra -ggdb
|
CFLAGS = -Wall -Wextra -ggdb
|
||||||
|
COVERAGE_CFLAGS = $(CFLAGS) --coverage
|
||||||
|
COVERAGE_LFLAGS = --coverage
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
LFLAGS = -lws2_32
|
LFLAGS = -lws2_32
|
||||||
@@ -13,16 +15,27 @@ CFILES = $(shell find src -name '*.c')
|
|||||||
HFILES = $(shell find src -name '*.h')
|
HFILES = $(shell find src -name '*.h')
|
||||||
OFILES = $(CFILES:.c=.o)
|
OFILES = $(CFILES:.c=.o)
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean coverage coverage-report coverage-html
|
||||||
|
|
||||||
all: mousefs$(EXT) mousefs_random_test$(EXT) example_client$(EXT) libmousefs.a
|
all: mousefs$(EXT) mousefs_random_test$(EXT) example_client$(EXT) libmousefs.a
|
||||||
|
|
||||||
|
coverage: mousefs_random_test_coverage$(EXT)
|
||||||
|
|
||||||
|
coverage-report:
|
||||||
|
@./scripts/measure_coverage.sh 5
|
||||||
|
|
||||||
|
coverage-html:
|
||||||
|
@./scripts/measure_coverage.sh 5 --html
|
||||||
|
|
||||||
mousefs$(EXT): $(CFILES) $(HFILES)
|
mousefs$(EXT): $(CFILES) $(HFILES)
|
||||||
gcc -o $@ $(CFILES) $(CFLAGS) $(LFLAGS) -Iinc -DBUILD_SERVER
|
gcc -o $@ $(CFILES) $(CFLAGS) $(LFLAGS) -Iinc -DBUILD_SERVER
|
||||||
|
|
||||||
mousefs_random_test$(EXT): $(CFILES) $(HFILES)
|
mousefs_random_test$(EXT): $(CFILES) $(HFILES)
|
||||||
gcc -o $@ $(CFILES) $(CFLAGS) $(LFLAGS) -Iinc -DBUILD_TEST
|
gcc -o $@ $(CFILES) $(CFLAGS) $(LFLAGS) -Iinc -DBUILD_TEST
|
||||||
|
|
||||||
|
mousefs_random_test_coverage$(EXT): $(CFILES) $(HFILES)
|
||||||
|
gcc -o $@ $(CFILES) $(COVERAGE_CFLAGS) $(LFLAGS) $(COVERAGE_LFLAGS) -Iinc -DBUILD_TEST
|
||||||
|
|
||||||
example_client$(EXT): libmousefs.a
|
example_client$(EXT): libmousefs.a
|
||||||
gcc -o $@ examples/main.c $(CFLAGS) -lmousefs $(LFLAGS) -Iinc -L.
|
gcc -o $@ examples/main.c $(CFLAGS) -lmousefs $(LFLAGS) -Iinc -L.
|
||||||
|
|
||||||
@@ -33,12 +46,18 @@ libmousefs.a: $(OFILES)
|
|||||||
ar rcs $@ $^
|
ar rcs $@ $^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f \
|
rm -f \
|
||||||
mousefs.exe \
|
mousefs.exe \
|
||||||
mousefs.out \
|
mousefs.out \
|
||||||
mousefs_random_test.exe \
|
mousefs_random_test.exe \
|
||||||
mousefs_random_test.out \
|
mousefs_random_test.out \
|
||||||
example_client.exe \
|
mousefs_random_test_coverage.exe \
|
||||||
example_client.out \
|
mousefs_random_test_coverage.out \
|
||||||
libmousefs.a \
|
example_client.exe \
|
||||||
src/*.o
|
example_client.out \
|
||||||
|
libmousefs.a \
|
||||||
|
src/*.o \
|
||||||
|
src/*.gcda \
|
||||||
|
src/*.gcno \
|
||||||
|
*.gcda \
|
||||||
|
*.gcno
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Branch Coverage Measurement
|
||||||
|
|
||||||
|
This directory contains scripts for measuring branch coverage of the random simulation.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
The HTML report generation requires `lcov`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install lcov
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Quick text summary (5 second simulation)
|
||||||
|
```bash
|
||||||
|
make coverage-report
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML report with branch details (5 second simulation)
|
||||||
|
```bash
|
||||||
|
make coverage-html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom duration
|
||||||
|
```bash
|
||||||
|
./scripts/measure_coverage.sh 10 # 10 second run, text output
|
||||||
|
./scripts/measure_coverage.sh 10 --html # 10 second run, HTML output
|
||||||
|
```
|
||||||
|
|
||||||
|
## What gets measured
|
||||||
|
|
||||||
|
The coverage tool:
|
||||||
|
- Builds the test binary with coverage instrumentation (`--coverage` flag)
|
||||||
|
- Runs the random simulation for the specified duration
|
||||||
|
- Generates reports showing which branches were executed
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
**Text report**: Shows per-file and total branch coverage percentages
|
||||||
|
|
||||||
|
**HTML report**: Interactive report generated by lcov/genhtml showing:
|
||||||
|
- Overall coverage summary
|
||||||
|
- Per-file coverage breakdown
|
||||||
|
- Source code with execution counts
|
||||||
|
- Branch coverage details
|
||||||
|
|
||||||
|
The HTML report is generated in `coverage_report/index.html`
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Fix line endings for coverage scripts
|
||||||
|
|
||||||
|
echo "Fixing line endings for coverage scripts..."
|
||||||
|
|
||||||
|
# Convert CRLF to LF
|
||||||
|
dos2unix scripts/measure_coverage.sh 2>/dev/null || sed -i 's/\r$//' scripts/measure_coverage.sh
|
||||||
|
dos2unix scripts/generate_coverage_html.sh 2>/dev/null || sed -i 's/\r$//' scripts/generate_coverage_html.sh
|
||||||
|
|
||||||
|
# Ensure execute permissions
|
||||||
|
chmod +x scripts/measure_coverage.sh
|
||||||
|
chmod +x scripts/generate_coverage_html.sh
|
||||||
|
|
||||||
|
echo "Done! Line endings fixed and execute permissions set."
|
||||||
|
echo ""
|
||||||
|
echo "You can now run:"
|
||||||
|
echo " make coverage-report"
|
||||||
|
echo " make coverage-html"
|
||||||
Executable
+31
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Generate HTML coverage report using lcov
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
OUTPUT_DIR="coverage_report"
|
||||||
|
|
||||||
|
# Check if lcov is installed
|
||||||
|
if ! command -v lcov &> /dev/null; then
|
||||||
|
echo "Error: lcov is not installed"
|
||||||
|
echo "Please install it with: sudo apt-get install lcov"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Capture coverage data with branch coverage enabled
|
||||||
|
echo "Capturing coverage data..."
|
||||||
|
lcov --capture --directory . --output-file coverage.info --rc lcov_branch_coverage=1
|
||||||
|
|
||||||
|
# Filter out system headers if any exist
|
||||||
|
echo "Filtering coverage data..."
|
||||||
|
lcov --remove coverage.info '/usr/*' --output-file coverage.info --ignore-errors unused --rc lcov_branch_coverage=1 || cp coverage.info coverage.info.bak
|
||||||
|
|
||||||
|
# Generate HTML report
|
||||||
|
echo "Generating HTML report..."
|
||||||
|
genhtml coverage.info --output-directory "$OUTPUT_DIR" --branch-coverage --rc lcov_branch_coverage=1
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -f coverage.info
|
||||||
|
|
||||||
|
echo "HTML report generated in $OUTPUT_DIR/"
|
||||||
|
echo "Open $OUTPUT_DIR/index.html in your browser"
|
||||||
Executable
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script to measure branch coverage of the random simulation
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
echo -e "${BLUE}Branch Coverage Measurement Tool${NC}"
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Clean previous coverage data
|
||||||
|
echo -e "${YELLOW}Cleaning previous coverage data...${NC}"
|
||||||
|
rm -f src/*.gcda src/*.gcno *.gcda *.gcno
|
||||||
|
make clean > /dev/null 2>&1
|
||||||
|
|
||||||
|
# Build with coverage
|
||||||
|
echo -e "${YELLOW}Building with coverage instrumentation...${NC}"
|
||||||
|
make coverage
|
||||||
|
|
||||||
|
# Run the simulation for a limited time
|
||||||
|
echo -e "${YELLOW}Running simulation...${NC}"
|
||||||
|
SIMULATION_TIME=${1:-5} # Default to 5 seconds if not specified
|
||||||
|
echo "Running for ${SIMULATION_TIME} seconds..."
|
||||||
|
|
||||||
|
# Run simulation in background and kill it after specified time
|
||||||
|
timeout ${SIMULATION_TIME}s ./mousefs_random_test_coverage.out || true
|
||||||
|
|
||||||
|
# Generate coverage reports
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Generating coverage reports...${NC}"
|
||||||
|
|
||||||
|
# Find all .gcda files and generate coverage reports
|
||||||
|
GCDA_FILES=$(find . -name "*.gcda")
|
||||||
|
|
||||||
|
TOTAL_BRANCHES=0
|
||||||
|
TAKEN_BRANCHES=0
|
||||||
|
|
||||||
|
# Generate gcov reports from the coverage data files
|
||||||
|
for gcda_file in $GCDA_FILES; do
|
||||||
|
# Extract the source file name from the gcda filename
|
||||||
|
# Files are named like: mousefs_random_test_coverage.out-basic.gcda
|
||||||
|
basename=$(basename "$gcda_file" .gcda)
|
||||||
|
source_name=${basename#*-} # Remove prefix up to and including '-'
|
||||||
|
|
||||||
|
# Run gcov to generate the .gcov file
|
||||||
|
gcov -b "$gcda_file" > /dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
|
||||||
|
# Parse gcov output to count branches
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
echo -e "${BLUE}Branch Coverage Summary${NC}"
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Process each .gcov file
|
||||||
|
for gcov_file in *.c.gcov; do
|
||||||
|
if [ -f "$gcov_file" ]; then
|
||||||
|
# Extract branch statistics from the gcov file
|
||||||
|
branches=$(grep -c "^branch" "$gcov_file" 2>/dev/null)
|
||||||
|
if [ -z "$branches" ]; then branches=0; fi
|
||||||
|
|
||||||
|
if [ "$branches" -gt 0 ]; then
|
||||||
|
taken_count=$(grep "^branch" "$gcov_file" 2>/dev/null | grep -c "taken [1-9]" 2>/dev/null || echo "0")
|
||||||
|
# Clean up the value - remove any whitespace/newlines
|
||||||
|
taken_count=$(echo "$taken_count" | tr -d '[:space:]')
|
||||||
|
if [ -z "$taken_count" ] || [ "$taken_count" = "" ]; then taken_count=0; fi
|
||||||
|
|
||||||
|
TOTAL_BRANCHES=$((TOTAL_BRANCHES + branches))
|
||||||
|
TAKEN_BRANCHES=$((TAKEN_BRANCHES + taken_count))
|
||||||
|
percentage=$((taken_count * 100 / branches))
|
||||||
|
filename=$(echo "$gcov_file" | sed 's/.gcov$//')
|
||||||
|
printf "%-40s %5d / %5d branches (%3d%%)\n" "$filename" "$taken_count" "$branches" "$percentage"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
if [ "$TOTAL_BRANCHES" -gt 0 ]; then
|
||||||
|
COVERAGE_PERCENT=$((TAKEN_BRANCHES * 100 / TOTAL_BRANCHES))
|
||||||
|
echo -e "${GREEN}Total: $TAKEN_BRANCHES / $TOTAL_BRANCHES branches reached (${COVERAGE_PERCENT}%)${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}No branch coverage data found${NC}"
|
||||||
|
fi
|
||||||
|
echo -e "${BLUE}========================================${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Generate HTML report if requested
|
||||||
|
if [ "$2" == "--html" ]; then
|
||||||
|
echo -e "${YELLOW}Generating HTML coverage report...${NC}"
|
||||||
|
# Get the directory where this script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
"$SCRIPT_DIR/generate_coverage_html.sh"
|
||||||
|
echo -e "${GREEN}HTML report generated in coverage_report/index.html${NC}"
|
||||||
|
echo "Open with: firefox coverage_report/index.html (or your preferred browser)"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up gcov files unless HTML was requested
|
||||||
|
if [ "$2" != "--html" ] && [ "$2" != "--detailed" ]; then
|
||||||
|
echo -e "${YELLOW}Cleaning up coverage files...${NC}"
|
||||||
|
rm -f *.gcov
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}Coverage measurement complete!${NC}"
|
||||||
+9
-1
@@ -8,12 +8,20 @@
|
|||||||
|
|
||||||
static sig_atomic_t simulation_should_stop = false;
|
static sig_atomic_t simulation_should_stop = false;
|
||||||
|
|
||||||
|
static void signal_handler(int signum)
|
||||||
|
{
|
||||||
|
(void)signum;
|
||||||
|
simulation_should_stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
// TODO: set simulation_should_stop=true on ctrl+C
|
// Set up signal handlers for clean shutdown
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
signal(SIGTERM, signal_handler);
|
||||||
|
|
||||||
startup_simulation(2);
|
startup_simulation(2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user