Compare commits

...

4 Commits

Author SHA1 Message Date
Elliot Lee
1676e9fe21 Set version to 2.0.1-rc1 2024-01-22 14:48:05 -08:00
Bronek Kozicki
fad9d639bf test: improve code coverage reporting (#4849)
* Speed up the generation of coverage reports by using multiple cores.

* Add codecov step to coverage workflow.
2024-01-22 13:09:18 -08:00
Chenna Keshava B S
efe6722bf8 docs: update help message about unit test-suite pattern matching (#4846)
Update the "rippled --help" message for the "-u" parameter. This
documents the unit test name pattern matching rule implemented by #4634.

Fix #4800
2024-01-19 21:55:57 -08:00
Mark Travis
a41f38547b Revert "Asynchronously write batches to NuDB. (#4503)" (#4882)
This reverts commit 1d9db1bfdd.

This improves the stability of online deletion.
2024-01-19 13:26:26 -08:00
21 changed files with 799 additions and 260 deletions

View File

@@ -1,5 +1,6 @@
coverage:
codecov: status:
ci: project:
- !appveyor default:
- travis target: 60%
threshold: 2%

View File

@@ -6,6 +6,8 @@ inputs:
required: true required: true
cmake-args: cmake-args:
default: null default: null
cmake-target:
default: all
# An implicit input is the environment variable `build_dir`. # An implicit input is the environment variable `build_dir`.
runs: runs:
using: composite using: composite
@@ -26,4 +28,5 @@ runs:
cmake \ cmake \
--build ${build_dir} \ --build ${build_dir} \
--config ${{ inputs.configuration }} \ --config ${{ inputs.configuration }} \
--parallel ${NUM_PROCESSORS:-$(nproc)} --parallel ${NUM_PROCESSORS:-$(nproc)} \
--target ${{ inputs.cmake-target }}

View File

@@ -49,7 +49,7 @@ jobs:
cc: /usr/bin/clang-14 cc: /usr/bin/clang-14
cxx: /usr/bin/clang++-14 cxx: /usr/bin/clang++-14
runs-on: [self-hosted, heavy] runs-on: [self-hosted, heavy]
container: thejohnfreeman/rippled-build-ubuntu:12e19cd9034b container: rippleci/rippled-build-ubuntu:aaf5e3e
env: env:
build_dir: .build build_dir: .build
steps: steps:
@@ -125,7 +125,7 @@ jobs:
- "-Dunity=ON" - "-Dunity=ON"
needs: dependencies needs: dependencies
runs-on: [self-hosted, heavy] runs-on: [self-hosted, heavy]
container: thejohnfreeman/rippled-build-ubuntu:12e19cd9034b container: rippleci/rippled-build-ubuntu:aaf5e3e
env: env:
build_dir: .build build_dir: .build
steps: steps:
@@ -159,3 +159,72 @@ jobs:
- name: test - name: test
run: | run: |
${build_dir}/rippled --unittest --unittest-jobs $(nproc) ${build_dir}/rippled --unittest --unittest-jobs $(nproc)
coverage:
strategy:
fail-fast: false
matrix:
platform:
- linux
compiler:
- gcc
configuration:
- Debug
needs: dependencies
runs-on: [self-hosted, heavy]
container: rippleci/rippled-build-ubuntu:aaf5e3e
env:
build_dir: .build
steps:
- name: download cache
uses: actions/download-artifact@v3
with:
name: ${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.configuration }}
- name: extract cache
run: |
mkdir -p ~/.conan
tar -xzf conan.tar -C ~/.conan
- name: check environment
run: |
echo ${PATH} | tr ':' '\n'
conan --version
cmake --version
gcovr --version
env | sort
ls ~/.conan
- name: checkout
uses: actions/checkout@v3
- name: dependencies
uses: ./.github/actions/dependencies
with:
configuration: ${{ matrix.configuration }}
- name: build
uses: ./.github/actions/build
with:
generator: Ninja
configuration: ${{ matrix.configuration }}
cmake-args: >-
-Dcoverage=ON
-Dcoverage_format=xml
-DCODE_COVERAGE_VERBOSE=ON
-DCMAKE_CXX_FLAGS="-O0"
-DCMAKE_C_FLAGS="-O0"
cmake-target: coverage
- name: build
shell: bash
run: |
mv "${build_dir}/coverage.xml" ./
- name: archive coverage report
uses: actions/upload-artifact@v3
with:
name: coverage.xml
path: coverage.xml
retention-days: 30
- name: upload coverage report
uses: codecov/codecov-action@v3
with:
files: coverage.xml
fail_ci_if_error: true
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -90,6 +90,7 @@ jobs:
configuration: ${{ matrix.configuration }} configuration: ${{ matrix.configuration }}
# Hard code for now. Move to the matrix if varied options are needed # Hard code for now. Move to the matrix if varied options are needed
cmake-args: '-Dassert=ON -Dreporting=OFF -Dunity=ON' cmake-args: '-Dassert=ON -Dreporting=OFF -Dunity=ON'
cmake-target: install
- name: test (permitted to silently fail) - name: test (permitted to silently fail)
shell: bash shell: bash
# Github runners are resource limited, which causes unit tests to fail # Github runners are resource limited, which causes unit tests to fail

View File

@@ -262,12 +262,72 @@ It patches their CMake to correctly import its dependencies.
generator. Pass `--help` to see the rest of the command line options. generator. Pass `--help` to see the rest of the command line options.
## Coverage report
The coverage report is intended for developers using compilers GCC
or Clang (including Apple Clang). It is generated by the build target `coverage`,
which is only enabled when the `coverage` option is set, e.g. with
`--options coverage=True` in `conan` or `-Dcoverage=ON` variable in `cmake`
Prerequisites for the coverage report:
- [gcovr tool][gcovr] (can be installed e.g. with [pip][python-pip])
- `gcov` for GCC (installed with the compiler by default) or
- `llvm-cov` for Clang (installed with the compiler by default)
- `Debug` build type
A coverage report is created when the following steps are completed, in order:
1. `rippled` binary built with instrumentation data, enabled by the `coverage`
option mentioned above
2. completed run of unit tests, which populates coverage capture data
3. completed run of the `gcovr` tool (which internally invokes either `gcov` or `llvm-cov`)
to assemble both instrumentation data and the coverage capture data into a coverage report
The above steps are automated into a single target `coverage`. The instrumented
`rippled` binary can also be used for regular development or testing work, at
the cost of extra disk space utilization and a small performance hit
(to store coverage capture). In case of a spurious failure of unit tests, it is
possible to re-run the `coverage` target without rebuilding the `rippled` binary
(since it is simply a dependency of the coverage report target). It is also possible
to select only specific tests for the purpose of the coverage report, by setting
the `coverage_test` variable in `cmake`
The default coverage report format is `html-details`, but the user
can override it to any of the formats listed in `Builds/CMake/CodeCoverage.cmake`
by setting the `coverage_format` variable in `cmake`. It is also possible
to generate more than one format at a time by setting the `coverage_extra_args`
variable in `cmake`. The specific command line used to run the `gcovr` tool will be
displayed if the `CODE_COVERAGE_VERBOSE` variable is set.
By default, the code coverage tool runs parallel unit tests with `--unittest-jobs`
set to the number of available CPU cores. This may cause spurious test
errors on Apple. Developers can override the number of unit test jobs with
the `coverage_test_parallelism` variable in `cmake`.
Example use with some cmake variables set:
```
cd .build
conan install .. --output-folder . --build missing --settings build_type=Debug
cmake -DCMAKE_BUILD_TYPE=Debug -Dcoverage=ON -Dcoverage_test_parallelism=2 -Dcoverage_format=html-details -Dcoverage_extra_args="--json coverage.json" -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake ..
cmake --build . --target coverage
```
After the `coverage` target is completed, the generated coverage report will be
stored inside the build directory, as either of:
- file named `coverage.`_extension_ , with a suitable extension for the report format, or
- directory named `coverage`, with the `index.html` and other files inside, for the `html-details` or `html-nested` report formats.
## Options ## Options
| Option | Default Value | Description | | Option | Default Value | Description |
| --- | ---| ---| | --- | ---| ---|
| `assert` | OFF | Enable assertions. | `assert` | OFF | Enable assertions.
| `reporting` | OFF | Build the reporting mode feature. | | `reporting` | OFF | Build the reporting mode feature. |
| `coverage` | OFF | Prepare the coverage report. |
| `tests` | ON | Build tests. | | `tests` | ON | Build tests. |
| `unity` | ON | Configure a unity build. | | `unity` | ON | Configure a unity build. |
| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. | | `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. |
@@ -362,6 +422,8 @@ If you want to experiment with a new package, follow these steps:
[5]: https://en.wikipedia.org/wiki/Unity_build [5]: https://en.wikipedia.org/wiki/Unity_build
[6]: https://github.com/boostorg/beast/issues/2648 [6]: https://github.com/boostorg/beast/issues/2648
[7]: https://github.com/boostorg/beast/issues/2661 [7]: https://github.com/boostorg/beast/issues/2661
[gcovr]: https://gcovr.com/en/stable/getting-started.html
[python-pip]: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/
[build_type]: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html [build_type]: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
[runtime]: https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html [runtime]: https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
[toolchain]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html [toolchain]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html

View File

@@ -0,0 +1,440 @@
# Copyright (c) 2012 - 2017, Lars Bilke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# CHANGES:
#
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
#
# 2013-09-17, Joakim Söderberg
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2016-02-03, Lars Bilke
# - Refactored functions to use named parameters
#
# 2017-06-02, Lars Bilke
# - Merged with modified version from github.com/ufz/ogs
#
# 2019-05-06, Anatolii Kurotych
# - Remove unnecessary --coverage flag
#
# 2019-12-13, FeRD (Frank Dana)
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
# - Set lcov basedir with -b argument
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
# - Delete output dir, .info file on 'make clean'
# - Remove Python detection, since version mismatches will break gcovr
# - Minor cleanup (lowercase function names, update examples...)
#
# 2019-12-19, FeRD (Frank Dana)
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
#
# 2020-01-19, Bob Apthorpe
# - Added gfortran support
#
# 2020-02-17, FeRD (Frank Dana)
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
# in EXCLUDEs, and remove manual escaping from gcovr targets
#
# 2021-01-19, Robin Mueller
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
# flags to the gcovr command
#
# 2020-05-04, Mihchael Davis
# - Add -fprofile-abs-path to make gcno files contain absolute paths
# - Fix BASE_DIRECTORY not working when defined
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
#
# 2021-05-10, Martin Stump
# - Check if the generator is multi-config before warning about non-Debug builds
#
# 2022-02-22, Marko Wehle
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
#
# 2022-09-28, Sebastian Mueller
# - fix append_coverage_compiler_flags_to_target to correctly add flags
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
#
# 2024-01-04, Bronek Kozicki
# - remove setup_target_for_coverage_lcov (slow) and setup_target_for_coverage_fastcov (no support for Clang)
# - fix Clang support by adding find_program( ... llvm-cov )
# - add Apple Clang support by adding execute_process( COMMAND xcrun -f llvm-cov ... )
# - add CODE_COVERAGE_GCOV_TOOL to explicitly select gcov tool and disable find_program
# - replace both functions setup_target_for_coverage_gcovr_* with a single setup_target_for_coverage_gcovr
# - add support for all gcovr output formats
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
#
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Append necessary compiler flags for all supported source files:
# append_coverage_compiler_flags()
# Or for specific target:
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
#
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
#
# 4. If you need to exclude additional directories from the report, specify them
# using full paths in the COVERAGE_EXCLUDES variable before calling
# setup_target_for_coverage_*().
# Example:
# set(COVERAGE_EXCLUDES
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
# '/path/to/my/src/dir2/*')
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
# Example:
# setup_target_for_coverage_gcovr(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
#
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
# Example:
# set(COVERAGE_EXCLUDES "dir1/*")
# setup_target_for_coverage_gcovr(
# NAME coverage
# EXECUTABLE testrunner
# FORMAT html-details
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
# EXCLUDE "dir2/*")
#
# 4.b If you need to pass specific options to gcovr, specify them in
# GCOVR_ADDITIONAL_ARGS variable.
# Example:
# set (GCOVR_ADDITIONAL_ARGS --exclude-throw-branches --exclude-noncode-lines -s)
# setup_target_for_coverage_gcovr(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "src/dir1" "src/dir2")
#
# 5. Use the functions described below to create a custom make target which
# runs your test executable and produces a code coverage report.
#
# 6. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
if(DEFINED CODE_COVERAGE_GCOV_TOOL)
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
elseif(DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if(APPLE)
execute_process( COMMAND xcrun -f llvm-cov
OUTPUT_VARIABLE LLVMCOV_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else()
find_program( LLVMCOV_PATH llvm-cov )
endif()
if(LLVMCOV_PATH)
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
find_program( GCOV_PATH gcov )
set(GCOV_TOOL "${GCOV_PATH}")
endif()
# Check supported compiler (Clang, GNU and Flang)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(LANG ${LANGUAGES})
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endforeach()
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
if(HAVE_cxx_fprofile_abs_path)
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
include(CheckCCompilerFlag)
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if(HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif()
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
FORCE )
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds."
FORCE )
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used for linking binaries during coverage builds."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
FORCE )
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif()
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# FORMAT "cobertura" # Output format, one of:
# # xml cobertura sonarqube json-summary
# # json-details coveralls csv txt
# # html-single html-nested html-details
# # (xml is an alias to cobertura;
# # if no format is set, defaults to xml)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOV_TOOL)
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
endif()
if(NOT GCOVR_PATH)
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
endif()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
if(NOT DEFINED Coverage_FORMAT)
set(Coverage_FORMAT xml)
endif()
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
else()
if((Coverage_FORMAT STREQUAL "html-details")
OR (Coverage_FORMAT STREQUAL "html-nested"))
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
elseif(Coverage_FORMAT STREQUAL "html-single")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
elseif((Coverage_FORMAT STREQUAL "json-summary")
OR (Coverage_FORMAT STREQUAL "json-details")
OR (Coverage_FORMAT STREQUAL "coveralls"))
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
elseif(Coverage_FORMAT STREQUAL "txt")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif(Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
else()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif()
endif()
if((Coverage_FORMAT STREQUAL "cobertura")
OR (Coverage_FORMAT STREQUAL "xml"))
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty )
set(Coverage_FORMAT cobertura) # overwrite xml
elseif(Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
elseif(Coverage_FORMAT STREQUAL "json-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
elseif(Coverage_FORMAT STREQUAL "coveralls")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
elseif(Coverage_FORMAT STREQUAL "csv")
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "txt")
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "html-single")
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
elseif(Coverage_FORMAT STREQUAL "html-nested")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "html-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}" )
else()
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Create folder
if(DEFINED GCOVR_CREATE_FOLDER)
set(GCOVR_FOLDER_CMD
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
else()
set(GCOVR_FOLDER_CMD echo) # dummy
endif()
# Running gcovr
set(GCOVR_CMD
${GCOVR_PATH}
--gcov-executable ${GCOV_TOOL}
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
-r ${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
endif()
message(STATUS "Command to generate gcovr coverage data: ")
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
message(STATUS "${GCOVR_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_EXEC_TESTS_CMD}
COMMAND ${GCOVR_FOLDER_CMD}
COMMAND ${GCOVR_CMD}
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
)
endfunction() # setup_target_for_coverage_gcovr
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags
# Setup coverage for specific library
function(append_coverage_compiler_flags_to_target name)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
target_compile_options(${name} PRIVATE ${_flag_list})
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
target_link_libraries(${name} PRIVATE gcov)
endif()
endfunction()

View File

@@ -2,97 +2,37 @@
coverage report target coverage report target
#]===================================================================] #]===================================================================]
if (coverage) if(NOT coverage)
if (is_clang) message(FATAL_ERROR "Code coverage not enabled! Aborting ...")
if (APPLE) endif()
execute_process (COMMAND xcrun -f llvm-profdata
OUTPUT_VARIABLE LLVM_PROFDATA
OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
find_program (LLVM_PROFDATA llvm-profdata)
endif ()
if (NOT LLVM_PROFDATA)
message (WARNING "unable to find llvm-profdata - skipping coverage_report target")
endif ()
if (APPLE) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
execute_process (COMMAND xcrun -f llvm-cov message(WARNING "Code coverage on Windows is not supported, ignoring 'coverage' flag")
OUTPUT_VARIABLE LLVM_COV return()
OUTPUT_STRIP_TRAILING_WHITESPACE) endif()
else ()
find_program (LLVM_COV llvm-cov)
endif ()
if (NOT LLVM_COV)
message (WARNING "unable to find llvm-cov - skipping coverage_report target")
endif ()
set (extract_pattern "") include(CodeCoverage)
if (coverage_core_only)
set (extract_pattern "${CMAKE_CURRENT_SOURCE_DIR}/src/ripple/")
endif ()
if (LLVM_COV AND LLVM_PROFDATA) # The instructions for these commands come from the `CodeCoverage` module,
add_custom_target (coverage_report # which was copied from https://github.com/bilke/cmake-modules, commit fb7d2a3,
USES_TERMINAL # then locally changed (see CHANGES: section in `CodeCoverage.cmake`)
COMMAND ${CMAKE_COMMAND} -E echo "Generating coverage - results will be in ${CMAKE_BINARY_DIR}/coverage/index.html."
COMMAND ${CMAKE_COMMAND} -E echo "Running rippled tests."
COMMAND rippled --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --quiet --unittest-log
COMMAND ${LLVM_PROFDATA}
merge -sparse default.profraw -o rip.profdata
COMMAND ${CMAKE_COMMAND} -E echo "Summary of coverage:"
COMMAND ${LLVM_COV}
report -instr-profile=rip.profdata
$<TARGET_FILE:rippled> ${extract_pattern}
# generate html report
COMMAND ${LLVM_COV}
show -format=html -output-dir=${CMAKE_BINARY_DIR}/coverage
-instr-profile=rip.profdata
$<TARGET_FILE:rippled> ${extract_pattern}
BYPRODUCTS coverage/index.html)
endif ()
elseif (is_gcc)
find_program (LCOV lcov)
if (NOT LCOV)
message (WARNING "unable to find lcov - skipping coverage_report target")
endif ()
find_program (GENHTML genhtml) set(GCOVR_ADDITIONAL_ARGS ${coverage_extra_args})
if (NOT GENHTML) if(NOT GCOVR_ADDITIONAL_ARGS STREQUAL "")
message (WARNING "unable to find genhtml - skipping coverage_report target") separate_arguments(GCOVR_ADDITIONAL_ARGS)
endif () endif()
set (extract_pattern "*") list(APPEND GCOVR_ADDITIONAL_ARGS
if (coverage_core_only) --exclude-throw-branches
set (extract_pattern "*/src/ripple/*") --exclude-noncode-lines
endif () --exclude-unreachable-branches -s
-j ${coverage_test_parallelism})
if (LCOV AND GENHTML) setup_target_for_coverage_gcovr(
add_custom_target (coverage_report NAME coverage
USES_TERMINAL FORMAT ${coverage_format}
COMMAND ${CMAKE_COMMAND} -E echo "Generating coverage- results will be in ${CMAKE_BINARY_DIR}/coverage/index.html." EXECUTABLE rippled
# create baseline info file EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
COMMAND ${LCOV} EXCLUDE "src/test" "${CMAKE_BINARY_DIR}/proto_gen" "${CMAKE_BINARY_DIR}/proto_gen_grpc"
--no-external -d "${CMAKE_CURRENT_SOURCE_DIR}" -c -d . -i -o baseline.info DEPENDENCIES rippled
| grep -v "ignoring data for external file" )
# run tests
COMMAND ${CMAKE_COMMAND} -E echo "Running rippled tests for coverage report."
COMMAND rippled --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --quiet --unittest-log
# Create test coverage data file
COMMAND ${LCOV}
--no-external -d "${CMAKE_CURRENT_SOURCE_DIR}" -c -d . -o tests.info
| grep -v "ignoring data for external file"
# Combine baseline and test coverage data
COMMAND ${LCOV}
-a baseline.info -a tests.info -o lcov-all.info
# extract our files
COMMAND ${LCOV}
-e lcov-all.info "${extract_pattern}" -o lcov.info
COMMAND ${CMAKE_COMMAND} -E echo "Summary of coverage:"
COMMAND ${LCOV} --summary lcov.info
# generate HTML report
COMMAND ${GENHTML}
-o ${CMAKE_BINARY_DIR}/coverage lcov.info
BYPRODUCTS coverage/index.html)
endif ()
endif ()
endif ()

View File

@@ -23,15 +23,15 @@ target_compile_options (opts
INTERFACE INTERFACE
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override> $<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
$<$<BOOL:${perf}>:-fno-omit-frame-pointer> $<$<BOOL:${perf}>:-fno-omit-frame-pointer>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-fprofile-arcs -ftest-coverage> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-fprofile-instr-generate -fcoverage-mapping> $<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
$<$<BOOL:${profile}>:-pg> $<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>) $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
target_link_libraries (opts target_link_libraries (opts
INTERFACE INTERFACE
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-fprofile-arcs -ftest-coverage> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-fprofile-instr-generate -fcoverage-mapping> $<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
$<$<BOOL:${profile}>:-pg> $<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>) $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)

View File

@@ -2,6 +2,8 @@
convenience variables and sanity checks convenience variables and sanity checks
#]===================================================================] #]===================================================================]
include(ProcessorCount)
if (NOT ep_procs) if (NOT ep_procs)
ProcessorCount(ep_procs) ProcessorCount(ep_procs)
if (ep_procs GREATER 1) if (ep_procs GREATER 1)

View File

@@ -2,123 +2,129 @@
declare user options/settings declare user options/settings
#]===================================================================] #]===================================================================]
option (assert "Enables asserts, even in release builds" OFF) include(ProcessorCount)
option (reporting "Build rippled with reporting mode enabled" OFF) ProcessorCount(PROCESSOR_COUNT)
option (tests "Build tests" ON) option(assert "Enables asserts, even in release builds" OFF)
option (unity "Creates a build using UNITY support in cmake. This is the default" ON) option(reporting "Build rippled with reporting mode enabled" OFF)
if (unity)
if (NOT is_ci) option(tests "Build tests" ON)
set (CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
endif () option(unity "Creates a build using UNITY support in cmake. This is the default" ON)
endif () if(unity)
if (is_gcc OR is_clang) if(NOT is_ci)
option (coverage "Generates coverage info." OFF) set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
option (profile "Add profiling flags" OFF) endif()
set (coverage_test "" CACHE STRING endif()
if(is_gcc OR is_clang)
option(coverage "Generates coverage info." OFF)
option(profile "Add profiling flags" OFF)
set(coverage_test_parallelism "${PROCESSOR_COUNT}" CACHE STRING
"Unit tests parallelism for the purpose of coverage report.")
set(coverage_format "html-details" CACHE STRING
"Output format of the coverage report.")
set(coverage_extra_args "" CACHE STRING
"Additional arguments to pass to gcovr.")
set(coverage_test "" CACHE STRING
"On gcc & clang, the specific unit test(s) to run for coverage. Default is all tests.") "On gcc & clang, the specific unit test(s) to run for coverage. Default is all tests.")
if (coverage_test AND NOT coverage) if(coverage_test AND NOT coverage)
set (coverage ON CACHE BOOL "gcc/clang only" FORCE) set(coverage ON CACHE BOOL "gcc/clang only" FORCE)
endif () endif()
option (coverage_core_only option(wextra "compile with extra gcc/clang warnings enabled" ON)
"Include only src/ripple files when generating coverage report. \ else()
Set to OFF to include all sources in coverage report." set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
ON) set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
option (wextra "compile with extra gcc/clang warnings enabled" ON) set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
else () endif()
set (profile OFF CACHE BOOL "gcc/clang only" FORCE) if(is_linux)
set (coverage OFF CACHE BOOL "gcc/clang only" FORCE) option(BUILD_SHARED_LIBS "build shared ripple libraries" OFF)
set (wextra OFF CACHE BOOL "gcc/clang only" FORCE) option(static "link protobuf, openssl, libc++, and boost statically" ON)
endif () option(perf "Enables flags that assist with perf recording" OFF)
if (is_linux) option(use_gold "enables detection of gold (binutils) linker" ON)
option (BUILD_SHARED_LIBS "build shared ripple libraries" OFF) option(use_mold "enables detection of mold (binutils) linker" ON)
option (static "link protobuf, openssl, libc++, and boost statically" ON) else()
option (perf "Enables flags that assist with perf recording" OFF)
option (use_gold "enables detection of gold (binutils) linker" ON)
option (use_mold "enables detection of mold (binutils) linker" ON)
else ()
# we are not ready to allow shared-libs on windows because it would require # we are not ready to allow shared-libs on windows because it would require
# export declarations. On macos it's more feasible, but static openssl # export declarations. On macos it's more feasible, but static openssl
# produces odd linker errors, thus we disable shared lib builds for now. # produces odd linker errors, thus we disable shared lib builds for now.
set (BUILD_SHARED_LIBS OFF CACHE BOOL "build shared ripple libraries - OFF for win/macos" FORCE) set(BUILD_SHARED_LIBS OFF CACHE BOOL "build shared ripple libraries - OFF for win/macos" FORCE)
set (static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE) set(static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE)
set (perf OFF CACHE BOOL "perf flags, linux only" FORCE) set(perf OFF CACHE BOOL "perf flags, linux only" FORCE)
set (use_gold OFF CACHE BOOL "gold linker, linux only" FORCE) set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
set (use_mold OFF CACHE BOOL "mold linker, linux only" FORCE) set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
endif () endif()
if (is_clang) if(is_clang)
option (use_lld "enables detection of lld linker" ON) option(use_lld "enables detection of lld linker" ON)
else () else()
set (use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE) set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
endif () endif()
option (jemalloc "Enables jemalloc for heap profiling" OFF) option(jemalloc "Enables jemalloc for heap profiling" OFF)
option (werr "treat warnings as errors" OFF) option(werr "treat warnings as errors" OFF)
option (local_protobuf option(local_protobuf
"Force a local build of protobuf instead of looking for an installed version." OFF) "Force a local build of protobuf instead of looking for an installed version." OFF)
option (local_grpc option(local_grpc
"Force a local build of gRPC instead of looking for an installed version." OFF) "Force a local build of gRPC instead of looking for an installed version." OFF)
# this one is a string and therefore can't be an option # this one is a string and therefore can't be an option
set (san "" CACHE STRING "On gcc & clang, add sanitizer instrumentation") set(san "" CACHE STRING "On gcc & clang, add sanitizer instrumentation")
set_property (CACHE san PROPERTY STRINGS ";undefined;memory;address;thread") set_property(CACHE san PROPERTY STRINGS ";undefined;memory;address;thread")
if (san) if(san)
string (TOLOWER ${san} san) string(TOLOWER ${san} san)
set (SAN_FLAG "-fsanitize=${san}") set(SAN_FLAG "-fsanitize=${san}")
set (SAN_LIB "") set(SAN_LIB "")
if (is_gcc) if(is_gcc)
if (san STREQUAL "address") if(san STREQUAL "address")
set (SAN_LIB "asan") set(SAN_LIB "asan")
elseif (san STREQUAL "thread") elseif(san STREQUAL "thread")
set (SAN_LIB "tsan") set(SAN_LIB "tsan")
elseif (san STREQUAL "memory") elseif(san STREQUAL "memory")
set (SAN_LIB "msan") set(SAN_LIB "msan")
elseif (san STREQUAL "undefined") elseif(san STREQUAL "undefined")
set (SAN_LIB "ubsan") set(SAN_LIB "ubsan")
endif () endif()
endif () endif()
set (_saved_CRL ${CMAKE_REQUIRED_LIBRARIES}) set(_saved_CRL ${CMAKE_REQUIRED_LIBRARIES})
set (CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}") set(CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}")
check_cxx_compiler_flag (${SAN_FLAG} COMPILER_SUPPORTS_SAN) check_cxx_compiler_flag(${SAN_FLAG} COMPILER_SUPPORTS_SAN)
set (CMAKE_REQUIRED_LIBRARIES ${_saved_CRL}) set(CMAKE_REQUIRED_LIBRARIES ${_saved_CRL})
if (NOT COMPILER_SUPPORTS_SAN) if(NOT COMPILER_SUPPORTS_SAN)
message (FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler") message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
endif () endif()
endif () endif()
set (container_label "" CACHE STRING "tag to use for package building containers") set(container_label "" CACHE STRING "tag to use for package building containers")
option (packages_only option(packages_only
"ONLY generate package building targets. This is special use-case and almost \ "ONLY generate package building targets. This is special use-case and almost \
certainly not what you want. Use with caution as you won't be able to build \ certainly not what you want. Use with caution as you won't be able to build \
any compiled targets locally." OFF) any compiled targets locally." OFF)
option (have_package_container option(have_package_container
"Sometimes you already have the tagged container you want to use for package \ "Sometimes you already have the tagged container you want to use for package \
building and you don't want docker to rebuild it. This flag will detach the \ building and you don't want docker to rebuild it. This flag will detach the \
dependency of the package build from the container build. It's an advanced \ dependency of the package build from the container build. It's an advanced \
use case and most likely you should not be touching this flag." OFF) use case and most likely you should not be touching this flag." OFF)
# the remaining options are obscure and rarely used # the remaining options are obscure and rarely used
option (beast_no_unit_test_inline option(beast_no_unit_test_inline
"Prevents unit test definitions from being inserted into global table" "Prevents unit test definitions from being inserted into global table"
OFF) OFF)
option (single_io_service_thread option(single_io_service_thread
"Restricts the number of threads calling io_service::run to one. \ "Restricts the number of threads calling io_service::run to one. \
This can be useful when debugging." This can be useful when debugging."
OFF) OFF)
option (boost_show_deprecated option(boost_show_deprecated
"Allow boost to fail on deprecated usage. Only useful if you're trying\ "Allow boost to fail on deprecated usage. Only useful if you're trying\
to find deprecated calls." to find deprecated calls."
OFF) OFF)
option (beast_hashers option(beast_hashers
"Use local implementations for sha/ripemd hashes (experimental, not recommended)" "Use local implementations for sha/ripemd hashes (experimental, not recommended)"
OFF) OFF)
if (WIN32) if(WIN32)
option (beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF) option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
else () else()
set (beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE) set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
endif () endif()
if (coverage) if(coverage)
message (STATUS "coverage build requested - forcing Debug build") message(STATUS "coverage build requested - forcing Debug build")
set (CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
endif () endif()

View File

@@ -38,7 +38,6 @@ include (CheckCXXCompilerFlag)
include (FetchContent) include (FetchContent)
include (ExternalProject) include (ExternalProject)
include (CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP include (CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
include (ProcessorCount)
if (target) if (target)
message (FATAL_ERROR "The target option has been removed - use native cmake options to control build") message (FATAL_ERROR "The target option has been removed - use native cmake options to control build")
endif () endif ()
@@ -126,12 +125,15 @@ if(reporting)
) )
endif() endif()
if(coverage)
include(RippledCov)
endif()
### ###
include(RippledCore) include(RippledCore)
include(deps/Protobuf) include(deps/Protobuf)
include(deps/gRPC) include(deps/gRPC)
include(RippledInstall) include(RippledInstall)
include(RippledCov)
include(RippledMultiConfig) include(RippledMultiConfig)
include(RippledValidatorKeys) include(RippledValidatorKeys)

View File

@@ -125,6 +125,25 @@ pip3 install pre-commit
pre-commit install pre-commit install
``` ```
## Unit Tests
To execute all unit tests:
```rippled --unittest --unittest-jobs=<number of cores>```
(Note: Using multiple cores on a Mac M1 can cause spurious test failures. The
cause is still under investigation. If you observe this problem, try specifying fewer jobs.)
To run a specific set of test suites:
```
rippled --unittest TestSuiteName
```
Note: In this example, all tests with prefix `TestSuiteName` will be run, so if
`TestSuiteName1` and `TestSuiteName2` both exist, then both tests will run.
Alternatively, if the unit test name finds an exact match, it will stop
doing partial matches, i.e. if a unit test with a title of `TestSuiteName`
exists, then no other unit test will be executed, apart from `TestSuiteName`.
## Avoid ## Avoid
1. Proliferation of nearly identical code. 1. Proliferation of nearly identical code.

View File

@@ -44,7 +44,7 @@ if [[ ${NINJA_BUILD:-} == true ]]; then
fi fi
coverage=false coverage=false
if [[ "${TARGET}" == "coverage_report" ]] ; then if [[ "${TARGET}" == "coverage" ]] ; then
echo "coverage option detected." echo "coverage option detected."
coverage=true coverage=true
fi fi

View File

@@ -431,9 +431,8 @@ run(int argc, char** argv)
po::value<std::string>()->implicit_value(""), po::value<std::string>()->implicit_value(""),
"Perform unit tests. The optional argument specifies one or " "Perform unit tests. The optional argument specifies one or "
"more comma-separated selectors. Each selector specifies a suite name, " "more comma-separated selectors. Each selector specifies a suite name, "
"full-name (lib.module.suite), module, or library " "suite name prefix, full-name (lib.module.suite), module, or library "
"(checked in that " "(checked in that order).")(
"order).")(
"unittest-arg", "unittest-arg",
po::value<std::string>()->implicit_value(""), po::value<std::string>()->implicit_value(""),
"Supplies an argument string to unit tests. If provided, this argument " "Supplies an argument string to unit tests. If provided, this argument "

View File

@@ -36,9 +36,8 @@ enum {
// This sets a limit on the maximum number of writes // This sets a limit on the maximum number of writes
// in a batch. Actual usage can be twice this since // in a batch. Actual usage can be twice this since
// we have a new batch growing as we write the old. // we have a new batch growing as we write the old.
// The main goal is to avoid delays while persisting the ledger.
// //
batchWriteLimitSize = 262144 batchWriteLimitSize = 65536
}; };
/** Return codes from Backend operations. */ /** Return codes from Backend operations. */

View File

@@ -20,7 +20,6 @@
#include <ripple/basics/contract.h> #include <ripple/basics/contract.h>
#include <ripple/nodestore/Factory.h> #include <ripple/nodestore/Factory.h>
#include <ripple/nodestore/Manager.h> #include <ripple/nodestore/Manager.h>
#include <ripple/nodestore/impl/BatchWriter.h>
#include <ripple/nodestore/impl/DecodedBlob.h> #include <ripple/nodestore/impl/DecodedBlob.h>
#include <ripple/nodestore/impl/EncodedBlob.h> #include <ripple/nodestore/impl/EncodedBlob.h>
#include <ripple/nodestore/impl/codec.h> #include <ripple/nodestore/impl/codec.h>
@@ -36,7 +35,7 @@
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {
class NuDBBackend : public Backend, public BatchWriter::Callback class NuDBBackend : public Backend
{ {
public: public:
static constexpr std::uint64_t currentType = 1; static constexpr std::uint64_t currentType = 1;
@@ -47,7 +46,6 @@ public:
beast::Journal const j_; beast::Journal const j_;
size_t const keyBytes_; size_t const keyBytes_;
BatchWriter batch_;
std::size_t const burstSize_; std::size_t const burstSize_;
std::string const name_; std::string const name_;
nudb::store db_; nudb::store db_;
@@ -62,7 +60,6 @@ public:
beast::Journal journal) beast::Journal journal)
: j_(journal) : j_(journal)
, keyBytes_(keyBytes) , keyBytes_(keyBytes)
, batch_(*this, scheduler)
, burstSize_(burstSize) , burstSize_(burstSize)
, name_(get(keyValues, "path")) , name_(get(keyValues, "path"))
, deletePath_(false) , deletePath_(false)
@@ -82,7 +79,6 @@ public:
beast::Journal journal) beast::Journal journal)
: j_(journal) : j_(journal)
, keyBytes_(keyBytes) , keyBytes_(keyBytes)
, batch_(*this, scheduler)
, burstSize_(burstSize) , burstSize_(burstSize)
, name_(get(keyValues, "path")) , name_(get(keyValues, "path"))
, db_(context) , db_(context)
@@ -266,7 +262,13 @@ public:
void void
store(std::shared_ptr<NodeObject> const& no) override store(std::shared_ptr<NodeObject> const& no) override
{ {
batch_.store(no); BatchWriteReport report;
report.writeCount = 1;
auto const start = std::chrono::steady_clock::now();
do_insert(no);
report.elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - start);
scheduler_.onBatchWrite(report);
} }
void void
@@ -327,7 +329,7 @@ public:
int int
getWriteLoad() override getWriteLoad() override
{ {
return batch_.getWriteLoad(); return 0;
} }
void void
@@ -355,12 +357,6 @@ public:
Throw<nudb::system_error>(ec); Throw<nudb::system_error>(ec);
} }
void
writeBatch(Batch const& batch) override
{
storeBatch(batch);
}
int int
fdRequired() const override fdRequired() const override
{ {

View File

@@ -33,7 +33,7 @@ namespace BuildInfo {
// and follow the format described at http://semver.org/ // and follow the format described at http://semver.org/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// clang-format off // clang-format off
char const* const versionString = "2.0.1-b1" char const* const versionString = "2.0.1-rc1"
// clang-format on // clang-format on
#if defined(DEBUG) || defined(SANITIZER) #if defined(DEBUG) || defined(SANITIZER)

View File

@@ -26,7 +26,7 @@
namespace ripple { namespace ripple {
class NFTokenBurn0_test : public beast::unit_test::suite class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
{ {
// Helper function that returns the owner count of an account root. // Helper function that returns the owner count of an account root.
static std::uint32_t static std::uint32_t
@@ -815,39 +815,39 @@ public:
} }
}; };
class NFTokenBurn1_test : public NFTokenBurn0_test class NFTokenBurnWOfixFungTokens_test : public NFTokenBurnBaseUtil_test
{ {
public: public:
void void
run() override run() override
{ {
NFTokenBurn0_test::run(1); NFTokenBurnBaseUtil_test::run(1);
} }
}; };
class NFTokenBurn2_test : public NFTokenBurn0_test class NFTokenBurnWOFixTokenRemint_test : public NFTokenBurnBaseUtil_test
{ {
public: public:
void void
run() override run() override
{ {
NFTokenBurn0_test::run(2); NFTokenBurnBaseUtil_test::run(2);
} }
}; };
class NFTokenBurn3_test : public NFTokenBurn0_test class NFTokenBurnAllFeatures_test : public NFTokenBurnBaseUtil_test
{ {
public: public:
void void
run() override run() override
{ {
NFTokenBurn0_test::run(3, true); NFTokenBurnBaseUtil_test::run(3, true);
} }
}; };
BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn0, tx, ripple, 3); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurnBaseUtil, tx, ripple, 3);
BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn1, tx, ripple, 3); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurnWOfixFungTokens, tx, ripple, 3);
BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn2, tx, ripple, 3); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurnWOFixTokenRemint, tx, ripple, 3);
BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn3, tx, ripple, 3); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurnAllFeatures, tx, ripple, 3);
} // namespace ripple } // namespace ripple

View File

@@ -27,7 +27,7 @@
namespace ripple { namespace ripple {
class NFToken0_test : public beast::unit_test::suite class NFTokenBaseUtil_test : public beast::unit_test::suite
{ {
FeatureBitset const disallowIncoming{featureDisallowIncoming}; FeatureBitset const disallowIncoming{featureDisallowIncoming};
@@ -6863,46 +6863,46 @@ public:
} }
}; };
class NFToken1_test : public NFToken0_test class NFTokenDisallowIncoming_test : public NFTokenBaseUtil_test
{ {
void void
run() override run() override
{ {
NFToken0_test::run(1); NFTokenBaseUtil_test::run(1);
} }
}; };
class NFToken2_test : public NFToken0_test class NFTokenWOfixV1_test : public NFTokenBaseUtil_test
{ {
void void
run() override run() override
{ {
NFToken0_test::run(2); NFTokenBaseUtil_test::run(2);
} }
}; };
class NFToken3_test : public NFToken0_test class NFTokenWOTokenRemint_test : public NFTokenBaseUtil_test
{ {
void void
run() override run() override
{ {
NFToken0_test::run(3); NFTokenBaseUtil_test::run(3);
} }
}; };
class NFToken4_test : public NFToken0_test class NFTokenAllFeatures_test : public NFTokenBaseUtil_test
{ {
void void
run() override run() override
{ {
NFToken0_test::run(4, true); NFTokenBaseUtil_test::run(4, true);
} }
}; };
BEAST_DEFINE_TESTSUITE_PRIO(NFToken0, tx, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBaseUtil, tx, ripple, 2);
BEAST_DEFINE_TESTSUITE_PRIO(NFToken1, tx, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenDisallowIncoming, tx, ripple, 2);
BEAST_DEFINE_TESTSUITE_PRIO(NFToken2, tx, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOfixV1, tx, ripple, 2);
BEAST_DEFINE_TESTSUITE_PRIO(NFToken3, tx, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOTokenRemint, tx, ripple, 2);
BEAST_DEFINE_TESTSUITE_PRIO(NFToken4, tx, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(NFTokenAllFeatures, tx, ripple, 2);
} // namespace ripple } // namespace ripple

View File

@@ -27,7 +27,7 @@
namespace ripple { namespace ripple {
namespace test { namespace test {
class Offer0_test : public beast::unit_test::suite class OfferBaseUtil_test : public beast::unit_test::suite
{ {
XRPAmount XRPAmount
reserve(jtx::Env& env, std::uint32_t count) reserve(jtx::Env& env, std::uint32_t count)
@@ -5371,52 +5371,52 @@ public:
} }
}; };
class Offer1_test : public Offer0_test class OfferWOFlowCross_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
{ {
Offer0_test::run(1); OfferBaseUtil_test::run(1);
} }
}; };
class Offer2_test : public Offer0_test class OfferWTakerDryOffer_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
{ {
Offer0_test::run(2); OfferBaseUtil_test::run(2);
} }
}; };
class Offer3_test : public Offer0_test class OfferWOSmallQOffers_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
{ {
Offer0_test::run(3); OfferBaseUtil_test::run(3);
} }
}; };
class Offer4_test : public Offer0_test class OfferWOFillOrKill_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
{ {
Offer0_test::run(4); OfferBaseUtil_test::run(4);
} }
}; };
class Offer5_test : public Offer0_test class OfferAllFeatures_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
{ {
Offer0_test::run(5, true); OfferBaseUtil_test::run(5, true);
} }
}; };
class Offer_manual_test : public Offer0_test class Offer_manual_test : public OfferBaseUtil_test
{ {
void void
run() override run() override
@@ -5439,12 +5439,12 @@ class Offer_manual_test : public Offer0_test
} }
}; };
BEAST_DEFINE_TESTSUITE_PRIO(Offer0, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferBaseUtil, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_PRIO(Offer1, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferWOFlowCross, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_PRIO(Offer2, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferWTakerDryOffer, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_PRIO(Offer3, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferWOSmallQOffers, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_PRIO(Offer4, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferWOFillOrKill, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_PRIO(Offer5, tx, ripple, 4); BEAST_DEFINE_TESTSUITE_PRIO(OfferAllFeatures, tx, ripple, 4);
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Offer_manual, tx, ripple, 20); BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Offer_manual, tx, ripple, 20);
} // namespace test } // namespace test

View File

@@ -35,7 +35,7 @@ namespace ripple {
namespace test { namespace test {
class TxQ1_test : public beast::unit_test::suite class TxQPosNegFlows_test : public beast::unit_test::suite
{ {
void void
checkMetrics( checkMetrics(
@@ -4949,7 +4949,7 @@ public:
} }
void void
run2() runMetaInfo()
{ {
testAcctInQueueButEmpty(); testAcctInQueueButEmpty();
testRPC(); testRPC();
@@ -4970,17 +4970,17 @@ public:
} }
}; };
class TxQ2_test : public TxQ1_test class TxQMetaInfo_test : public TxQPosNegFlows_test
{ {
void void
run() override run() override
{ {
run2(); runMetaInfo();
} }
}; };
BEAST_DEFINE_TESTSUITE_PRIO(TxQ1, app, ripple, 1); BEAST_DEFINE_TESTSUITE_PRIO(TxQPosNegFlows, app, ripple, 1);
BEAST_DEFINE_TESTSUITE_PRIO(TxQ2, app, ripple, 1); BEAST_DEFINE_TESTSUITE_PRIO(TxQMetaInfo, app, ripple, 1);
} // namespace test } // namespace test
} // namespace ripple } // namespace ripple