Merge John Ralls's 'asan' into stable.

This commit is contained in:
John Ralls 2023-12-08 14:56:29 -08:00
commit e22a57ad26
47 changed files with 545 additions and 135 deletions

View File

@ -8,33 +8,70 @@ jobs:
env:
TZ: America/Los_Angeles
steps:
- name: Checkout
uses: actions/checkout@v3
- run: sudo apt-get update
- name: Install additional dependencies
run: sudo apt-get install -y gettext cmake libxslt-dev xsltproc ninja-build libboost-all-dev libgtk-3-dev guile-2.2-dev libgwengui-gtk3-dev libaqbanking-dev libofx-dev libdbi-dev libdbd-sqlite3 libwebkit2gtk-4.0-dev googletest
- name: Install language packs.
run: sudo apt-get --reinstall install -y language-pack-en language-pack-fr
- run: |
echo "ROOT_DIR=$GITHUB_WORKSPACE/.." >> $GITHUB_ENV
- name: Create Directories
run: |
pwd
mkdir $ROOT_DIR/inst
mkdir build
- name: Configure GnuCash
run: |
cd build
cmake -G Ninja -DWITH_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$ROOT_DIR/inst $GITHUB_WORKSPACE
- name: Build and Test GnuCash
run: |
cd build
ninja
ninja distcheck
env:
CTEST_OUTPUT_ON_FAILURE: On
- uses: actions/upload-artifact@v3
if: failure()
with:
name: TestLog
path: ${{ github.workspace }}/build/Testing/Temporary/LastTest.log
- name: Checkout
uses: actions/checkout@v3
- run: sudo apt-get update
- name: Install additional dependencies
run: sudo apt-get install -y gettext cmake libxslt-dev xsltproc ninja-build libboost-all-dev libgtk-3-dev guile-2.2-dev libgwengui-gtk3-dev libaqbanking-dev libofx-dev libdbi-dev libdbd-sqlite3 libwebkit2gtk-4.0-dev googletest
- name: Install language packs.
run: sudo apt-get --reinstall install -y language-pack-en language-pack-fr
- run: |
echo "ROOT_DIR=$GITHUB_WORKSPACE/.." >> $GITHUB_ENV
- name: Create Directories
run: |
pwd
mkdir $ROOT_DIR/inst
mkdir build
- name: Configure GnuCash
run: |
cd build
cmake -G Ninja -DWITH_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$ROOT_DIR/inst $GITHUB_WORKSPACE
- name: Build and Test GnuCash
run: |
cd build
ninja
ninja distcheck
env:
CTEST_OUTPUT_ON_FAILURE: On
- uses: actions/upload-artifact@v3
if: failure()
with:
name: TestLog
path: ${{ github.workspace }}/build/Testing/Temporary/LastTest.log
ci_tests_ASAN:
runs-on: ubuntu-latest
name: Address Sanitizer CI Tests
continue-on-error: true
env:
TZ: America/Los_Angeles
steps:
- name: Checkout
uses: actions/checkout@v3
- run: sudo apt-get update
- name: Install additional dependencies
run: sudo apt-get install -y gettext cmake libxslt-dev xsltproc ninja-build libboost-all-dev libgtk-3-dev guile-2.2-dev libgwengui-gtk3-dev libaqbanking-dev libofx-dev libdbi-dev libdbd-sqlite3 libwebkit2gtk-4.0-dev googletest
- name: Install language packs.
run: sudo apt-get --reinstall install -y language-pack-en language-pack-fr
- run: |
echo "ROOT_DIR=$GITHUB_WORKSPACE/.." >> $GITHUB_ENV
- name: Create Directories
run: |
pwd
mkdir $ROOT_DIR/inst
mkdir build
- name: Configure GnuCash
run: |
cd build
cmake -G Ninja -DWITH_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$ROOT_DIR/inst $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Asan
- name: Build and Test GnuCash
run: |
cd build
ninja
ninja check
env:
CTEST_OUTPUT_ON_FAILURE: On
- uses: actions/upload-artifact@v3
if: failure()
with:
name: TestLog
path: ${{ github.workspace }}/build/Testing/Temporary/LastTest.log

66
.github/workflows/coverage.yml vendored Normal file
View File

@ -0,0 +1,66 @@
name: coverage
on: push
permissions: {}
jobs:
coverage:
runs-on: ubuntu-latest
name: C++ Code coverage analysis
continue-on-error: true
env:
TZ: America/Los_Angeles
steps:
- name: Checkout
uses: actions/checkout@v3
- run: sudo apt-get update
- name: Install additional dependencies
run: sudo apt-get install -y gettext cmake libxslt-dev xsltproc ninja-build libboost-all-dev libgtk-3-dev guile-2.2-dev libgwengui-gtk3-dev libaqbanking-dev libofx-dev libdbi-dev libdbd-sqlite3 libwebkit2gtk-4.0-dev googletest lcov
- name: Install language packs.
run: sudo apt-get --reinstall install -y language-pack-en language-pack-fr
- run: |
echo "ROOT_DIR=$GITHUB_WORKSPACE/.." >> $GITHUB_ENV
- name: Create Directories
run: |
pwd
mkdir $ROOT_DIR/inst
mkdir build
- name: Configure GnuCash
run: |
cd build
cmake -G Ninja -DWITH_PYTHON=ON -DCMAKE_INSTALL_PREFIX=$ROOT_DIR/inst $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE=ON
- name: Build and test GnuCash with coverage analysis
run: |
cd build
ninja
ninja lcov-initialize
ninja check
ninja -k 0 lcov-collect
ninja lcov-generate-html
env:
CTEST_OUTPUT_ON_FAILURE: Off
- name: prepare_upload
if: success()
run: |
mkdir build/github-pages
mv build/Coverage-HTML build/github-pages/
chmod -v -R +rX "build/github-pages" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: Upload pages
uses: actions/upload-pages-artifact@v2
if: success()
with:
path: ${{ github.workspace }}/build/github-pages
deploy-coverage:
needs: coverage
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Publish
id: deployment
uses: actions/deploy-pages@v2

View File

@ -54,6 +54,10 @@ option (WITH_OFX "compile with ofx support (needs LibOFX)" ON)
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)
# ############################################################
# These are also settable from the command line in a similar way.
@ -610,6 +614,48 @@ if (MINGW)
set( CMAKE_CXX_FLAGS "-DWINVER=0x0500 -D_EMULATE_GLIBC=0 ${CMAKE_CXX_FLAGS}") # Workaround for bug in gtest on mingw, see https://github.com/google/googletest/issues/893 and https://github.com/google/googletest/issues/920
endif()
if (APPLE)
execute_process(COMMAND clang --print-file-name=libclang_rt.asan_osx_dynamic.dylib
OUTPUT_VARIABLE ASAN_DYNAMIC_LIB
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(ASAN_DYNAMIC_LIB_ENV "DYLD_INSERT_LIBRARIES=${ASAN_DYNAMIC_LIB}")
set(ASAN_BUILD_OPTIONS fast_unwind_on_malloc=0)
elseif(UNIX)
execute_process(COMMAND gcc -print-file-name=libasan.so OUTPUT_VARIABLE LIBASAN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND gcc -print-file-name=libstdc++.so OUTPUT_VARIABLE LIBSTDCXX_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
set(PRELOADS "${LIBASAN_PATH}:${LIBSTDCXX_PATH}")
set(ASAN_BUILD_OPTIONS "detect_leaks=0:fast_unwind_on_malloc=0")
set(ASAN_DYNAMIC_LIB_ENV LD_PRELOAD=${PRELOADS})
endif ()
set(ASAN_LINK_OPTIONS -fsanitize=address -fsanitize=undefined)
if (COVERAGE OR GUILE_COVERAGE)
include(GncCoverage)
endif()
if (COVERAGE)
set(COVERAGE_COMPILE_OPTION --coverage)
add_compile_options("$<$<CONFIG:Debug>:${COVERAGE_COMPILE_OPTION}>")
add_link_options("$<$<CONFIG:Debug>:${COVERAGE_COMPILE_OPTION}>")
list(APPEND ASAN_LINK_OPTIONS ${COVERAGE_COMPILE_OPTION})
endif()
set(ASAN_COMPILE_OPTIONS -g ${ASAN_LINK_OPTIONS})
add_compile_options("$<$<CONFIG:Asan>:${ASAN_COMPILE_OPTIONS}>")
add_link_options("$<$<CONFIG:Asan>:${ASAN_LINK_OPTIONS}>")
# See https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags
set(ASAN_TEST_OPTIONS fast_unwind_on_malloc=0)
if (UNIX AND NOT APPLE)
if (LEAKS)
list(APPEND ASAN_TEST_OPTIONS detect_leaks=1)
else()
list(APPEND ASAN_TEST_OPTIONS detect_leaks=0)
endif()
if (ODR)
list(APPEND ASAN_TEST_OPTIONS detect_odr_violation=2)
else()
list(APPEND ASAN_TEST_OPTIONS detect_odr_violation=0)
endif()
string(REPLACE ";" ":" ASAN_TEST_OPTIONS "${ASAN_TEST_OPTIONS}")
endif()
if (APPLE AND WITH_GNUCASH)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
@ -650,6 +696,10 @@ add_custom_target(check
COMMAND ${CMAKE_CTEST_COMMAND}
)
if (COVERAGE)
add_dependencies(check lcov-initialize)
endif()
set(gnucash_DOCS
AUTHORS
ChangeLog.1999

View File

@ -1725,13 +1725,13 @@ gnc_register_multichoice_callback_option(GncOptionDBPtr& db,
static void
test_book_set_data(QofBook* book, const char* key, void* data)
{
qof_book_set_data(book, key, data);
qof_book_set_data(book, key, data);
}
static void
test_book_clear_data(QofBook* book, const char* key)
{
qof_book_set_data(book, key, nullptr);
qof_book_set_data(book, key, nullptr);
}
static void

View File

@ -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))

View File

@ -96,6 +96,7 @@ if(WITH_PYTHON)
add_test(NAME sqlite3test COMMAND sqlite3test)
add_dependencies(check sqlite3test)
set_tests_properties(sqlite3test PROPERTIES ENVIRONMENT "$<$<CONFIG:Asan>:;ASAN_OPTIONS=${ASAN_TEST_OPTIONS}>")
install(TARGETS gnucash_core_c
LIBRARY DESTINATION ${PYTHON_SYSCONFIG_OUTPUT}/gnucash

View File

@ -7,11 +7,11 @@ if (WITH_PYTHON)
endif()
add_custom_target(test-python-bindings ALL DEPENDS unittest_support gnucash-core-c-build gnucash-core-c-py sw-core-utils-build sw-core-utils-py sw-app-utils-build sw-app-utils-py)
add_dependencies(check test-python-bindings)
add_test(python-bindings ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/runTests.py.in)
set_property(TEST python-bindings PROPERTY ENVIRONMENT
GNC_BUILDDIR=${CMAKE_BINARY_DIR}
PYTHONPATH=${PYTHON_SYSCONFIG_BUILD}:${LIBDIR_BUILD}/gnucash:${test_core_dir}
)
add_test(NAME python-bindings COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/runTests.py.in)
set(PYTHON_ENV "GNC_UNINSTALLED=1;GNC_BUILDDIR=${CMAKE_BINARY_DIR};PYTHONPATH=${PYTHON_SYSCONFIG_BUILD}:${LIBDIR_BUILD}/gnucash:${test_core_dir}")
set(ASAN_ENV "${ASAN_DYNAMIC_LIB_ENV};ASAN_OPTIONS=${ASAN_TEST_OPTIONS}")
set_tests_properties(python-bindings PROPERTIES ENVIRONMENT "$<IF:$<CONFIG:Asan>,${PYTHON_ENV};${ASAN_ENV},${PYTHON_ENV}>")
endif()
set(test_python_bindings_DATA

View File

@ -266,18 +266,23 @@ function(gnc_add_scheme_targets _TARGET)
message(" GNC_MODULE_PATH: ${_GNC_MODULE_PATH}")
endif()
#We quote the arguments to stop CMake stripping the path separators.
set (GUILE_ENV
"${LIBRARY_PATH}"
"GNC_UNINSTALLED=YES"
"GNC_BUILDDIR=${CMAKE_BINARY_DIR}"
"GUILE_LOAD_PATH=${_GUILE_LOAD_PATH}"
"GUILE_LOAD_COMPILED_PATH=${_GUILE_LOAD_COMPILED_PATH}"
"GNC_MODULE_PATH=${_GNC_MODULE_PATH}"
)
add_custom_command(
OUTPUT ${output_file}
COMMAND ${CMAKE_COMMAND} -E env
"${LIBRARY_PATH}"
"GNC_UNINSTALLED=YES"
"GNC_BUILDDIR=${CMAKE_BINARY_DIR}"
"GUILE_LOAD_PATH=${_GUILE_LOAD_PATH}"
"GUILE_LOAD_COMPILED_PATH=${_GUILE_LOAD_COMPILED_PATH}"
"GNC_MODULE_PATH=${_GNC_MODULE_PATH}"
"${GUILE_ENV}$<$<CONFIG:Asan>:;${ASAN_DYNAMIC_LIB_ENV};ASAN_OPTIONS=${ASAN_BUILD_OPTIONS}>"
${GUILE_EXECUTABLE} -e "\(@@ \(guild\) main\)" -s ${GUILD_EXECUTABLE} compile -o ${output_file} ${source_file_abs_path}
DEPENDS ${guile_depends}
MAIN_DEPENDENCY ${source_file_abs_path}
COMMAND_EXPAND_LISTS
VERBATIM
)
endforeach(source_file)

View File

@ -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 "")
@ -77,49 +86,74 @@ function(gnc_add_test _TARGET _SOURCE_FILES TEST_INCLUDE_VAR_NAME TEST_LIBS_VAR_
# Extra arguments are treated as environment variables
set(HAVE_ENV_VARS TRUE)
endif()
set(ENVVARS "GNC_UNINSTALLED=YES;GNC_BUILDDIR=${CMAKE_BINARY_DIR}")
if (HAVE_ENV_VARS)
list(APPEND ENVVARS ${ARGN})
endif()
set(TEST_INCLUDE_DIRS ${${TEST_INCLUDE_VAR_NAME}})
set(TEST_LIBS ${${TEST_LIBS_VAR_NAME}})
set_source_files_properties (${_SOURCE_FILES} PROPERTIES OBJECT_DEPENDS ${CONFIG_H})
add_executable(${_TARGET} EXCLUDE_FROM_ALL ${_SOURCE_FILES})
target_link_libraries(${_TARGET} ${TEST_LIBS})
target_include_directories(${_TARGET} PRIVATE ${TEST_INCLUDE_DIRS})
if (${HAVE_ENV_VARS})
add_test(${_TARGET} ${CMAKE_BINARY_DIR}/bin/${_TARGET})
set_tests_properties(${_TARGET} PROPERTIES ENVIRONMENT "GNC_UNINSTALLED=YES;GNC_BUILDDIR=${CMAKE_BINARY_DIR};${ARGN}")
if (CMAKE_GENERATOR STREQUAL Xcode)
add_test(NAME ${_TARGET} COMMAND ${_TARGET} CONFIGURATIONS Debug;Release)
else()
if (CMAKE_GENERATOR STREQUAL Xcode)
add_test(NAME ${_TARGET} COMMAND ${_TARGET} CONFIGURATIONS Debug;Release)
else()
add_test(NAME ${_TARGET} COMMAND ${_TARGET})
endif()
set_tests_properties(${_TARGET} PROPERTIES ENVIRONMENT "GNC_UNINSTALLED=YES;GNC_BUILDDIR=${CMAKE_BINARY_DIR}")
add_test(NAME ${_TARGET} COMMAND ${_TARGET})
endif()
add_executable(${_TARGET} EXCLUDE_FROM_ALL ${_SOURCE_FILES})
target_link_libraries(${_TARGET} PRIVATE ${TEST_LIBS})
target_include_directories(${_TARGET} PRIVATE ${TEST_INCLUDE_DIRS})
set_tests_properties(${_TARGET} PROPERTIES ENVIRONMENT "${ENVVARS}$<$<CONFIG:Asan>:;ASAN_OPTIONS=${ASAN_TEST_OPTIONS}>")
add_dependencies(check ${_TARGET})
endfunction()
function(gnc_add_test_with_guile _TARGET _SOURCE_FILES TEST_INCLUDE_VAR_NAME TEST_LIBS_VAR_NAME)
get_guile_env()
gnc_add_test(${_TARGET} "${_SOURCE_FILES}" "${TEST_INCLUDE_VAR_NAME}" "${TEST_LIBS_VAR_NAME}"
"${GUILE_ENV};${ARGN}"
"${GUILE_ENV}$<$<CONFIG:Asan>:;${ASAN_DYNAMIC_LIB_ENV}>;${ARGN}"
)
endfunction()
function(gnc_add_scheme_test _TARGET _SOURCE_FILE)
add_test(${_TARGET} ${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};${ARGN}")
set_tests_properties(${_TARGET} PROPERTIES ENVIRONMENT "${GUILE_ENV}$<$<CONFIG:Asan>:;${ASAN_DYNAMIC_LIB_ENV};ASAN_OPTIONS=${ASAN_TEST_OPTIONS}>;${ARGN}>")
endfunction()
function(gnc_add_scheme_tests _SOURCE_FILES)

View File

@ -0,0 +1,111 @@
#lcov command options:
# -a, --add-tracefile (takes glob)
# -c, --capture; create a trace file from the .da files
# -e, --extract; a reduced scope for analysis
# -l, --list; the contents of a tracefile
# -r, --remove; remove pattern-match from tracefile
# -z, --zerocounters; run this first, then -c -i
# --diff
# --summary
# other necessary options:
# --directory; points to the source root. If left off it analyzes the kernel
# --no-external; only analyze code in --directory
# --build-directory; where the .no when different from the .da files
# --branch-coverage; to ensure branch info is saved
# --demangle-cpp; requires c++filt
if (COVERAGE OR GUILE_COVERAGE)
find_program(LCOV lcov)
find_program(GENINFO geninfo)
find_program(GENHTML genhtml)
find_program(CPPFILT c++filt)
if (NOT LCOV OR NOT GENINFO OR NOT GENHTML OR NOT CPPFILT)
MESSAGE(WARNING "A required program for presenting coverage information isn't available, disabling coverage")
set(COVERAGE OFF CACHE INTERNAL "")
return()
endif()
else()
return()
endif()
execute_process(COMMAND lcov --version OUTPUT_VARIABLE lcov_version_response)
string(REGEX MATCH "[-.0-9]+" lcov_version ${lcov_version_response})
set(LCOV_VERSION ${lcov_version} CACHE INTERNAL "")
set(excludes_arg "")
foreach (sys_path ${CMAKE_SYSTEM_PREFIX_PATH})
list(APPEND excludes_arg "--exclude" "${sys_path}/*")
endforeach()
set(ignores_arg "--ignore-errors" "unused,unused" "--ignore-errors" "mismatch,mismatch"
"--ignore-errors" "empty,empty")
list(APPEND ignores_arg "--rc" "geninfo_unexecuted_blocks=1")
set(generate_flags "")
set(geninfo_flags --quiet ${excludes_arg})
if (LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
list(APPEND geninfo_flags ${ignores_arg})
list(APPEND generate_flags "--branch-coverage" "--demangle-cpp" "c++filt")
else()
list(APPEND generate_flags "--rc" "lcov_branch_coverage=1" "--rc" "genhtml_demangle_cpp=1")
endif()
set(coverage_dir "${CMAKE_BINARY_DIR}/Coverage" CACHE INTERNAL "Directory to accumulate coverage tracefiles")
set(coverage_html_dir "${CMAKE_BINARY_DIR}/Coverage-HTML" CACHE INTERNAL "Directory to place HTML coverage results pages")
file(MAKE_DIRECTORY ${coverage_dir})
add_custom_target(lcov-initialize)
if (LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_custom_target(lcov-collect
COMMAND lcov ${geninfo_flags} -a ${coverage_dir}/*.info -o ${coverage_dir}/gnucash.info
COMMAND lcov --summary ${coverage_dir}/gnucash.info
VERBATIM
COMMAND_EXPAND_LISTS)
else()
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/collect.sh
CONTENT
"#!/bin/bash
if [ -e $2 ]
then rm $2
fi
j=\"\"
for i in $1/*.info
do j=\"$j -a $i\"
done
lcov $j -o $2
"
FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE WORLD_EXECUTE)
add_custom_target(lcov-collect
COMMAND ${CMAKE_COMMAND} -E env ${CMAKE_BINARY_DIR}/collect.sh ${coverage_dir} ${coverage_dir}/gnucash.info
DEPENDS ${CMAKE_BINARY_DIR}/collect.sh
VERBATIM
COMMAND_EXPAND_LISTS)
endif()
set_target_properties(lcov-collect PROPERTIES ADDITIONAL_CLEAN_FILES "${coverage_dir}/gnucash.info")
add_custom_target(lcov-generate-html
genhtml --quiet --output-directory "${coverage_html_dir}" --legend --function-coverage ${generate_flags} ${coverage_dir}/gnucash.info
VERBATIM
COMMAND_EXPAND_LISTS)
set_target_properties(lcov-generate-html PROPERTIES ADDITIONAL_CLEAN_FILES "${coverage_html_dir}")
function (add_coverage_target tgt)
get_target_property(build_dir ${tgt} BINARY_DIR)
set(target_dir "${build_dir}/CMakeFiles/${tgt}.dir")
add_custom_target(lcov-initialize-${tgt}
lcov ${geninfo_flags} -z --directory ${target_dir}
COMMAND lcov ${geninfo_flags} ${generate_flags} -c -i --directory ${target_dir} -o "${coverage_dir}/${tgt}_base.info"
VERBATIM
COMMAND_EXPAND_LISTS)
add_dependencies(lcov-initialize lcov-initialize-${tgt})
add_dependencies(lcov-initialize-${tgt} ${tgt})
add_custom_target(lcov-collect-${tgt}
COMMAND lcov ${geninfo_flags} ${generate_flags} -c --directory ${target_dir} -o "${coverage_dir}/${tgt}_result.info"
VERBATIM
COMMAND_EXPAND_LISTS)
add_dependencies(lcov-collect lcov-collect-${tgt})
set_target_properties(${tgt} PROPERTIES ADDITIONAL_CLEAN_FILES "${coverage_dir}/${tgt}_base.info;${coverage_dir}/${tgt}_result.info")
endFunction()

View File

@ -160,6 +160,11 @@ if (MAC_INTEGRATION)
target_link_options(gnucash-cli PRIVATE -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_SOURCE_DIR}/Info.plist)
endif()
if (COVERAGE AND LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_coverage_target(gnucash)
add_coverage_target(gnucash-cli)
endif()
install(TARGETS gnucash gnucash-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
# No headers to install.

View File

@ -55,6 +55,10 @@ if (APPLE)
set_target_properties (gnc-gnome-search PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-gnome-search)
endif()
install(TARGETS gnc-gnome-search
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -224,6 +224,10 @@ if (MAC_INTEGRATION)
target_link_libraries(gnc-gnome-utils ${OSX_EXTRA_LIBRARIES})
endif()
if (COVERAGE)
add_coverage_target(gnc-gnome-utils)
endif()
target_include_directories(gnc-gnome-utils
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}

View File

@ -163,6 +163,9 @@ if (MAC_INTEGRATION)
target_link_libraries(gnc-gnome ${OSX_EXTRA_LIBRARIES})
endif()
if (COVERAGE)
add_coverage_target(gnc-gnome)
endif()
install(TARGETS gnc-gnome
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -73,6 +73,11 @@ if (APPLE)
endif()
add_dependencies(gnc-html swig-gnc-html-c)
if (COVERAGE)
add_coverage_target(gnc-html)
endif()
install(TARGETS gnc-html
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -61,6 +61,10 @@ if (APPLE)
set_target_properties (gnc-generic-import PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if (COVERAGE)
add_coverage_target(gnc-generic-import)
endif()
install(TARGETS gnc-generic-import
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -81,6 +81,10 @@ if(WITH_AQBANKING)
set_target_properties (gncmod-aqbanking PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gncmod-aqbanking)
endif()
install(TARGETS gncmod-aqbanking
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -37,6 +37,10 @@ if (APPLE)
set_target_properties (gnc-bi-import PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE AND LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_coverage_target(gnc-bi-import)
endif()
install(TARGETS gnc-bi-import
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -43,6 +43,10 @@ if (APPLE)
set_target_properties (gnc-csv-export PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-csv-export)
endif()
install(TARGETS gnc-csv-export
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -84,6 +84,10 @@ if (APPLE)
set_target_properties (gnc-csv-import PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-csv-import)
endif()
install(TARGETS gnc-csv-import
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -35,6 +35,10 @@ if (APPLE)
set_target_properties (gnc-customer-import PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (0 AND COVERAGE) # Generates no coverage data
add_coverage_target(gnc-customer-import)
endif()
install(TARGETS gnc-customer-import
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -32,6 +32,10 @@ if (APPLE)
set_target_properties (gnc-log-replay PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE AND LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_coverage_target(gnc-log-replay)
endif()
install(TARGETS gnc-log-replay
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -48,6 +48,10 @@ if (WITH_OFX)
set_target_properties (gncmod-ofx PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE AND LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_coverage_target(gncmod-ofx)
endif()
install(TARGETS gncmod-ofx
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -36,6 +36,10 @@ if (APPLE)
set_target_properties (gnc-qif-import PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE AND LCOV_VERSION VERSION_GREATER_EQUAL "2.0")
add_coverage_target(gnc-qif-import)
endif()
install(TARGETS gnc-qif-import
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -56,6 +56,10 @@ if (APPLE)
set_target_properties (gnc-ledger-core PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-ledger-core)
endif()
install(TARGETS gnc-ledger-core
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -60,6 +60,10 @@ install(TARGETS gnc-register-core
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if (COVERAGE)
add_coverage_target(gnc-register-core)
endif()
install(FILES ${register_core_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gnucash)
set_local_dist(register_core_DIST_local CMakeLists.txt README ${register_core_SOURCES} ${register_core_HEADERS})

View File

@ -55,6 +55,10 @@ if (APPLE)
set_target_properties (gnc-register-gnome PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-register-gnome)
endif()
install(TARGETS gnc-register-gnome
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -43,6 +43,10 @@ if (APPLE)
set_target_properties (gnc-report PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gnc-report)
endif()
install(TARGETS gnc-report
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -84,7 +84,11 @@ if (APPLE)
set_target_properties (gnc-app-utils PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
install(TARGETS gnc-app-utils
if (COVERAGE)
add_coverage_target(gnc-app-utils)
endif()
install (TARGETS gnc-app-utils
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

View File

@ -43,6 +43,10 @@ if (WITH_SQL)
set_target_properties (gncmod-backend-dbi PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/gnucash")
endif()
if (COVERAGE)
add_coverage_target(gncmod-backend-dbi)
endif()
install(TARGETS gncmod-backend-dbi
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/gnucash

View File

@ -1030,7 +1030,7 @@ template<> bool
QofDbiBackendProvider<DbType::DBI_SQLITE>::type_check(const char *uri)
{
FILE* f;
gchar buf[50];
gchar buf[51]{};
G_GNUC_UNUSED size_t chars_read;
gint status;
gchar* filename;
@ -1050,7 +1050,7 @@ QofDbiBackendProvider<DbType::DBI_SQLITE>::type_check(const char *uri)
}
// OK if file has the correct header
chars_read = fread (buf, sizeof (buf), 1, f);
chars_read = fread (buf, sizeof (buf) - 1, 1, f);
status = fclose (f);
if (status < 0)
{

View File

@ -80,5 +80,9 @@ if(WITH_SQL)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if (COVERAGE)
add_coverage_target(gnc-backend-sql)
endif()
# No headers to install
endif()

View File

@ -96,6 +96,10 @@ install(TARGETS gnc-backend-xml-utils
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# No headers to install
if (COVERAGE)
add_coverage_target(gnc-backend-xml-utils)
endif()
# ----
@ -119,6 +123,10 @@ if (APPLE)
set_target_properties (gncmod-backend-xml PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if (COVERAGE)
add_coverage_target(gncmod-backend-xml)
endif()
install(TARGETS gncmod-backend-xml
LIBRARY DESTINATION ${LIB_DIR}
ARCHIVE DESTINATION ${LIB_DIR}

View File

@ -234,7 +234,9 @@ GncXmlBackend::load(QofBook* book, QofBackendLoadType loadType)
if (loadType != LOAD_TYPE_INITIAL_LOAD) return;
error = ERR_BACKEND_NO_ERR;
m_book = book;
if (m_book)
g_object_unref(m_book);
m_book = QOF_BOOK(g_object_ref(book));
int rc;
switch (determine_file_type (m_fullpath))
@ -306,7 +308,8 @@ GncXmlBackend::sync(QofBook* book)
* for multiple books have been removed in the meantime and there is just one
* book, no more.
*/
if (m_book == nullptr) m_book = book;
if (m_book == nullptr)
m_book = QOF_BOOK(g_object_ref(book));
if (book != m_book) return;
if (qof_book_is_readonly (m_book))

View File

@ -13,7 +13,7 @@ set(XML_TEST_INCLUDE_DIRS
)
set(XML_TEST_LIBS gnc-engine gnc-test-engine test-core ${LIBXML2_LDFLAGS} -lz)
set(XML_TEST_LIBS gnc-backend-xml-utils gnc-engine gnc-test-engine test-core ${LIBXML2_LDFLAGS} -lz)
set(XML_GTEST_LIBS ${XML_TEST_LIBS} gtest)
function(add_xml_test _TARGET _SOURCE_FILES)
@ -26,40 +26,6 @@ function(add_xml_gtest _TARGET _SOURCE_FILES)
target_compile_options(${_TARGET} PRIVATE -DU_SHOW_CPLUSPLUS_API=0 -DG_LOG_DOMAIN=\"gnc.backend.xml\")
endfunction()
################################
set(test_backend_xml_base_SOURCES
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp-dom-parsers.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp-dom-generators.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp-utils.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp-stack.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/sixtp-to-dom-parser.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-xml-helper.cpp
)
## the xml backend is now a GModule - this test does
## not load it as a module and cannot link to it
## and remain portable.
set(test_backend_xml_module_SOURCES
${test_backend_xml_base_SOURCES}
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/io-example-account.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/io-gncxml-gen.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/io-gncxml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/io-utils.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-account-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-budget-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-lot-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-recurrence-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-schedxaction-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-freqspec-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-transaction-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-commodity-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-book-xml-v2.cpp
${CMAKE_SOURCE_DIR}/libgnucash/backend/xml/gnc-pricedb-xml-v2.cpp
)
set_local_dist(test_backend_xml_DIST_local
CMakeLists.txt
grab-types.pl
@ -84,8 +50,8 @@ set_local_dist(test_backend_xml_DIST_local
)
set(test_backend_xml_DIST ${test_backend_xml_DIST_local} ${test_backend_xml_test_files_DIST} PARENT_SCOPE)
add_xml_test(test-dom-converters1 "${test_backend_xml_base_SOURCES};test-dom-converters1.cpp")
add_xml_test(test-kvp-frames "${test_backend_xml_base_SOURCES};test-kvp-frames.cpp")
add_xml_test(test-dom-converters1 "test-dom-converters1.cpp")
add_xml_test(test-kvp-frames "test-kvp-frames.cpp")
add_xml_test(test-load-backend test-load-backend.cpp)
add_xml_test(test-load-xml2 test-load-xml2.cpp
GNC_TEST_FILES=${CMAKE_CURRENT_SOURCE_DIR}/test-files/xml2
@ -96,19 +62,19 @@ add_xml_test(test-load-xml2 test-load-xml2.cpp
#)
add_xml_test(test-load-example-account
"${test_backend_xml_module_SOURCES};test-load-example-account.cpp"
"test-load-example-account.cpp"
GNC_ACCOUNT_PATH=${CMAKE_SOURCE_DIR}/data/accounts/C
)
target_compile_options(test-load-example-account PRIVATE -DU_SHOW_CPLUSPLUS_API=0)
add_xml_gtest(test-load-save-files gtest-load-save-files.cpp
GNC_TEST_FILES=${CMAKE_CURRENT_SOURCE_DIR}/test-files/load-save
)
add_xml_test(test-string-converters "${test_backend_xml_base_SOURCES};test-string-converters.cpp")
add_xml_test(test-xml-account "${test_backend_xml_module_SOURCES};test-xml-account.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-commodity "${test_backend_xml_module_SOURCES};test-xml-commodity.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-pricedb "${test_backend_xml_module_SOURCES};test-xml-pricedb.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-transaction "${test_backend_xml_module_SOURCES};test-xml-transaction.cpp;test-file-stuff.cpp")
add_xml_test(test-xml2-is-file "${test_backend_xml_module_SOURCES};test-xml2-is-file.cpp"
add_xml_test(test-string-converters "test-string-converters.cpp")
add_xml_test(test-xml-account "test-xml-account.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-commodity "test-xml-commodity.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-pricedb "test-xml-pricedb.cpp;test-file-stuff.cpp")
add_xml_test(test-xml-transaction "test-xml-transaction.cpp;test-file-stuff.cpp")
add_xml_test(test-xml2-is-file "test-xml2-is-file.cpp"
GNC_TEST_FILES=${CMAKE_CURRENT_SOURCE_DIR}/test-files/xml2)
set(test-real-data-env

View File

@ -72,6 +72,10 @@ install(TARGETS gnc-core-utils
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if (COVERAGE)
add_coverage_target(gnc-core-utils)
endif()
### gncla-dir.h
set(prefix ${CMAKE_INSTALL_PREFIX})

View File

@ -263,6 +263,10 @@ if (APPLE)
set_target_properties (gnc-engine PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if (COVERAGE)
add_coverage_target(gnc-engine)
endif()
install(TARGETS gnc-engine
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -720,9 +720,15 @@ xaccFreeSplit (Split *split)
split->date_reconciled = 0;
G_OBJECT_CLASS (QOF_INSTANCE_GET_CLASS (&split->inst))->dispose(G_OBJECT (split));
// Is this right?
if (split->gains_split) split->gains_split->gains_split = NULL;
/* qof_instance_release(&split->inst); */
if (split->gains_split)
{
Split *other = xaccSplitGetOtherSplit(split->gains_split);
split->gains_split->gains_split = NULL;
if (other)
other->gains_split = NULL;
}
g_object_unref(split);
}

View File

@ -333,7 +333,8 @@ gnc_date_string_to_dateformat(const char* fmt_str, QofDateFormat *format)
const char*
gnc_date_monthformat_to_string(GNCDateMonthFormat format)
{
switch (format)
//avoid UB if format is out of range
switch (static_cast<uint8_t>(format))
{
case GNCDATE_MONTH_NUMBER:
return "number";
@ -430,7 +431,9 @@ QofDateFormat qof_date_format_get (void)
void qof_date_format_set(QofDateFormat df)
{
if (df >= DATE_FORMAT_FIRST && df <= DATE_FORMAT_LAST)
//avoid UB if df is out of range
auto dfi{static_cast<uint8_t>(df)};
if (dfi >= DATE_FORMAT_FIRST && dfi <= DATE_FORMAT_LAST)
{
prevQofDateFormat = dateFormat;
dateFormat = df;

View File

@ -477,8 +477,8 @@ namespace IANAParser
endian_swap(&info.gmtoff);
tzinfo.push_back(
{info, &fileblock[abbrev + info.abbrind],
fileblock[std_dist + index] != '\0',
fileblock[gmt_dist + index] != '\0'});
(index < isstd_count ? fileblock[std_dist + index] != '\0' : true),
(index < isgmt_count ? fileblock[gmt_dist + index] != '\0' : false)});
}
}

View File

@ -32,6 +32,7 @@
* Copyright (c) 2000 Dave Peticolas
* Copyright (c) 2007 David Hampton <hampton@employees.org>
*/
#include "qof-string-cache.h"
#include <glib.h>
#include <config.h>
@ -53,6 +54,7 @@
#include "qofobject-p.h"
#include "qofbookslots.h"
#include "kvp-frame.hpp"
#include "gnc-lot.h"
// For GNC_ID_ROOT_ACCOUNT:
#include "AccountP.h"
@ -111,7 +113,8 @@ qof_book_init (QofBook *book)
qof_instance_init_data (&book->inst, QOF_ID_BOOK, book);
book->data_tables = g_hash_table_new (g_str_hash, g_str_equal);
book->data_tables = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)qof_string_cache_remove, NULL);
book->data_table_finalizers = g_hash_table_new (g_str_hash, g_str_equal);
book->book_open = 'y';
@ -317,6 +320,13 @@ qof_book_finalize_real (G_GNUC_UNUSED GObject *bookp)
{
}
static void
destroy_lot(QofInstance *inst, [[maybe_unused]]void* data)
{
auto lot{GNC_LOT(inst)};
gnc_lot_destroy(lot);
}
void
qof_book_destroy (QofBook *book)
{
@ -333,6 +343,11 @@ qof_book_destroy (QofBook *book)
*/
g_hash_table_foreach (book->data_table_finalizers, book_final, book);
/* Lots hold a variety of pointers that need to still exist while
* cleaning them up so run its book_end before the rest.
*/
auto lots{qof_book_get_collection(book, GNC_ID_LOT)};
qof_collection_foreach(lots, destroy_lot, nullptr);
qof_object_book_end (book);
g_hash_table_destroy (book->data_table_finalizers);
@ -350,7 +365,6 @@ qof_book_destroy (QofBook *book)
cols = book->hash_of_collections;
g_object_unref (book);
g_hash_table_destroy (cols);
/*book->hash_of_collections = NULL;*/
LEAVE ("book=%p", book);
}
@ -450,13 +464,14 @@ qof_book_set_backend (QofBook *book, QofBackend *be)
/* ====================================================================== */
/* Store arbitrary pointers in the QofBook for data storage extensibility */
/* XXX if data is NULL, we should remove the key from the hash table!
*/
void
qof_book_set_data (QofBook *book, const char *key, gpointer data)
{
if (!book || !key) return;
g_hash_table_insert (book->data_tables, (gpointer)key, data);
if (data)
g_hash_table_insert (book->data_tables, (gpointer)CACHE_INSERT(key), data);
else
g_hash_table_remove(book->data_tables, key);
}
void

View File

@ -38,30 +38,37 @@ protected:
t_asset_account1 = xaccMallocAccount(book);
xaccAccountSetName(t_asset_account1, "Asset");
xaccAccountSetType(t_asset_account1, ACCT_TYPE_ASSET);
gnc_account_append_child(root, t_asset_account1);
t_bank_account = xaccMallocAccount(book);
xaccAccountSetName(t_bank_account, "Bank");
xaccAccountSetType(t_bank_account, ACCT_TYPE_BANK);
gnc_account_append_child(t_asset_account1, t_bank_account);
t_asset_account2 = xaccMallocAccount(book);
xaccAccountSetName(t_asset_account2, "Asset-Bank");
xaccAccountSetType(t_asset_account2, ACCT_TYPE_ASSET);
gnc_account_append_child(root, t_asset_account2);
t_sav_account = xaccMallocAccount(book);
xaccAccountSetName(t_sav_account, "Bank");
xaccAccountSetType(t_sav_account,ACCT_TYPE_BANK);
gnc_account_append_child(t_asset_account2, t_sav_account);
t_expense_account = xaccMallocAccount(book);
xaccAccountSetName(t_expense_account, "Expense");
xaccAccountSetType(t_expense_account, ACCT_TYPE_EXPENSE);
gnc_account_append_child(root, t_expense_account);
t_expense_account1 = xaccMallocAccount(book);
xaccAccountSetName(t_expense_account1, "Food");
xaccAccountSetType(t_expense_account1, ACCT_TYPE_EXPENSE);
gnc_account_append_child(t_expense_account, t_expense_account1);
t_expense_account2 = xaccMallocAccount(book);
xaccAccountSetName(t_expense_account2, "Drink");
xaccAccountSetType(t_expense_account2, ACCT_TYPE_EXPENSE);
gnc_account_append_child(t_expense_account, t_expense_account2);
}
void TearDown() {

View File

@ -82,7 +82,7 @@ run_test (void)
auto ent = QOF_INSTANCE(g_object_new(QOF_TYPE_INSTANCE, "guid", &guid, NULL));
do_test ((NULL == qof_collection_lookup_entity (col, &guid)),
"duplicate guid");
ent->e_type = type;
ent->e_type = CACHE_INSERT(type);
qof_collection_insert_entity (col, ent);
do_test ((NULL != qof_collection_lookup_entity (col, &guid)),
"guid not found");

View File

@ -962,10 +962,7 @@ test_book_new_destroy( void )
qof_book_set_data_fin( book, key, (gpointer) data, mock_final_cb );
test_struct.called = FALSE;
g_test_message( "Testing book destroy" );
qof_book_destroy( book );
g_assert_true( qof_book_shutting_down( book ) );
g_assert_true( test_struct.called );
}
void

View File

@ -303,8 +303,8 @@ test_qof_object_book_begin( Fixture *fixture, gconstpointer pData )
g_assert_cmpint( g_list_index( get_book_list(), (gconstpointer) book2 ), != , -1 );
g_assert_cmpint( object_book_begin_struct.call_count, == , list_length );
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
qof_book_destroy( book2 );
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
}
static void
@ -389,8 +389,8 @@ test_qof_object_is_dirty( Fixture *fixture, gconstpointer pData )
g_assert_true( qof_object_is_dirty( book ) == TRUE );
g_assert_cmpint( object_dirty_struct.call_count, == , 1 ); /* should break on first */
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
qof_book_destroy( book );
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
}
static struct
@ -433,8 +433,8 @@ test_qof_object_mark_clean( Fixture *fixture, gconstpointer pData )
qof_object_mark_clean( book );
g_assert_cmpint( object_mark_clean_struct.call_count, == , list_length );
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
qof_book_destroy( book );
qof_object_foreach_type ((QofForeachTypeCB)g_free, NULL);
}
static struct

View File

@ -27,6 +27,10 @@ target_include_directories (gnc-module
${CMAKE_BINARY_DIR}/common # for config.h
)
if (COVERAGE)
add_coverage_target(gnc-module)
endif()
install(TARGETS gnc-module
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -23,6 +23,10 @@ if (APPLE)
set_target_properties (gnc-locale-tax PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if (COVERAGE)
add_coverage_target(gnc-locale-tax)
endif()
install(TARGETS gnc-locale-tax
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}