diff --git a/Makefile b/Makefile index d8c62fc..74fdbff 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ CFLAGS = -Wall -Wextra -ggdb +COVERAGE_CFLAGS = $(CFLAGS) --coverage +COVERAGE_LFLAGS = --coverage ifeq ($(OS),Windows_NT) LFLAGS = -lws2_32 @@ -13,16 +15,21 @@ CFILES = $(shell find src -name '*.c') HFILES = $(shell find src -name '*.h') OFILES = $(CFILES:.c=.o) -.PHONY: all clean +.PHONY: all clean coverage all: mousefs$(EXT) mousefs_random_test$(EXT) example_client$(EXT) libmousefs.a +coverage: mousefs_random_test_coverage$(EXT) + mousefs$(EXT): $(CFILES) $(HFILES) gcc -o $@ $(CFILES) $(CFLAGS) $(LFLAGS) -Iinc -DBUILD_SERVER mousefs_random_test$(EXT): $(CFILES) $(HFILES) 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 gcc -o $@ examples/main.c $(CFLAGS) -lmousefs $(LFLAGS) -Iinc -L. @@ -33,12 +40,18 @@ libmousefs.a: $(OFILES) ar rcs $@ $^ clean: - rm -f \ - mousefs.exe \ - mousefs.out \ - mousefs_random_test.exe \ - mousefs_random_test.out \ - example_client.exe \ - example_client.out \ - libmousefs.a \ - src/*.o + rm -f \ + mousefs.exe \ + mousefs.out \ + mousefs_random_test.exe \ + mousefs_random_test.out \ + mousefs_random_test_coverage.exe \ + mousefs_random_test_coverage.out \ + example_client.exe \ + example_client.out \ + libmousefs.a \ + src/*.o \ + src/*.gcda \ + src/*.gcno \ + *.gcda \ + *.gcno diff --git a/measure_coverage.sh b/measure_coverage.sh new file mode 100755 index 0000000..d513ec8 --- /dev/null +++ b/measure_coverage.sh @@ -0,0 +1,106 @@ +#!/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 + +# Optionally show detailed coverage for specific files +if [ "$2" == "--detailed" ]; then + echo -e "${YELLOW}Detailed coverage reports available in *.gcov files${NC}" + echo "Use 'less .gcov' to view detailed line and branch coverage" +fi + +# Clean up gcov files +echo -e "${YELLOW}Cleaning up coverage files...${NC}" +rm -f *.gcov + +echo +echo -e "${GREEN}Coverage measurement complete!${NC}" diff --git a/src/main_test.c b/src/main_test.c index 294a0e7..17d0cfb 100644 --- a/src/main_test.c +++ b/src/main_test.c @@ -8,12 +8,20 @@ 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) { (void)argc; (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);