From d92d97aef618679b1f0309d648c507d5913c63d6 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Tue, 5 Dec 2023 17:00:52 -0800 Subject: [PATCH] Add Scheme coverage collection with option GUILE_COVERAGE. This can be used with or without COVERAGE, though if without the results will reflect only the Scheme code exercised by the tests. --- CMakeLists.txt | 3 +- bindings/guile/test/srfi64-extras.scm | 2 +- common/cmake_modules/GncAddTest.cmake | 53 +++++++++++++++++++++----- common/cmake_modules/GncCoverage.cmake | 2 +- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7660a7f55e..4ec3c712a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ option (WITH_PYTHON "enable python plugin and bindings" OFF) option (ENABLE_BINRELOC "compile with binary relocation support" ON) option (DISABLE_NLS "do not use Native Language Support" OFF) option (COVERAGE "Instrument a Debug or Asan build for coverage reporting" OFF) +option (GUILE_COVERAGE "Compute testing coverage of Scheme code. WARNING: 15X slowdown!" OFF) option (LEAKS "Report leaks for tests in a non-Apple Asan build." OFF) option (ODR "Report One Definition Rule violations in tests in a non-Apple Asan build." OFF) # ############################################################ @@ -627,7 +628,7 @@ elseif(UNIX) set(ASAN_DYNAMIC_LIB_ENV LD_PRELOAD=${PRELOADS}) endif () set(ASAN_LINK_OPTIONS -fsanitize=address -fsanitize=undefined) -if (COVERAGE) +if (COVERAGE OR GUILE_COVERAGE) include(GncCoverage) endif() if (COVERAGE) diff --git a/bindings/guile/test/srfi64-extras.scm b/bindings/guile/test/srfi64-extras.scm index e572e988a8..b41baee432 100644 --- a/bindings/guile/test/srfi64-extras.scm +++ b/bindings/guile/test/srfi64-extras.scm @@ -45,5 +45,5 @@ (lambda (runner) (format #t "Source:~a\npass = ~a, fail = ~a\n" (test-result-ref runner 'source-file) num-passed num-failed) - (exit (zero? num-failed)))) + (zero? num-failed))) runner)) diff --git a/common/cmake_modules/GncAddTest.cmake b/common/cmake_modules/GncAddTest.cmake index 09c04e0388..ef3c96aa45 100644 --- a/common/cmake_modules/GncAddTest.cmake +++ b/common/cmake_modules/GncAddTest.cmake @@ -34,6 +34,15 @@ function(get_guile_env) set(guile_load_paths "") list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}") list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/deprecated") # Path to gnucash' deprecated modules + if (GUILE_COVERAGE) + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash") + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/report") + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/reports") + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/engine") + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/app-utils") + list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/qif-import") + + endif() set(guile_load_path "${guile_load_paths}") set(guile_load_compiled_paths "") @@ -103,20 +112,46 @@ function(gnc_add_test_with_guile _TARGET _SOURCE_FILES TEST_INCLUDE_VAR_NAME TES ) endfunction() - function(gnc_add_scheme_test _TARGET _SOURCE_FILE) - add_test(NAME ${_TARGET} COMMAND ${GUILE_EXECUTABLE} --debug -c " - (set! %load-hook + if (GUILE_COVERAGE) + add_test(NAME ${_TARGET} COMMAND ${GUILE_EXECUTABLE} --debug -c " + (set! %load-hook (lambda (filename) - (when (and filename - (string-contains filename \"${GUILE_REL_SITEDIR}\") - (not (string-prefix? \"${CMAKE_BINARY_DIR}\" filename))) + (when (and filename + (string-contains filename \"${GUILE_REL_SITEDIR}\") + (not (string-prefix? \"${CMAKE_BINARY_DIR}\" filename))) (format #t \"%load-path = ~s~%\" %load-path) (format #t \"%load-compiled-path = ~s~%\" %load-compiled-path) (error \"Loading guile/site file from outside build tree!\" filename)))) - (load-from-path \"${_TARGET}\") - (exit (run-test))" - ) + (load-from-path \"${_TARGET}\") + (use-modules (system vm coverage) + (system vm vm)) + (call-with-values (lambda () + (with-code-coverage + (lambda () + (run-test)))) + + (lambda (data result) + (let ((port (open-output-file \"${coverage_dir}/${_TARGET}_results.info\"))) + (coverage-data->lcov data port) + (close port)) + (exit result))) +" + ) + else() + add_test(NAME ${_TARGET} COMMAND ${GUILE_EXECUTABLE} --debug -c " + (set! %load-hook + (lambda (filename) + (when (and filename + (string-contains filename \"${GUILE_REL_SITEDIR}\") + (not (string-prefix? \"${CMAKE_BINARY_DIR}\" filename))) + (format #t \"%load-path = ~s~%\" %load-path) + (format #t \"%load-compiled-path = ~s~%\" %load-compiled-path) + (error \"Loading guile/site file from outside build tree!\" filename)))) + (load-from-path \"${_TARGET}\") + (exit (run-test))" + ) + endif() get_guile_env() set_tests_properties(${_TARGET} PROPERTIES ENVIRONMENT "${GUILE_ENV}$<$:;${ASAN_DYNAMIC_LIB_ENV};ASAN_OPTIONS=${ASAN_TEST_OPTIONS}>;${ARGN}>") endfunction() diff --git a/common/cmake_modules/GncCoverage.cmake b/common/cmake_modules/GncCoverage.cmake index 79dde288a0..64843d1f71 100644 --- a/common/cmake_modules/GncCoverage.cmake +++ b/common/cmake_modules/GncCoverage.cmake @@ -14,7 +14,7 @@ # --branch-coverage; to ensure branch info is saved # --demangle-cpp; requires c++filt -if (COVERAGE) +if (COVERAGE OR GUILE_COVERAGE) find_program(LCOV lcov) find_program(GENINFO geninfo) find_program(GENHTML genhtml)