Commit e45535849cb7187e22c9fd11d14e0eb37f5d7dc8

Ramsay Jones 2009-08-19T17:06:39

Add test-suite coverage testing using gcov Add a new "coverage" Makefile target that re-builds the library and tests using the gcc compiler/linker flags required by gcov, runs the test suite to capture the runtime data, then compiles a coverage report. The report, which is saved in a file named "untested", consists of a list of untested files, followed by a list of untested functions. More detailed execution statistics are given in the gcov log files which are saved in the top-level directory (named like src#hash.c.gcov). Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>

diff --git a/.gitignore b/.gitignore
index 66ce776..5c7507c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@
 *.o
 *.a
 *.exe
+*.gcda
+*.gcno
+*.gcov
diff --git a/Makefile b/Makefile
index dfae6ed..a0a6eea 100644
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,7 @@ clean:
 	rm -rf apidocs
 	rm -f *~ src/*~ src/git/*~ src/sha1/*~ src/unix/*~ src/win32/*~
 	@$(MAKE) -C tests -s --no-print-directory clean
+	@$(MAKE) -s --no-print-directory cov-clean
 
 test-clean:
 	@$(MAKE) -C tests -s --no-print-directory clean
@@ -134,3 +135,41 @@ libgit2.pc: libgit2.pc.in
 .PHONY: install-headers
 .PHONY: install uninstall
 .PHONY: sparse
+
+### Test suite coverage testing
+#
+.PHONY: coverage cov-clean cov-build cov-report
+
+COV_GCDA = $(patsubst %.c,%.gcda,$(SRC_C))
+COV_GCNO = $(patsubst %.c,%.gcno,$(SRC_C))
+
+coverage:
+	@$(MAKE) -s --no-print-directory clean
+	@$(MAKE) --no-print-directory cov-build
+	@$(MAKE) --no-print-directory cov-report
+
+cov-clean:
+	rm -f $(COV_GCDA) $(COV_GCNO) *.gcov untested
+
+COV_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
+
+cov-build:
+	$(MAKE) CFLAGS="$(COV_CFLAGS)" all
+	$(MAKE) TEST_COVERAGE=1 NO_OPENSSL=$(NO_OPENSSL) test
+
+cov-report:
+	@echo "--- untested files:" | tee untested
+	@{ for f in $(SRC_C); do \
+		gcda=$$(dirname $$f)"/"$$(basename $$f .c)".gcda"; \
+		if test -f $$gcda; then \
+			gcov -b -p -o $$(dirname $$f) $$f >/dev/null; \
+		else \
+			echo $$f | tee -a untested; \
+		fi; \
+	   done; }
+	@rm -f *.h.gcov
+	@echo "--- untested functions:" | tee -a untested
+	@grep '^function .* called 0' *.c.gcov \
+	| sed -e 's/\([^:]*\)\.gcov:function \([^ ]*\) called.*/\1: \2/' \
+	| sed -e 's|#|/|g' | tee -a untested
+
diff --git a/tests/Makefile b/tests/Makefile
index 813b246..2ad730b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -25,6 +25,10 @@ TEST_EXE = $(patsubst %.o,%.exe,$(TEST_OBJ))
 TEST_RUN = $(patsubst %.exe,%.run,$(TEST_EXE))
 TEST_VAL = $(patsubst %.exe,%.val,$(TEST_EXE))
 
+ifdef TEST_COVERAGE
+	EXTRA_LIBS += -O0 -lgcov
+endif
+
 ifndef NO_OPENSSL
 	EXTRA_LIBS += $(CRYPTO_LIB)
 endif
@@ -32,7 +36,7 @@ endif
 BASIC_CFLAGS := -I../src
 
 ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS)
-LIBS += $(EXTRA_LIBS)
+ALL_LIBS = $(LIBS) $(EXTRA_LIBS)
 
 all:: $(TEST_RUN)
 
@@ -74,7 +78,7 @@ $(TEST_EXE): %.exe: %.o %_main.o
 	$(LD) -o $@ \
 		$(patsubst %.exe,%_main.o,$@) \
 		$(patsubst %.exe,%.o,$@) \
-		$(T_LIB) $(LIBS)
+		$(T_LIB) $(ALL_LIBS)
 
 $(TEST_RUN): %.run: %.exe
 	@t=trash-$(<F) && \